From 6ca5f2e4e77c5d5418a57811790f6ddf6b675f8f Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Mon, 6 Jul 2009 21:41:29 +0000 Subject: [PATCH] Utilities for creating magical mapping functions that use reflection. --- .../samskivert/depot/util/RuntimeUtil.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/java/com/samskivert/depot/util/RuntimeUtil.java diff --git a/src/java/com/samskivert/depot/util/RuntimeUtil.java b/src/java/com/samskivert/depot/util/RuntimeUtil.java new file mode 100644 index 0000000..9870731 --- /dev/null +++ b/src/java/com/samskivert/depot/util/RuntimeUtil.java @@ -0,0 +1,103 @@ +// +// $Id$ +// +// Depot library - a Java relational persistence library +// Copyright (C) 2006-2009 Michael Bayne and Pär Winzell +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.depot.util; + +import java.lang.reflect.Field; + +import com.google.common.base.Function; + +import com.samskivert.depot.PersistentRecord; + +/** + * Creates functions that map persistent records to runtime counterparts and vice versa. + */ +public class RuntimeUtil +{ + /** + * Creates a function that creates an instance of R and initializes all accessible (ie. public) + * fields of R from fields of P with matching name. Fields of P that do not exist in R will be + * ignored. Note: the types of the fields must match exactly. + */ + public static

Function makeToRuntime ( + Class

pclass, final Class rclass) + { + final Field[] rfields = rclass.getFields(); + final Field[] pfields = getPersistentFields(pclass, rfields); + return new Function() { + public R apply (P record) { + try { + R object = rclass.newInstance(); + for (int ii = 0, ll = rfields.length; ii < ll; ii++) { + rfields[ii].set(object, pfields[ii].get(record)); + } + return object; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + /** + * Creates a function that creates an instance of P and initializes all accessible (ie. public) + * fields of P from fields of R with matching name. Fields of P that do not exist in R will be + * left as default. Note: the types of the fields must match exactly. + */ + public static Function makeToRecord ( + Class rclass, final Class

pclass) + { + final Field[] rfields = rclass.getFields(); + final Field[] pfields = getPersistentFields(pclass, rfields); + return new Function() { + public P apply (R object) { + try { + P record = pclass.newInstance(); + for (int ii = 0, ll = rfields.length; ii < ll; ii++) { + pfields[ii].set(record, rfields[ii].get(object)); + } + return record; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }; + } + + protected static Field[] getPersistentFields ( + Class pclass, Field[] rfields) + { + Field[] pfields = new Field[rfields.length]; + for (int ii = 0; ii < rfields.length; ii++) { + try { + pfields[ii] = pclass.getField(rfields[ii].getName()); + } catch (NoSuchFieldException nsfe) { + throw new IllegalArgumentException( + "Cannot create mapping for " + rfields[ii] + ". " + + "No corresponding field exists in " + pclass + "."); + } + if (!pfields[ii].getType().equals(rfields[ii].getType())) { + throw new IllegalArgumentException("Cannot create mapping from " + pfields[ii] + + " to " + rfields[ii] + "."); + } + } + return pfields; + } +}