You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2012/12/06 17:59:48 UTC

[48/52] [partial] ISIS-188: more reorganizing of artifacts into physical directories.

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyCollectionMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyCollectionMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyCollectionMapper.java
new file mode 100644
index 0000000..6561038
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyCollectionMapper.java
@@ -0,0 +1,379 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.sql.auto;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.CollectionMapper;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.FieldMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.IdMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.IdMappingAbstract;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Sql;
+import org.apache.isis.runtimes.dflt.objectstores.sql.VersionMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.ObjectReferenceMapping;
+import org.apache.isis.runtimes.dflt.runtime.persistence.PersistorUtil;
+
+/**
+ * Stores 1-to-many collections by creating a foreign-key column in the table
+ * for the incoming objectAssociation class. This assumes this the class is only
+ * ever in 1 collection parent.
+ * 
+ * @version $Rev$ $Date$
+ */
+public class ForeignKeyCollectionMapper extends AbstractAutoMapper implements CollectionMapper {
+    private static final Logger LOG = Logger.getLogger(ForeignKeyCollectionMapper.class);
+    private final ObjectAssociation field;
+    private final IdMapping idMapping;
+    private final VersionMapping versionMapping;
+    private final ObjectReferenceMapping foreignKeyMapping;
+    private String foreignKeyName;
+    private String columnName;
+    private final ObjectMappingLookup objectMapperLookup2;
+
+    private ObjectMapping originalMapping = null;
+
+    public ForeignKeyCollectionMapper(final ObjectAssociation objectAssociation, final String parameterBase, final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup) {
+        super(objectAssociation.getSpecification().getFullIdentifier(), parameterBase, lookup, objectMapperLookup);
+
+        this.field = objectAssociation;
+
+        objectMapperLookup2 = objectMapperLookup;
+
+        idMapping = lookup.createIdMapping();
+        versionMapping = lookup.createVersionMapping();
+
+        setColumnName(determineColumnName(objectAssociation));
+        foreignKeyName = Sql.sqlName("fk_" + getColumnName());
+
+        foreignKeyName = Sql.identifier(foreignKeyName);
+        foreignKeyMapping = lookup.createMapping(columnName, specification);
+    }
+
+    protected ForeignKeyCollectionMapper(final FieldMappingLookup lookup, final AbstractAutoMapper abstractAutoMapper, final ObjectAssociation field) {
+        super(lookup, abstractAutoMapper, field.getSpecification().getFullIdentifier());
+
+        this.field = field;
+        objectMapperLookup2 = null;
+
+        idMapping = lookup.createIdMapping();
+        versionMapping = lookup.createVersionMapping();
+
+        setColumnName(determineColumnName(field));
+        foreignKeyName = Sql.sqlName("fk_" + getColumnName());
+
+        foreignKeyName = Sql.identifier(foreignKeyName);
+        foreignKeyMapping = lookup.createMapping(columnName, specification);
+    }
+
+    protected String determineColumnName(final ObjectAssociation objectAssociation) {
+        return objectAssociation.getSpecification().getShortIdentifier();
+    }
+
+    public String getColumnName() {
+        return columnName;
+    }
+
+    public void setColumnName(final String columnName) {
+        this.columnName = columnName;
+    }
+
+    protected VersionMapping getVersionMapping() {
+        return versionMapping;
+    }
+
+    protected ObjectReferenceMapping getForeignKeyMapping() {
+        return foreignKeyMapping;
+    }
+
+    protected String getForeignKeyName() {
+        return foreignKeyName;
+    }
+
+    @Override
+    public void startup(final DatabaseConnector connector) {
+        if (originalMapping == null) {
+            originalMapping = objectMappingLookup.getMapping(specification, null);
+        }
+        originalMapping.startup(connector, objectMapperLookup2);
+        super.startup(connector);
+    }
+
+    @Override
+    public boolean needsTables(final DatabaseConnector connection) {
+        return !connection.hasColumn(table, foreignKeyName);
+    }
+
+    @Override
+    public void createTables(final DatabaseConnector connection) {
+        if (connection.hasTable(table)) {
+            final StringBuffer sql = new StringBuffer();
+            sql.append("alter table ");
+            sql.append(table);
+            sql.append(" add ");
+            appendColumnDefinitions(sql);
+            connection.update(sql.toString());
+        } else {
+            final StringBuffer sql = new StringBuffer();
+            sql.append("create table ");
+            sql.append(table);
+            sql.append(" (");
+            idMapping.appendCreateColumnDefinitions(sql);
+            sql.append(", ");
+
+            appendColumnDefinitions(sql);
+
+            // for (final FieldMapping mapping : fieldMappings) {
+            // mapping.appendColumnDefinitions(sql);
+            // sql.append(",");
+            // }
+            // sql.append(versionMapping.appendColumnDefinitions());
+            sql.append(")");
+            connection.update(sql.toString());
+        }
+    }
+
+    public IdMappingAbstract getIdMapping() {
+        return idMapping;
+    }
+
+    protected void appendCollectionUpdateColumnsToNull(final StringBuffer sql) {
+        sql.append(foreignKeyName + "=NULL ");
+    }
+
+    protected void appendCollectionWhereValues(final DatabaseConnector connector, final ObjectAdapter parent, final StringBuffer sql) {
+        foreignKeyMapping.appendUpdateValues(connector, sql, parent);
+    }
+
+    protected void appendCollectionUpdateValues(final DatabaseConnector connector, final ObjectAdapter parent, final StringBuffer sql) {
+        appendCollectionWhereValues(connector, parent, sql);
+    }
+
+    protected void appendColumnDefinitions(final StringBuffer sql) {
+        foreignKeyMapping.appendColumnDefinitions(sql);
+    }
+
+    @Override
+    public void loadInternalCollection(final DatabaseConnector connector, final ObjectAdapter parentAdapter) {
+
+        final ObjectAdapter collectionAdapter = field.get(parentAdapter);
+        if (!collectionAdapter.canTransitionToResolving()) {
+            return;
+        } 
+        
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("loading internal collection " + field);
+        }
+        final List<ObjectAdapter> list = new ArrayList<ObjectAdapter>();
+        try {
+            PersistorUtil.startResolving(collectionAdapter);
+            
+            loadCollectionIntoList(connector, parentAdapter, table, specification, getIdMapping(), fieldMappingByField, versionMapping, list);
+            
+            final CollectionFacet collectionFacet = collectionAdapter.getSpecification().getFacet(CollectionFacet.class);
+            collectionFacet.init(collectionAdapter, list.toArray(new ObjectAdapter[list.size()]));
+            
+        } finally {
+            PersistorUtil.toEndState(collectionAdapter);
+        }
+
+        // TODO: Need to finalise this behaviour. At the moment, all
+        // collections will get infinitely resolved. I
+        // don't think this is desirable.
+        for (final ObjectAdapter field : list) {
+            // final ObjectMapping mapping =
+            // objectMappingLookup.getMapping(field, connector);
+            if (field.getSpecification().isOfType(parentAdapter.getSpecification())) {
+                loadInternalCollection(connector, field);
+            }
+        }
+    }
+
+    protected void loadCollectionIntoList(final DatabaseConnector connector, final ObjectAdapter parent, final String table, final ObjectSpecification specification, final IdMappingAbstract idMappingAbstract, final Map<ObjectAssociation, FieldMapping> fieldMappingByField, final VersionMapping versionMapping,
+            final List<ObjectAdapter> list) {
+
+        final StringBuffer sql = new StringBuffer();
+        sql.append("select ");
+        idMappingAbstract.appendColumnNames(sql);
+
+        sql.append(", ");
+        final String columnList = columnList(fieldMappingByField);
+        if (columnList.length() > 0) {
+            sql.append(columnList);
+            sql.append(", ");
+        }
+        sql.append(versionMapping.appendColumnNames());
+        sql.append(" from ");
+        sql.append(table);
+        sql.append(" where ");
+        appendCollectionWhereValues(connector, parent, sql);
+
+        final Results rs = connector.select(sql.toString());
+        while (rs.next()) {
+            final Oid oid = idMappingAbstract.recreateOid(rs, specification);
+            final ObjectAdapter element = getAdapter(specification, oid);
+            loadFields(element, rs, fieldMappingByField);
+            LOG.debug("  element  " + element.getOid());
+            list.add(element);
+        }
+        rs.close();
+    }
+
+    protected void loadFields(final ObjectAdapter adapter, final Results rs, final Map<ObjectAssociation, FieldMapping> fieldMappingByField) {
+        if (!adapter.canTransitionToResolving()) {
+            return;
+        }
+
+        try {
+            PersistorUtil.startResolving(adapter);
+            for (final FieldMapping mapping : fieldMappingByField.values()) {
+                mapping.initializeField(adapter, rs);
+            }
+            adapter.setVersion(versionMapping.getLock(rs));
+        } finally {
+            PersistorUtil.toEndState(adapter);
+        }
+    }
+
+    /**
+     * Override this in the Polymorphic case to return just the elements that
+     * are appropriate for the subclass currently being handled.
+     * 
+     * @param collection
+     * @return those elements that ought to be used.
+     */
+    protected Iterator<ObjectAdapter> getElementsForCollectionAsIterator(final ObjectAdapter collection) {
+        final CollectionFacet collectionFacet = collection.getSpecification().getFacet(CollectionFacet.class);
+        final Iterable<ObjectAdapter> elements = collectionFacet.iterable(collection);
+        return elements.iterator();
+    }
+
+    @Override
+    public void saveInternalCollection(final DatabaseConnector connector, final ObjectAdapter parent) {
+        final ObjectAdapter collection = field.get(parent);
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("Saving internal collection " + collection);
+        }
+
+        final Iterator<ObjectAdapter> elements = getElementsForCollectionAsIterator(collection);
+
+        // TODO What is needed to allow a collection update (add/remove) to mark
+        // the collection as dirty?
+        // checkIfDirty(collection);
+
+        if (elements.hasNext() == false) {
+            return;
+        }
+
+        clearCollectionParent(connector, parent);
+
+        resetCollectionParent(connector, parent, elements);
+    }
+
+    protected void clearCollectionParent(final DatabaseConnector connector, final ObjectAdapter parent) {
+        // Delete collection parent
+        final StringBuffer sql = new StringBuffer();
+        sql.append("update ");
+        sql.append(table);
+        sql.append(" set ");
+        appendCollectionUpdateColumnsToNull(sql);
+        sql.append(" where ");
+        appendCollectionWhereValues(connector, parent, sql);
+        connector.update(sql.toString());
+    }
+
+    protected void resetCollectionParent(final DatabaseConnector connector, final ObjectAdapter parent, final Iterator<ObjectAdapter> elements) {
+        // Reinstall collection parent
+        final StringBuffer update = new StringBuffer();
+        update.append("update ");
+        update.append(table);
+        update.append(" set ");
+        appendCollectionUpdateValues(connector, parent, update);
+        update.append(" where ");
+
+        idMapping.appendColumnNames(update);
+
+        update.append(" IN (");
+
+        int count = 0;
+        for (final Iterator<ObjectAdapter> iterator = elements; iterator.hasNext();) {
+            final ObjectAdapter element = iterator.next();
+
+            if (count++ > 0) {
+                update.append(",");
+            }
+            final RootOid elementOid = (RootOid) element.getOid();
+            idMapping.appendObjectId(connector, update, elementOid);
+        }
+        update.append(")");
+        if (count > 0) {
+            connector.insert(update.toString());
+        }
+    }
+
+    protected void checkIfDirty(final ObjectAdapter collection) {
+        // Test: is dirty?
+        final ObjectSpecification collectionSpecification = collection.getSpecification();
+        if (collectionSpecification.isDirty(collection)) {
+            LOG.debug(collection.getOid() + " is dirty");
+        } else {
+            LOG.debug(collection.getOid() + " is clean");
+        }
+
+        final CollectionFacet collectionFacetD = collection.getSpecification().getFacet(CollectionFacet.class);
+        for (final ObjectAdapter element : collectionFacetD.iterable(collection)) {
+            if (collectionSpecification.isDirty(element)) {
+                LOG.debug(element.getOid() + " is dirty");
+            } else {
+                LOG.debug(element.getOid() + " is clean");
+            }
+        }
+    }
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln(field.getName(), "collection");
+        debug.indent();
+        debug.appendln("Foreign key name", foreignKeyName);
+        debug.appendln("Foreign key mapping", foreignKeyMapping);
+        debug.appendln("ID mapping", idMapping);
+        debug.appendln("Version mapping", versionMapping);
+        debug.appendln("Original mapping", originalMapping);
+        debug.unindent();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyInChildCollectionMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyInChildCollectionMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyInChildCollectionMapper.java
new file mode 100644
index 0000000..e333d7b
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ForeignKeyInChildCollectionMapper.java
@@ -0,0 +1,88 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+/**
+ * 
+ */
+package org.apache.isis.runtimes.dflt.objectstores.sql.auto;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.specloader.specimpl.OneToManyAssociationImpl;
+import org.apache.isis.runtimes.dflt.objectstores.sql.FieldMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMappingLookup;
+
+/**
+ * Used to map 1-to-many collections by creating, in the child table, 1 column
+ * per parent collection. The column is named by combining the final part of the
+ * parent class name and the collection variable name.
+ * 
+ * @author Kevin
+ */
+public class ForeignKeyInChildCollectionMapper extends ForeignKeyCollectionMapper {
+    private static final Logger LOG = Logger.getLogger(ForeignKeyCollectionMapper.class);
+
+    protected final ObjectAssociation priorField; // prevents recursion
+    protected final List<ObjectAssociation> priorFields;
+
+    public ForeignKeyInChildCollectionMapper(final ObjectAssociation objectAssociation, final String parameterBase, final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup, final AbstractAutoMapper abstractAutoMapper, final ObjectAssociation field) {
+        super(objectAssociation, parameterBase, lookup, objectMapperLookup);
+
+        priorFields = abstractAutoMapper.fields;
+        priorField = field;
+
+        setUpFieldMappers();
+    }
+
+    protected ForeignKeyInChildCollectionMapper(final FieldMappingLookup lookup, final AbstractAutoMapper abstractAutoMapper, final ObjectAssociation field) {
+        super(lookup, abstractAutoMapper, field);
+        priorFields = null;
+        priorField = null;
+    }
+
+    @Override
+    protected void getExtraFields(final List<ObjectAssociation> existingFields) {
+        if (priorFields != null) {
+            for (final ObjectAssociation priorField1 : priorFields) {
+                if (existingFields.contains(priorField1) == false) {
+                    existingFields.add(priorField1);
+                } else {
+                    LOG.debug("Skipping prior field: " + priorField1.getName());
+                }
+            }
+        }
+    }
+
+    @Override
+    protected String determineColumnName(final ObjectAssociation objectAssociation) {
+        if (objectAssociation instanceof OneToManyAssociationImpl) {
+            final OneToManyAssociationImpl fkAssoc = (OneToManyAssociationImpl) objectAssociation;
+            final FacetedMethod peer = fkAssoc.getFacetedMethod();
+            final String fullClassName = peer.getIdentifier().getClassName();
+            final int lastPos = fullClassName.lastIndexOf('.');
+            return fullClassName.substring(lastPos + 1) + "_" + fkAssoc.getId();
+        } else {
+            return objectAssociation.getSpecification().getShortIdentifier();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionBaseMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionBaseMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionBaseMapper.java
new file mode 100755
index 0000000..b6223d0
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionBaseMapper.java
@@ -0,0 +1,233 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+/**
+ * 
+ */
+package org.apache.isis.runtimes.dflt.objectstores.sql.auto;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Defaults;
+import org.apache.isis.runtimes.dflt.objectstores.sql.FieldMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.IdMappingAbstract;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Sql;
+import org.apache.isis.runtimes.dflt.objectstores.sql.VersionMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.JdbcPolymorphicObjectReferenceMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.OidGenerator;
+
+/**
+ * Used to map 1-to-many collections by creating, in the collection child table
+ * (which may be an interface or abstract class), 2 columns per parent
+ * collection. The first column is the class type, the second is the entity ID.
+ * The columns are named by combining the final part of the parent class name
+ * and the collection variable name.
+ * 
+ * You have a choice between this class and
+ * {@link PolymorphicForeignKeyInChildCollectionMapper}
+ * 
+ * @author Kevin
+ */
+public class PolymorphicForeignKeyInChildCollectionBaseMapper extends ForeignKeyInChildCollectionMapper {
+
+    private static final Logger LOG = Logger.getLogger(PolymorphicForeignKeyInChildCollectionBaseMapper.class);
+
+    private final String classColumnName;
+    private final String itemIdColumnName;
+    private final IdMappingAbstract polyIdMapper;
+
+    private final OidGenerator oidGenerator;
+
+    public PolymorphicForeignKeyInChildCollectionBaseMapper(final ObjectAssociation objectAssociation, final String parameterBase, final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup, final AbstractAutoMapper abstractAutoMapper, final ObjectAssociation field) {
+
+        super(objectAssociation, parameterBase, lookup, objectMapperLookup, abstractAutoMapper, field);
+
+        classColumnName = Sql.identifier(Sql.sqlName(getForeignKeyName() + "_cls"));
+        itemIdColumnName = Sql.identifier("item_id");
+
+        polyIdMapper = new JdbcPolymorphicObjectReferenceMapping(itemIdColumnName);
+        oidGenerator = IsisContext.getPersistenceSession().getOidGenerator();
+    }
+
+    @Override
+    public boolean needsTables(final DatabaseConnector connection) {
+        return super.needsTables(connection) || !connection.hasColumn(table, classColumnName);
+    }
+
+    @Override
+    public void createTables(final DatabaseConnector connection) {
+        if (super.needsTables(connection)) {
+            super.createTables(connection);
+        }
+
+        if (!connection.hasColumn(table, classColumnName)) {
+            addColumn(connection, classColumnName, Defaults.TYPE_LONG_STRING());
+            addColumn(connection, itemIdColumnName, Defaults.TYPE_PK());
+        }
+    }
+
+    protected void addColumn(final DatabaseConnector connection, final String columnName, final String columnType) {
+        final StringBuffer sql = new StringBuffer();
+        sql.append("alter table ");
+        sql.append(table);
+        sql.append(" add ");
+        sql.append(columnName);
+        sql.append(" ");
+        sql.append(columnType);
+        connection.update(sql.toString());
+    }
+
+    @Override
+    protected void appendCollectionUpdateColumnsToNull(final StringBuffer sql) {
+        super.appendCollectionUpdateColumnsToNull(sql);
+        sql.append(", " + classColumnName + "=NULL ");
+    }
+
+    @Override
+    protected void appendCollectionUpdateValues(final DatabaseConnector connector, final ObjectAdapter parent, final StringBuffer sql) {
+        super.appendCollectionUpdateValues(connector, parent, sql);
+    }
+
+    @Override
+    protected void appendColumnDefinitions(final StringBuffer sql) {
+        super.appendColumnDefinitions(sql);
+    }
+
+    @Override
+    protected void clearCollectionParent(final DatabaseConnector connector, final ObjectAdapter parent) {
+        // Delete collection parent
+        final StringBuffer sql = new StringBuffer();
+        sql.append("DELETE FROM ");
+        sql.append(table);
+        sql.append(" WHERE ");
+        appendCollectionWhereValues(connector, parent, sql);
+        connector.update(sql.toString());
+    }
+
+    @Override
+    protected void resetCollectionParent(final DatabaseConnector connector, final ObjectAdapter parent, final Iterator<ObjectAdapter> elements) {
+        LOG.debug("Saving polymorphic list");
+
+        ObjectSpecification elementSpecification;
+        while (elements.hasNext()) {
+            final ObjectAdapter thisAdapter = elements.next();
+            elementSpecification = thisAdapter.getSpecification();
+
+            // Reinstall collection parent
+            final StringBuffer update = new StringBuffer();
+            update.append("INSERT INTO ");
+            update.append(table);
+            update.append(" (");
+            // list of column names
+            super.getIdMapping().appendColumnNames(update);
+            update.append("," + getForeignKeyName());
+            update.append(", " + itemIdColumnName);
+            update.append("," + classColumnName);
+            update.append(") VALUES (");
+
+            // Row ID column
+            final Object pojo = thisAdapter.getObject();
+            final RootOid transientRootOid = oidGenerator.createTransientOid(pojo);
+            
+            final RootOid persistentRootOid = oidGenerator.createPersistent(pojo, transientRootOid);
+            
+            polyIdMapper.appendObjectId(connector, update, persistentRootOid);
+            
+            // polyIdMapper.appendObjectId(connector, update,
+            // thisAdapter.getOid());
+            update.append(",");
+
+            // Foreign key ID column
+            getForeignKeyMapping().appendInsertValues(connector, update, parent);
+            update.append(",");
+
+            // item Id column
+            final RootOid oid = (RootOid) thisAdapter.getOid();
+            getIdMapping().appendObjectId(connector, update, oid);
+
+            // Class name column
+            update.append(",?)");
+            connector.addToQueryValues(elementSpecification.getFullIdentifier());
+
+            connector.insert(update.toString());
+        }
+    }
+
+    @Override
+    public IdMappingAbstract getIdMapping() {
+        return polyIdMapper;
+    }
+
+    @Override
+    protected void loadCollectionIntoList(final DatabaseConnector connector, final ObjectAdapter parent, final String table, final ObjectSpecification specification, final IdMappingAbstract idMappingAbstract, final Map<ObjectAssociation, FieldMapping> fieldMappingByField, final VersionMapping versionMapping,
+            final List<ObjectAdapter> list) {
+        LOG.debug("Loading polymorphic list");
+
+        final StringBuffer sql = new StringBuffer();
+        sql.append("select ");
+        super.getIdMapping().appendColumnNames(sql);
+
+        sql.append("," + getForeignKeyName());
+        sql.append("," + classColumnName);
+        sql.append("," + itemIdColumnName);
+
+        sql.append(" from ");
+        sql.append(table);
+        sql.append(" where ");
+        appendCollectionWhereValues(connector, parent, sql);
+
+        final Results rs = connector.select(sql.toString());
+
+        final SpecificationLoaderSpi reflector = IsisContext.getSpecificationLoader();
+        final JdbcPolymorphicObjectReferenceMapping idMapping = (JdbcPolymorphicObjectReferenceMapping) idMappingAbstract;
+
+        while (rs.next()) {
+            final ObjectSpecification itemSpecification = reflector.loadSpecification(rs.getString(classColumnName));
+            idMapping.setObjectSpecification(itemSpecification);
+
+            // Load new recordSet for the actual class
+            final ObjectMapping itemMapper = objectMappingLookup.getMapping(itemSpecification, connector);
+            final TypedOid oid = idMapping.recreateOid(rs, itemSpecification);
+            final ObjectAdapter loadedObject = itemMapper.getObject(connector, oid);
+
+            LOG.debug("  element  " + loadedObject.getOid());
+
+            list.add(loadedObject);
+        }
+        rs.close();
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionMapper.java
new file mode 100755
index 0000000..eac2f22
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/PolymorphicForeignKeyInChildCollectionMapper.java
@@ -0,0 +1,204 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+/**
+ * 
+ */
+package org.apache.isis.runtimes.dflt.objectstores.sql.auto;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.FieldMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.IdMappingAbstract;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.VersionMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Used to map 1-to-many collections by creating, in the child table, 1 column
+ * per parent collection. The column is named by combining the final part of the
+ * parent class name and the collection variable name.
+ * 
+ * You have a choice between this class and
+ * {@link PolymorphicForeignKeyInChildCollectionBaseMapper}
+ * 
+ * @author Kevin
+ */
+public class PolymorphicForeignKeyInChildCollectionMapper extends ForeignKeyInChildCollectionMapper {
+
+    private static final Logger LOG = Logger.getLogger(PolymorphicForeignKeyInChildCollectionMapper.class);
+
+    private final ObjectAssociation baseField;
+    private final List<String> tables;
+    private final List<ObjectSpecification> tableSpecifications;
+    private final List<ObjectMapping> subClassMappers;
+
+    // For iterating through the subclasses
+    private ObjectSpecification currentTableSpecification;
+    private Iterator<ObjectAdapter> currentIterator;
+    private List<ObjectAdapter> currentCollection;
+    private int currentIndexStart;
+    private int currentIndex;
+
+    // Store for passing on to other mappers
+    final String parameterBase;
+    final FieldMappingLookup lookup;
+    final ObjectMappingLookup objectMapperLookup;
+    final String fieldClassName;
+
+    public PolymorphicForeignKeyInChildCollectionMapper(final ObjectAssociation objectAssociation, final String parameterBase, final FieldMappingLookup lookup, final ObjectMappingLookup objectMapperLookup, final AbstractAutoMapper abstractAutoMapper, final ObjectAssociation field) {
+
+        super(lookup, abstractAutoMapper, field);
+
+        fieldClassName = className;
+
+        baseField = objectAssociation;
+        tables = new ArrayList<String>();
+        tableSpecifications = new ArrayList<ObjectSpecification>();
+        subClassMappers = new ArrayList<ObjectMapping>();
+
+        // Capture for use in creating subclass mappers.
+        this.parameterBase = parameterBase;
+        this.lookup = lookup;
+        this.objectMapperLookup = objectMapperLookup;
+
+        addSubSpecificationsToTable(specification);
+    }
+
+    protected void addSubSpecificationsToTable(final ObjectSpecification objectSpecification) {
+        if (objectSpecification.isAbstract() == false) {
+            final String tableNameFromSpecification = getTableNameFromSpecification(objectSpecification);
+            tables.add(tableNameFromSpecification);
+            tableSpecifications.add(objectSpecification);
+
+            final ObjectMapping autoMapper = objectMapperLookup.getMapping(objectSpecification, null);
+            subClassMappers.add(autoMapper);
+        }
+        if (objectSpecification.hasSubclasses()) {
+            for (final ObjectSpecification subSpecification : objectSpecification.subclasses()) {
+                addSubSpecificationsToTable(subSpecification);
+            }
+        }
+    }
+
+    @Override
+    public boolean needsTables(final DatabaseConnector connection) {
+        for (final String subTableName : tables) {
+            table = subTableName;
+            if (super.needsTables(connection)) {
+                // Stop on first table that is needed.
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void createTables(final DatabaseConnector connection) {
+        for (final String subTableName : tables) {
+            table = subTableName;
+            if (super.needsTables(connection)) {
+                super.createTables(connection);
+            }
+        }
+    }
+
+    @Override
+    protected Iterator<ObjectAdapter> getElementsForCollectionAsIterator(final ObjectAdapter collection) {
+        return currentIterator;
+    }
+
+    @Override
+    public void saveInternalCollection(final DatabaseConnector connector, final ObjectAdapter parent) {
+        final ObjectAdapter collection = baseField.get(parent);
+        LOG.debug("Saving polymorphic internal collection " + collection);
+
+        currentCollection = new ArrayList<ObjectAdapter>();
+        currentIterator = super.getElementsForCollectionAsIterator(collection);
+        for (; currentIterator.hasNext();) {
+            final ObjectAdapter item = currentIterator.next();
+            currentCollection.add(item);
+        }
+
+        for (int i = 0; i < tables.size(); i++) {
+            currentTableSpecification = tableSpecifications.get(i);
+            currentIndex = 0;
+            currentIndexStart = 0;
+
+            currentIterator = new Iterator<ObjectAdapter>() {
+                @Override
+                public boolean hasNext() {
+                    for (int i = currentIndexStart; i < currentCollection.size(); i++) {
+                        final ObjectAdapter thisObjectAdapter = currentCollection.get(i);
+                        if (thisObjectAdapter.getSpecification().isOfType(currentTableSpecification)) {
+                            currentIndexStart = currentIndex = i;
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+
+                @Override
+                public ObjectAdapter next() {
+                    currentIndexStart = currentIndex + 1;
+                    return currentCollection.get(currentIndex);
+                }
+
+                @Override
+                public void remove() {
+                }
+            };
+
+            // Provide replacement table and column definitions here
+            table = tables.get(i);
+            super.saveInternalCollection(connector, parent);
+        }
+    }
+
+    @Override
+    protected void loadCollectionIntoList(final DatabaseConnector connector, final ObjectAdapter parent, final String table, final ObjectSpecification specification, final IdMappingAbstract idMappingAbstract, final Map<ObjectAssociation, FieldMapping> fieldMappingByField, final VersionMapping versionMapping,
+            final List<ObjectAdapter> superList) {
+        final List<ObjectAdapter> list = Lists.newArrayList();
+        
+        for (int i = 0; i < tables.size(); i++) {
+            currentTableSpecification = tableSpecifications.get(i);
+            final AutoMapper mapper = (AutoMapper) subClassMappers.get(i);
+            final String mapperTable = tables.get(i);
+
+            super.loadCollectionIntoList(connector, parent, mapperTable, currentTableSpecification, mapper.getIdMapping(), mapper.fieldMappingByField, mapper.getVersionMapping(), list);
+
+            superList.addAll(list);
+            list.clear();
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ReversedAutoAssociationMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ReversedAutoAssociationMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ReversedAutoAssociationMapper.java
new file mode 100644
index 0000000..913a5e4
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/auto/ReversedAutoAssociationMapper.java
@@ -0,0 +1,211 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.sql.auto;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.version.SerialNumberVersion;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.CollectionMapper;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.FieldMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.ObjectMappingLookup;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.VersionMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.ObjectReferenceMapping;
+import org.apache.isis.runtimes.dflt.runtime.persistence.PersistorUtil;
+
+/**
+ * used where there is a one to many association, and the elements are only
+ * known to parent
+ */
+public class ReversedAutoAssociationMapper extends AbstractAutoMapper implements CollectionMapper {
+    private static final Logger LOG = Logger.getLogger(ReversedAutoAssociationMapper.class);
+    private final ObjectAssociation field;
+    private final ObjectReferenceMapping idMapping;
+    private final VersionMapping versionMapping;
+
+    public ReversedAutoAssociationMapper(final String elemenType, final ObjectAssociation field, final String parameterBase, final FieldMappingLookup lookup, final ObjectMappingLookup objectLookup) {
+        super(elemenType, parameterBase, lookup, objectLookup);
+
+        this.field = field;
+
+        idMapping = lookup.createMapping(field.getSpecification());
+        versionMapping = lookup.createVersionMapping();
+
+        setUpFieldMappers();
+    }
+
+    @Override
+    public void createTables(final DatabaseConnector connection) {
+        if (!connection.hasTable(table)) {
+            final StringBuffer sql = new StringBuffer();
+            sql.append("create table ");
+            sql.append(table);
+            sql.append(" (");
+            idMapping.appendColumnDefinitions(sql);
+            sql.append(", ");
+            for (final FieldMapping mapping : fieldMappingByField.values()) {
+                mapping.appendColumnDefinitions(sql);
+                sql.append(",");
+            }
+            sql.append(versionMapping.appendColumnDefinitions());
+            sql.append(")");
+            connection.update(sql.toString());
+        }
+        for (int i = 0; collectionMappers != null && i < collectionMappers.length; i++) {
+            if (collectionMappers[i].needsTables(connection)) {
+                collectionMappers[i].createTables(connection);
+            }
+        }
+    }
+
+    @Override
+    public void loadInternalCollection(final DatabaseConnector connector, final ObjectAdapter parentAdapter) {
+        final ObjectAdapter collectionAdapter = field.get(parentAdapter);
+        if (!collectionAdapter.canTransitionToResolving()) {
+            return;
+        } 
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("loading internal collection " + field);
+        }
+        
+        try {
+            // added, since was missing (presumably an error given similarity with other 'Mapper' impls?)
+            PersistorUtil.startResolving(collectionAdapter);
+            
+            final StringBuffer sql = new StringBuffer();
+            sql.append("select ");
+            idMapping.appendColumnNames(sql);
+            sql.append(", ");
+            sql.append(columnList(fieldMappingByField));
+            sql.append(" from ");
+            sql.append(table);
+            sql.append(" where ");
+            idMapping.appendUpdateValues(connector, sql, parentAdapter);
+            
+            final Results rs = connector.select(sql.toString());
+            final List<ObjectAdapter> list = new ArrayList<ObjectAdapter>();
+            while (rs.next()) {
+                final Oid oid = idMapping.recreateOid(rs, specification);
+                final ObjectAdapter element = getAdapter(specification, oid);
+                loadFields(element, rs);
+                if(LOG.isDebugEnabled()) {
+                    LOG.debug("  element  " + element.getOid());
+                }
+                list.add(element);
+            }
+            final CollectionFacet collectionFacet = collectionAdapter.getSpecification().getFacet(CollectionFacet.class);
+            collectionFacet.init(collectionAdapter, list.toArray(new ObjectAdapter[list.size()]));
+            rs.close();
+        } finally {
+            PersistorUtil.toEndState(collectionAdapter);
+        }
+
+    }
+
+    protected void loadFields(final ObjectAdapter object, final Results rs) {
+        try {
+            PersistorUtil.startResolving(object);
+            for (final FieldMapping mapping : fieldMappingByField.values()) {
+                mapping.initializeField(object, rs);
+            }
+            /*
+             * for (int i = 0; i < oneToManyProperties.length; i++) { /* Need to set
+             * up collection to be a ghost before we access as below
+             */
+            // CollectionAdapter collection = (CollectionAdapter)
+            /*
+             * oneToManyProperties[i].get(object); }
+             */
+            
+            object.setVersion(versionMapping.getLock(rs));
+            
+        } finally {
+            PersistorUtil.toEndState(object);
+        }
+    }
+
+    @Override
+    public void saveInternalCollection(final DatabaseConnector connector, final ObjectAdapter parent) {
+        final ObjectAdapter collection = field.get(parent);
+        LOG.debug("Saving internal collection " + collection);
+
+        deleteAllElments(connector, parent);
+        reinsertElements(connector, parent, collection);
+    }
+
+    private void reinsertElements(final DatabaseConnector connector, final ObjectAdapter parent, final ObjectAdapter collection) {
+        final StringBuffer sql = new StringBuffer();
+        sql.append("insert into " + table + " (");
+        idMapping.appendColumnNames(sql);
+        sql.append(", ");
+        final String columnList = columnList(fieldMappingByField);
+        if (columnList.length() > 0) {
+            sql.append(columnList);
+            sql.append(", ");
+        }
+        sql.append(versionMapping.insertColumns());
+        sql.append(") values (");
+        idMapping.appendInsertValues(connector, sql, parent);
+        sql.append(", ");
+
+        final CollectionFacet collectionFacet = field.getFacet(CollectionFacet.class);
+        for (final ObjectAdapter element : collectionFacet.iterable(collection)) {
+            final StringBuffer insert = new StringBuffer(sql);
+            insert.append(values(connector, element));
+            final Version version = SerialNumberVersion.create(0, "", new Date());
+            insert.append(versionMapping.insertValues(connector, version));
+            insert.append(") ");
+
+            connector.insert(insert.toString());
+            element.setVersion(version);
+        }
+    }
+
+    private void deleteAllElments(final DatabaseConnector connector, final ObjectAdapter parent) {
+        final StringBuffer sql = new StringBuffer();
+        sql.append("delete from ");
+        sql.append(table);
+        sql.append(" where ");
+        idMapping.appendUpdateValues(connector, sql, parent);
+        connector.update(sql.toString());
+    }
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln(field.getName(), "collection");
+        debug.indent();
+        debug.appendln("ID mapping", idMapping);
+        debug.appendln("Version mapping", versionMapping);
+        debug.unindent();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcFieldMapping.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcFieldMapping.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcFieldMapping.java
new file mode 100644
index 0000000..b3830e5
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcFieldMapping.java
@@ -0,0 +1,111 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.sql.jdbc;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Sql;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+
+public abstract class AbstractJdbcFieldMapping implements FieldMapping {
+	
+    private final String columnName;
+    protected final ObjectAssociation field;
+
+    public AbstractJdbcFieldMapping(final ObjectAssociation field) {
+        this.field = field;
+        columnName = Sql.sqlFieldName(field.getId());
+    }
+
+    @Override
+    public ObjectAssociation getField() {
+    	return field;
+    }
+    
+    @Override
+    public void appendColumnDefinitions(final StringBuffer sql) {
+        sql.append(columnName);
+        sql.append(" ");
+        sql.append(columnType());
+    }
+
+    @Override
+    public void appendColumnNames(final StringBuffer sql) {
+        sql.append(columnName);
+    }
+
+    @Override
+    public void appendInsertValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        final ObjectAdapter fieldValue = field.get(object);
+        if (fieldValue == null) {
+            sql.append("NULL");
+        } else {
+            sql.append("?");
+            connector.addToQueryValues(preparedStatementObject(fieldValue));
+        }
+    }
+
+    @Override
+    public void appendUpdateValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        appendEqualsClause(connector, sql, object, "=");
+    }
+
+    @Override
+    public void appendWhereClause(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        appendEqualsClause(connector, sql, object, "=");
+    }
+
+    protected void appendEqualsClause(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object, final String condition) {
+        sql.append(Sql.sqlFieldName(field.getId()));
+        sql.append(condition);
+        final ObjectAdapter fieldValue = field.get(object);
+        sql.append("?");
+        connector.addToQueryValues(preparedStatementObject(fieldValue));
+    }
+
+    @Override
+    public void initializeField(final ObjectAdapter object, final Results rs) {
+        final String columnName = Sql.sqlFieldName(field.getId());
+        final ObjectAdapter restoredValue = setFromDBColumn(rs, columnName, field);
+        ((OneToOneAssociation) field).initAssociation(object, restoredValue);
+    }
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln(field.getId(), columnName + "/" + columnType());
+    }
+
+    @Override
+    public void appendWhereObject(final DatabaseConnector connector, final ObjectAdapter objectAdapter) {
+        final Object object = preparedStatementObject(objectAdapter);
+        connector.addToQueryValues(object);
+    }
+
+    protected abstract String columnType();
+
+    protected abstract Object preparedStatementObject(ObjectAdapter value);
+
+    protected abstract ObjectAdapter setFromDBColumn(Results results, String columnName, ObjectAssociation field);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcMultiFieldMapping.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcMultiFieldMapping.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcMultiFieldMapping.java
new file mode 100755
index 0000000..45f6753
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/AbstractJdbcMultiFieldMapping.java
@@ -0,0 +1,195 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.sql.jdbc;
+
+import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Sql;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+public abstract class AbstractJdbcMultiFieldMapping extends AbstractJdbcFieldMapping {
+    private final int columnCount;
+    private final String[] types;
+    private final String[] columnNames;
+    private final AdapterManager adapterManager;
+
+    /**
+     * 
+     * @param field
+     *            the field object association.
+     * @param columnCount
+     *            the number of columns required to store this field. See the
+     *            abstract methods ,
+     *            {@link AbstractJdbcFieldMapping#preparedStatementObject(int i, ObjectAdapter fieldValue)}
+     *            ,
+     *            {@link AbstractJdbcFieldMapping#getObjectFromResults(Results results)}
+     *            ,
+     * @param types
+     *            the list of SQL data types, 1 per columnCount, to represent
+     *            the value type.
+     */
+    public AbstractJdbcMultiFieldMapping(final ObjectAssociation field, final int columnCount, final String... types) {
+        super(field);
+        this.columnCount = columnCount;
+
+        this.types = new String[columnCount];
+        for (int i = 0; i < types.length; i++) {
+            this.types[i] = types[i];
+        }
+
+        final String fieldName = field.getId();
+        columnNames = new String[columnCount];
+        columnNames[0] = Sql.sqlFieldName(fieldName + "1");
+        columnNames[1] = Sql.sqlFieldName(fieldName + "2");
+
+        adapterManager = IsisContext.getPersistenceSession().getAdapterManager();
+
+    }
+
+    @Override
+    public void appendColumnDefinitions(final StringBuffer sql) {
+        for (int i = 0; i < columnCount; i++) {
+            sql.append(columnName(i) + " " + columnType(i));
+            if (i < columnCount - 1) {
+                sql.append(", ");
+            }
+        }
+    }
+
+    @Override
+    public void appendColumnNames(final StringBuffer sql) {
+        for (int i = 0; i < columnCount; i++) {
+            sql.append(columnName(i));
+            if (i < columnCount - 1) {
+                sql.append(", ");
+            }
+        }
+    }
+
+    @Override
+    public void appendInsertValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        final ObjectAdapter fieldValue = field.get(object);
+        final Object o = (fieldValue == null) ? null : fieldValue.getObject();
+
+        for (int i = 0; i < columnCount; i++) {
+            if (fieldValue == null) {
+                sql.append("NULL");
+            } else {
+                sql.append("?");
+                if (i < columnCount - 1) {
+                    sql.append(", ");
+                }
+
+                connector.addToQueryValues(preparedStatementObject(i, o));
+            }
+        }
+    }
+
+    @Override
+    public void appendUpdateValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        final ObjectAdapter fieldValue = field.get(object);
+        final Object o = (fieldValue == null) ? null : fieldValue.getObject();
+        for (int i = 0; i < columnCount; i++) {
+            appendEqualsClause(connector, i, sql, o, "=");
+        }
+    }
+
+    @Override
+    public void appendWhereClause(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        appendUpdateValues(connector, sql, object);
+    }
+
+    private void appendEqualsClause(final DatabaseConnector connector, final int index, final StringBuffer sql, final Object object, final String condition) {
+
+        final Object oPart = preparedStatementObject(index, object);
+
+        sql.append(columnName(index) + condition + "?");
+        if (index < columnCount - 1) {
+            sql.append(", ");
+        }
+
+        connector.addToQueryValues(oPart);
+    }
+
+    @Override
+    public ObjectAdapter setFromDBColumn(final Results results, final String columnName, final ObjectAssociation field) {
+        ObjectAdapter restoredValue;
+        final Object objectValue = getObjectFromResults(results);
+        restoredValue = adapterManager.adapterFor(objectValue); // NOTE: If this
+                                                                // fails, then
+                                                                // fetch back
+                                                                // the
+                                                                // declaration
+                                                                // from the
+                                                                // constructor
+                                                                // to here.
+        return restoredValue;
+    }
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        for (int i = 0; i < columnCount; i++) {
+            debug.appendln(field.getId(), columnName(i) + "/" + columnType(i));
+        }
+    }
+
+    @Override
+    protected String columnType() {
+        throw new ApplicationException("Should never be called");
+    }
+
+    @Override
+    protected Object preparedStatementObject(final ObjectAdapter value) {
+        throw new ApplicationException("Should never be called");
+    }
+
+    protected String columnType(final int index) {
+        return types[index];
+    }
+
+    protected String columnName(final int index) {
+        return columnNames[index];
+    }
+
+    /**
+     * Return an object suitable for passing to the SQL prepared statement
+     * constructor, to handle field "index". Will be called "columnCount" times.
+     * 
+     * @param index
+     *            0 based index
+     * @param fieldObject
+     *            the value type currently being
+     * @return a JDBC-compatible object.
+     */
+    protected abstract Object preparedStatementObject(int index, Object o);
+
+    /**
+     * Return an applib object represented by the results set.
+     * 
+     * @param results
+     *            the current record row from the underlying table
+     * @return a fully initialised value object.
+     */
+    protected abstract Object getObjectFromResults(Results results);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcAbstractReferenceFieldMapping.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcAbstractReferenceFieldMapping.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcAbstractReferenceFieldMapping.java
new file mode 100755
index 0000000..c74d6da
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcAbstractReferenceFieldMapping.java
@@ -0,0 +1,150 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.sql.jdbc;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.AbstractFieldMappingFactory;
+import org.apache.isis.runtimes.dflt.objectstores.sql.DatabaseConnector;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Defaults;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Sql;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+/**
+ * Provides support for persisting abstract classes and interfaces.
+ * 
+ * Provides two columns: the first is the standard property field. The second is
+ * initialised only when the field is "saved", and contains the actual classname
+ * of the persisted concrete class.
+ * 
+ * 
+ * @version $Rev$ $Date$
+ */
+public class JdbcAbstractReferenceFieldMapping extends JdbcObjectReferenceFieldMapping {
+    private final String classnameColumn;
+    private final String dataType;
+
+    public static class Factory extends AbstractFieldMappingFactory {
+
+        public Factory(final String type) {
+            super();
+        }
+
+        @Override
+        public FieldMapping createFieldMapping(final ObjectSpecification object, final ObjectAssociation field) {
+            final String dataType = getTypeOverride(object, field, Defaults.TYPE_LONG_STRING());
+            return new JdbcAbstractReferenceFieldMapping(field, dataType);
+        }
+    }
+
+    public JdbcAbstractReferenceFieldMapping(final ObjectAssociation field, final String dataType) {
+        super(field);
+        this.dataType = dataType;
+        classnameColumn = Sql.identifier(getColumn() + "_cls");
+    }
+
+    @Override
+    public void appendColumnDefinitions(final StringBuffer sql) {
+        super.appendColumnDefinitions(sql);
+
+        sql.append(", ");
+        sql.append(classnameColumn);
+        sql.append(" ");
+        sql.append(dataType);
+    }
+
+    @Override
+    public void appendCreateColumnDefinitions(final StringBuffer sql) {
+        super.appendCreateColumnDefinitions(sql);
+        sql.append(classnameColumn);
+        sql.append(" ");
+        sql.append(dataType);
+    }
+
+    @Override
+    public void appendColumnNames(final StringBuffer sql) {
+        super.appendColumnNames(sql);
+        sql.append(", ");
+        sql.append(classnameColumn);
+    }
+
+    @Override
+    public void appendWhereClause(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        super.appendWhereClause(connector, sql, object);
+    }
+
+    @Override
+    public void appendInsertValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        super.appendInsertValues(connector, sql, object);
+        sql.append(",?");
+
+        final ObjectAdapter objectAdapter = field.get(object);
+        if (objectAdapter != null) {
+            connector.addToQueryValues(objectAdapter.getSpecification().getFullIdentifier());
+        } else {
+            connector.addToQueryValues(null);
+        }
+    }
+
+    @Override
+    public void appendUpdateValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        super.appendUpdateValues(connector, sql, object);
+
+        sql.append(",");
+        sql.append(classnameColumn);
+        sql.append(" = ?");
+
+        final ObjectAdapter objectAdapter = field.get(object);
+        if (objectAdapter != null) {
+            connector.addToQueryValues(objectAdapter.getSpecification().getFullIdentifier());
+        } else {
+            connector.addToQueryValues(null);
+        }
+    }
+
+    @Override
+    public void initializeField(final ObjectAdapter object, final Results rs) {
+        final String className = rs.getString(classnameColumn);
+        if (className != null) {
+            final ObjectSpecification specification = getReflector().loadSpecification(className);
+
+            final Oid oid = recreateOid(rs, specification);
+
+            final ObjectAdapter reference = getAdapter(specification, oid);
+            ((OneToOneAssociation) field).initAssociation(object, reference);
+        }
+    }
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln(field.getId(), getColumn());
+    }
+
+    private SpecificationLoaderSpi getReflector() {
+        return IsisContext.getSpecificationLoader();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcBinaryValueMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcBinaryValueMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcBinaryValueMapper.java
new file mode 100755
index 0000000..835f401
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcBinaryValueMapper.java
@@ -0,0 +1,132 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.sql.jdbc;
+
+import org.apache.isis.core.commons.exceptions.IsisApplicationException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.AbstractFieldMappingFactory;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+/**
+ * 
+ * 
+ * @version $Rev$ $Date$
+ */
+public class JdbcBinaryValueMapper extends AbstractJdbcFieldMapping {
+
+    public static class Factory extends AbstractFieldMappingFactory {
+        private final String type;
+
+        public Factory(final String type) {
+            super();
+            this.type = type;
+        }
+
+        @Override
+        public FieldMapping createFieldMapping(final ObjectSpecification object, final ObjectAssociation field) {
+            final String dataType = getTypeOverride(object, field, type);
+            return new JdbcBinaryValueMapper(field, dataType);
+        }
+    }
+
+    private final String type;
+
+    public JdbcBinaryValueMapper(final ObjectAssociation field, final String type) {
+        super(field);
+        this.type = type;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.AbstractJdbcFieldMapping
+     * #columnType()
+     */
+    @Override
+    protected String columnType() {
+        return type;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.AbstractJdbcFieldMapping
+     * #preparedStatementObject(org.apache
+     * .isis.core.metamodel.adapter.ObjectAdapter)
+     */
+    @Override
+    protected Object preparedStatementObject(final ObjectAdapter value) {
+        if (value == null) {
+            return null;
+        }
+        final Object o = value.getObject();
+        return o;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.AbstractJdbcFieldMapping
+     * #setFromDBColumn(org.apache.isis. runtimes.dflt.objectstores.sql.Results,
+     * java.lang.String,
+     * org.apache.isis.core.metamodel.spec.feature.ObjectAssociation)
+     */
+    @Override
+    protected ObjectAdapter setFromDBColumn(final Results results, final String columnName, final ObjectAssociation field) {
+        ObjectAdapter restoredValue;
+
+        final Class<?> correspondingClass = field.getSpecification().getCorrespondingClass();
+        Object resultObject = results.getObject(columnName);
+        if (resultObject == null) {
+            return null;
+        }
+
+        if (resultObject.getClass() != correspondingClass) {
+            if (checkIfIsClass(correspondingClass, Integer.class, int.class)) {
+                resultObject = results.getInt(columnName);
+            } else if (checkIfIsClass(correspondingClass, Double.class, double.class)) {
+                resultObject = results.getDouble(columnName);
+            } else if (checkIfIsClass(correspondingClass, Float.class, float.class)) {
+                resultObject = results.getFloat(columnName);
+            } else if (checkIfIsClass(correspondingClass, Short.class, short.class)) {
+                resultObject = results.getShort(columnName);
+            } else if (checkIfIsClass(correspondingClass, Long.class, long.class)) {
+                resultObject = results.getLong(columnName);
+            } else if (checkIfIsClass(correspondingClass, Boolean.class, boolean.class)) {
+                resultObject = results.getBoolean(columnName);
+            } else {
+                throw new IsisApplicationException("Unhandled type: " + correspondingClass.getCanonicalName());
+            }
+        }
+
+        restoredValue = IsisContext.getPersistenceSession().getAdapterManager().adapterFor(resultObject);
+
+        return restoredValue;
+
+    }
+
+    private boolean checkIfIsClass(final Class<?> expected, final Class<?> couldBe1, final Class<?> couldBe2) {
+        return (expected == couldBe1 || expected == couldBe2);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/0861ed93/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcColorValueMapper.java
----------------------------------------------------------------------
diff --git a/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcColorValueMapper.java b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcColorValueMapper.java
new file mode 100755
index 0000000..1ef8975
--- /dev/null
+++ b/framework/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/jdbc/JdbcColorValueMapper.java
@@ -0,0 +1,101 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.sql.jdbc;
+
+import org.apache.isis.applib.value.Color;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.sql.AbstractFieldMappingFactory;
+import org.apache.isis.runtimes.dflt.objectstores.sql.Results;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+/**
+ * 
+ * 
+ * @version $Rev$ $Date$
+ */
+public class JdbcColorValueMapper extends AbstractJdbcFieldMapping {
+
+    public static class Factory extends AbstractFieldMappingFactory {
+        private final String type;
+
+        public Factory(final String type) {
+            super();
+            this.type = type;
+        }
+
+        @Override
+        public FieldMapping createFieldMapping(final ObjectSpecification object, final ObjectAssociation field) {
+            final String dataType = getTypeOverride(object, field, type);
+            return new JdbcColorValueMapper(field, dataType);
+        }
+    }
+
+    private final String type;
+
+    public JdbcColorValueMapper(final ObjectAssociation field, final String type) {
+        super(field);
+        this.type = type;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.AbstractJdbcFieldMapping
+     * #columnType()
+     */
+    @Override
+    protected String columnType() {
+        return type;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.AbstractJdbcFieldMapping
+     * #preparedStatementObject(org.apache
+     * .isis.core.metamodel.adapter.ObjectAdapter)
+     */
+    @Override
+    protected Object preparedStatementObject(final ObjectAdapter value) {
+        final Object o = value.getObject();
+        return ((Color) o).intValue();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * org.apache.isis.runtimes.dflt.objectstores.sql.jdbc.AbstractJdbcFieldMapping
+     * #setFromDBColumn(org.apache.isis. runtimes.dflt.objectstores.sql.Results,
+     * java.lang.String,
+     * org.apache.isis.core.metamodel.spec.feature.ObjectAssociation)
+     */
+    @Override
+    protected ObjectAdapter setFromDBColumn(final Results results, final String columnName, final ObjectAssociation field) {
+        ObjectAdapter restoredValue;
+        final int intValue = results.getInt(columnName);
+        final Color colorValue = new Color(intValue);
+        restoredValue = IsisContext.getPersistenceSession().getAdapterManager().adapterFor(colorValue);
+        return restoredValue;
+    }
+
+}