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 18:42:17 UTC

[15/52] [partial] ISIS-188: moving framework/ subdirs up to parent

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/DatabaseConnectorPool.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/DatabaseConnectorPool.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/DatabaseConnectorPool.java
new file mode 100644
index 0000000..cb5d5cc
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/DatabaseConnectorPool.java
@@ -0,0 +1,108 @@
+/*
+ *  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;
+
+import java.util.Vector;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+
+public class DatabaseConnectorPool {
+    private static final Logger LOG = Logger.getLogger(DatabaseConnectorPool.class);
+    private static final int AVERAGE_POOL_SIZE = 5;
+
+    private final DatabaseConnectorFactory factory;
+    private final Vector<DatabaseConnector> connectorPool;
+
+    public DatabaseConnectorPool(final DatabaseConnectorFactory factory) {
+        this(factory, AVERAGE_POOL_SIZE);
+    }
+
+    public DatabaseConnectorPool(final DatabaseConnectorFactory factory, final int size) {
+        this.factory = factory;
+        connectorPool = new Vector<DatabaseConnector>();
+        for (int i = 0; i < size; i++) {
+            newConnector();
+        }
+        LOG.info("Created an intial pool of " + size + " database connections");
+
+        final DatabaseConnector connection = acquire();
+        Sql.setMetaData(connection.getMetaData());
+        release(connection);
+    }
+
+    private DatabaseConnector newConnector() {
+        final DatabaseConnector connector = factory.createConnector();
+        connector.setConnectionPool(this);
+        connectorPool.addElement(connector);
+        return connector;
+    }
+
+    public DatabaseConnector acquire() {
+        DatabaseConnector connector = findFreeConnector();
+        if (connector == null) {
+            connector = newConnector();
+            connector.setUsed(true);
+            LOG.info("Added an additional database connection; now contains " + connectorPool.size() + " connections");
+        }
+        LOG.debug("acquired connection " + connector);
+        return connector;
+    }
+
+    private DatabaseConnector findFreeConnector() {
+        for (int i = 0, no = connectorPool.size(); i < no; i++) {
+            final DatabaseConnector connector = connectorPool.elementAt(i);
+            if (!connector.isUsed()) {
+                connector.setUsed(true);
+                return connector;
+            }
+        }
+        return null;
+    }
+
+    public void release(final DatabaseConnector connector) {
+        connector.setUsed(false);
+        LOG.debug("released connection " + connector);
+    }
+
+    public void shutdown() {
+        for (int i = 0, no = connectorPool.size(); i < no; i++) {
+            final DatabaseConnector connector = connectorPool.elementAt(i);
+            try {
+                connector.close();
+            } catch (final SqlObjectStoreException e) {
+                LOG.error("Failed to release connectuion", e);
+            }
+        }
+        connectorPool.removeAllElements();
+    }
+
+    public void debug(final DebugBuilder debug) {
+        final DatabaseConnector connection = acquire();
+        connection.debug(debug);
+        release(connection);
+
+    }
+
+    public SqlMetaData getMetaData() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Defaults.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Defaults.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Defaults.java
new file mode 100755
index 0000000..dccd04c
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Defaults.java
@@ -0,0 +1,354 @@
+/*
+ *  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;
+
+import java.util.Calendar;
+
+import org.joda.time.DateTimeZone;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+
+/**
+ * Provides objectstore defaults. Most significantly, maintains the object store default TimeZone, and maintains
+ * Calendar.
+ * 
+ * 
+ * @version $Rev$ $Date$
+ */
+public class Defaults {
+    private static String propertiesBase;
+    private static IsisConfiguration isisConfiguration;
+
+    /**
+     * Initialise the Defaults internals. Called by the PersistorInstaller.
+     * 
+     * @param propertiesBase
+     *            by default, @link {@link SqlObjectStore#BASE_NAME}
+     * @param isisConfiguration
+     */
+    public static void initialise(final String propertiesBase, final IsisConfiguration isisConfiguration) {
+        Defaults.propertiesBase = propertiesBase; // "isis.persistor.sql"
+        setTimeZone(DateTimeZone.UTC);
+
+        Defaults.isisConfiguration = isisConfiguration;
+
+        setTablePrefix(getStringProperty(propertiesBase, isisConfiguration, "tableprefix", "isis_"));
+        setPkIdLabel(getStringProperty(propertiesBase, isisConfiguration, "pk_id"));
+        setIdColumn(getStringProperty(propertiesBase, isisConfiguration, "id"));
+        setMaxInstances(getIntProperty(propertiesBase, isisConfiguration, "maxinstances", 100));
+        final String useVersioningProperty = getStringProperty(propertiesBase, isisConfiguration, "versioning", "true");
+        final int isTrue = useVersioningProperty.compareToIgnoreCase("true");
+        useVersioning(isTrue == 0);
+
+        defineDatabaseCommands();
+
+        final String BASE_DATATYPE = propertiesBase + ".datatypes.";
+        final IsisConfiguration dataTypes = isisConfiguration.getProperties(BASE_DATATYPE);
+        populateSqlDataTypes(dataTypes, BASE_DATATYPE);
+
+    }
+
+    /**
+     * Returns a string value by looking up "isis.persistor.sql.default.XXXX"
+     * 
+     * @param propertiesBase
+     * @param configParameters
+     * @param property
+     * @return
+     */
+    protected static String getStringProperty(final String propertiesBase, final IsisConfiguration configParameters,
+        final String property) {
+        return configParameters.getString(propertiesBase + ".default." + property, property);
+    }
+
+    /**
+     * Returns a string value by looking up "isis.persistor.sql.default.XXXX", returning the specified default, if no
+     * value was found.
+     * 
+     * @param propertiesBase
+     * @param configParameters
+     * @param property
+     * @param defaultValue
+     * @return
+     */
+    protected static String getStringProperty(final String propertiesBase, final IsisConfiguration configParameters,
+        final String property, final String defaultValue) {
+        return configParameters.getString(propertiesBase + ".default." + property, defaultValue);
+    }
+
+    /**
+     * Returns an integer value by looking up "isis.persistor.sql.default.XXXX", returning the specified default, if no
+     * value was found.
+     * 
+     * @param propertiesBase
+     * @param configParameters
+     * @param property
+     * @param defaultValue
+     * @return
+     */
+    protected static int getIntProperty(final String propertiesBase, final IsisConfiguration configParameters,
+        final String property, final int defaultValue) {
+        return configParameters.getInteger(propertiesBase + ".default." + property, defaultValue);
+    }
+
+    // {{ Calendar
+    private static Calendar calendar;
+
+    public static Calendar getCalendar() {
+        return calendar;
+    }
+
+    // }}
+
+    // {{ DateTimeZone
+    private static DateTimeZone dateTimeZone;
+
+    public static DateTimeZone getTimeZone() {
+        return dateTimeZone;
+    }
+
+    public static void setTimeZone(final DateTimeZone timezone) {
+        dateTimeZone = timezone;
+        calendar = Calendar.getInstance(timezone.toTimeZone());
+    }
+
+    // }}
+
+    // {{ Table prefix, defaults to "isis_"
+    private static String tablePrefix;
+
+    public static String getTablePrefix() {
+        return Defaults.tablePrefix;
+    }
+
+    public static void setTablePrefix(final String prefix) {
+        Defaults.tablePrefix = prefix;
+    }
+
+    // }}
+
+    // {{ Primary Key label, defaults to "pk_id"
+    private static String pkIdLabel;
+
+    public static void setPkIdLabel(final String pkIdLabel) {
+        Defaults.pkIdLabel = pkIdLabel;
+    }
+
+    public static String getPkIdLabel() {
+        return pkIdLabel;
+    }
+
+    // }}
+
+    // {{ Id Column, defaults to "id"
+    private static String idColumn;
+
+    public static void setIdColumn(final String idColumn) {
+        Defaults.idColumn = idColumn;
+    }
+
+    public static String getIdColumn() {
+        return idColumn;
+    }
+
+    // }}
+
+    // {{ MaxInstances
+    private static int maxInstances;
+
+    public static int getMaxInstances() {
+        return maxInstances;
+    }
+
+    public static void setMaxInstances(final int maxInstances) {
+        Defaults.maxInstances = maxInstances;
+    }
+
+    // }}
+
+    // {{ Default data types
+    static String TYPE_BOOLEAN;
+    static String TYPE_TIMESTAMP;
+    static String TYPE_DATETIME;
+    static String TYPE_DATE;
+    static String TYPE_TIME;
+    static String TYPE_SHORT;
+    static String TYPE_DOUBLE;
+    static String TYPE_FLOAT;
+    static String TYPE_LONG;
+    static String TYPE_INT;
+    static String TYPE_PK;
+    static String TYPE_STRING;
+    static String TYPE_LONG_STRING;
+    static String TYPE_PASSWORD;
+    static String PASSWORD_SEED;
+    static Integer PASSWORD_ENC_LENGTH;
+    static String TYPE_DEFAULT;
+
+    /**
+     * Default SQL data types used to define the fields in the database. By providing this method, we allow the user an
+     * opportunity to override these types by specifying alternatives in sql.properties (or which ever). For example,
+     * Postgresql does not know about DATETIME, but can use TIMESTAMP instead.
+     * 
+     * @param dataTypes
+     * @param baseName
+     */
+    private static void populateSqlDataTypes(final IsisConfiguration dataTypes, final String baseName) {
+        TYPE_TIMESTAMP = dataTypes.getString(baseName + "timestamp", "DATETIME");
+        TYPE_DATETIME = dataTypes.getString(baseName + "datetime", "DATETIME");
+        TYPE_DATE = dataTypes.getString(baseName + "date", "DATE");
+        TYPE_TIME = dataTypes.getString(baseName + "time", "TIME");
+        TYPE_DOUBLE = dataTypes.getString(baseName + "double", "DOUBLE");
+        TYPE_FLOAT = dataTypes.getString(baseName + "float", "FLOAT");
+        TYPE_SHORT = dataTypes.getString(baseName + "short", "INT");
+        TYPE_LONG = dataTypes.getString(baseName + "long", "BIGINT");
+        TYPE_INT = dataTypes.getString(baseName + "int", "INT");
+        TYPE_BOOLEAN = dataTypes.getString(baseName + "boolean", "BOOLEAN"); // CHAR(1)
+        TYPE_PK = dataTypes.getString(baseName + "primarykey", "INTEGER");
+        TYPE_STRING = dataTypes.getString(baseName + "string", "VARCHAR(65)");
+        TYPE_LONG_STRING = dataTypes.getString(baseName + "longstring", "VARCHAR(128)");
+        TYPE_PASSWORD = dataTypes.getString(baseName + "password", "VARCHAR(128)");
+        PASSWORD_ENC_LENGTH = getIntProperty(propertiesBase, isisConfiguration, "password.length", 120);
+        PASSWORD_SEED = getStringProperty(propertiesBase, isisConfiguration, "password.seed");
+        TYPE_DEFAULT = dataTypes.getString(baseName + "default", "VARCHAR(65)");
+
+    }
+
+    public static String TYPE_TIMESTAMP() {
+        return TYPE_TIMESTAMP;
+    }
+
+    public static String TYPE_SHORT() {
+        return TYPE_SHORT;
+    }
+
+    public static String TYPE_INT() {
+        return TYPE_INT;
+    }
+
+    public static String TYPE_LONG() {
+        return TYPE_LONG;
+    }
+
+    public static String TYPE_FLOAT() {
+        return TYPE_FLOAT;
+    }
+
+    public static String TYPE_DOUBLE() {
+        return TYPE_DOUBLE;
+    }
+
+    public static String TYPE_BOOLEAN() {
+        return TYPE_BOOLEAN;
+    }
+
+    public static String TYPE_PK() {
+        return TYPE_PK;
+    }
+
+    public static String TYPE_STRING() {
+        return TYPE_STRING;
+    }
+
+    public static String TYPE_LONG_STRING() {
+        return TYPE_LONG_STRING;
+    }
+
+    public static String TYPE_PASSWORD() {
+        return TYPE_PASSWORD;
+    }
+
+    public static String PASSWORD_SEED() {
+        return PASSWORD_SEED;
+    }
+
+    public static Integer PASSWORD_ENC_LENGTH() {
+        return PASSWORD_ENC_LENGTH;
+    }
+
+    public static String TYPE_DEFAULT() {
+        return TYPE_DEFAULT;
+    }
+
+    public static String TYPE_DATE() {
+        return TYPE_DATE;
+    }
+
+    public static String TYPE_DATETIME() {
+        return TYPE_DATETIME;
+    }
+
+    public static String TYPE_TIME() {
+        return TYPE_TIME;
+    }
+
+    // }}
+
+    // {{ Versioning
+    private static boolean useVersioning;
+
+    public static void useVersioning(final boolean useVersioning) {
+        Defaults.useVersioning = useVersioning;
+    }
+
+    public static boolean useVersioning() {
+        return useVersioning;
+    }
+
+    public static boolean useVersioning(final String shortIdentifier) {
+        if (useVersioning() == false) {
+            return false;
+        }
+        final String useVersioningProperty =
+            getStringProperty(propertiesBase, isisConfiguration, "versioning." + shortIdentifier, "true");
+        return (useVersioningProperty.compareToIgnoreCase("true") == 0);
+    }
+
+    // }}
+
+    // {{ Database commands
+
+    private static String START_TRANSACTION;
+    private static String ABORT_TRANSACTION;
+    private static String COMMIT_TRANSACTION;
+
+    private static void defineDatabaseCommands() {
+        START_TRANSACTION =
+            getStringProperty(propertiesBase, isisConfiguration, "command.beginTransaction", "START TRANSACTION;");
+        ABORT_TRANSACTION =
+            getStringProperty(propertiesBase, isisConfiguration, "command.abortTransaction", "ROLLBACK;");
+        COMMIT_TRANSACTION =
+            getStringProperty(propertiesBase, isisConfiguration, "command.commitTransaction", "COMMIT;");
+    }
+
+    public static String START_TRANSACTION() {
+        return START_TRANSACTION;
+    }
+
+    public static String ABORT_TRANSACTION() {
+        return ABORT_TRANSACTION;
+    }
+
+    public static String COMMIT_TRANSACTION() {
+        return COMMIT_TRANSACTION;
+    }
+    // }}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingFactoryInstaller.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingFactoryInstaller.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingFactoryInstaller.java
new file mode 100644
index 0000000..a5b806a
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingFactoryInstaller.java
@@ -0,0 +1,24 @@
+/*
+ *  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;
+
+public interface FieldMappingFactoryInstaller {
+    void load(FieldMappingLookup lookup);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingLookup.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingLookup.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingLookup.java
new file mode 100644
index 0000000..d8fcc59
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/FieldMappingLookup.java
@@ -0,0 +1,130 @@
+/*
+ *  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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+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.jdbc.JdbcGeneralValueMapper;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.FieldMappingFactory;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.ObjectReferenceMapping;
+import org.apache.isis.runtimes.dflt.objectstores.sql.mapping.ObjectReferenceMappingFactory;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+public class FieldMappingLookup {
+    private static final Logger LOG = Logger.getLogger(FieldMappingLookup.class);
+    private final Map<ObjectSpecification, FieldMappingFactory> fieldMappings = new HashMap<ObjectSpecification, FieldMappingFactory>();
+    private final Map<ObjectSpecification, ObjectReferenceMappingFactory> referenceMappings = new HashMap<ObjectSpecification, ObjectReferenceMappingFactory>();
+    private FieldMappingFactory referenceFieldMappingfactory;
+    private ObjectReferenceMappingFactory objectReferenceMappingfactory;
+
+    public FieldMapping createMapping(final ObjectSpecification object, final ObjectAssociation field) {
+        final ObjectSpecification spec = field.getSpecification();
+        FieldMappingFactory factory = fieldMappings.get(spec);
+        if (factory != null) {
+            return factory.createFieldMapping(object, field);
+        } else if (spec.isEncodeable()) {
+            factory = new JdbcGeneralValueMapper.Factory(Defaults.TYPE_DEFAULT());
+            addFieldMappingFactory(spec, factory);
+            return factory.createFieldMapping(object, field);
+        } else {// if (true /* TODO test for reference */) {
+            factory = referenceFieldMappingfactory;
+            addFieldMappingFactory(spec, factory);
+            return factory.createFieldMapping(object, field);
+            // } else {
+            // throw new IsisException("No mapper for " + spec +
+            // " (no default mapper)");
+        }
+    }
+
+    public ObjectReferenceMapping createMapping(final ObjectSpecification spec) {
+        return createMapping(spec.getShortIdentifier(), spec);
+    }
+
+    public ObjectReferenceMapping createMapping(final String columnName, final ObjectSpecification spec) {
+        ObjectReferenceMappingFactory factory = referenceMappings.get(spec);
+        if (factory != null) {
+            return factory.createReferenceMapping(columnName, spec);
+        } else if (spec.isEncodeable()) {
+            // TODO add generic encodeable mapping
+            throw new NotYetImplementedException();
+        } else {// if (true /* TODO test for reference */) {
+            factory = objectReferenceMappingfactory;
+            // add(spec, factory);
+            return factory.createReferenceMapping(columnName, spec); // TODO:
+                                                                     // here
+            // } else {
+            // throw new IsisException("No mapper for " + spec +
+            // " (no default mapper)");
+        }
+    }
+
+    public void addFieldMappingFactory(final Class<?> valueType, final FieldMappingFactory mapper) {
+        final ObjectSpecification spec = IsisContext.getSpecificationLoader().loadSpecification(valueType);
+        addFieldMappingFactory(spec, mapper);
+    }
+
+    private void addFieldMappingFactory(final ObjectSpecification specification, final FieldMappingFactory mapper) {
+        LOG.debug("add mapper " + mapper + " for " + specification);
+        fieldMappings.put(specification, mapper);
+    }
+
+    public void addReferenceMappingFactory(final ObjectSpecification specification, final ObjectReferenceMappingFactory mapper) {
+        LOG.debug("add mapper " + mapper + " for " + specification);
+        referenceMappings.put(specification, mapper);
+    }
+
+    public void init() {
+        // fieldMappingFactory.load(this);
+    }
+
+    public IdMapping createIdMapping() {
+        // TODO inject and use external factory
+        final IdMapping idMapping = new IdMapping();
+        idMapping.init();
+        return idMapping;
+    }
+
+    public VersionMapping createVersionMapping() {
+        // TODO inject and use external factory
+        final VersionMapping versionMapping = new VersionMapping();
+        versionMapping.init();
+        return versionMapping;
+    }
+
+    public void setReferenceFieldMappingFactory(final FieldMappingFactory referenceMappingfactory) {
+        this.referenceFieldMappingfactory = referenceMappingfactory;
+    }
+
+    public void setObjectReferenceMappingfactory(final ObjectReferenceMappingFactory objectReferenceMappingfactory) {
+        this.objectReferenceMappingfactory = objectReferenceMappingfactory;
+    }
+
+    public TitleMapping createTitleMapping() {
+        // TODO inject and use external factory
+        return new TitleMapping();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMapping.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMapping.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMapping.java
new file mode 100644
index 0000000..c56b71e
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMapping.java
@@ -0,0 +1,40 @@
+/*
+ *  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;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+public class IdMapping extends IdMappingAbstract {
+
+    public void init() {
+        String idColumn = null;
+        // idColumn = configParameters.getString(parameterBase + "id");
+        if (idColumn == null) {
+            idColumn = Defaults.getPkIdLabel();
+        }
+        setColumn(idColumn);
+    }
+
+    public void appendUpdateValues(final StringBuffer sql, final ObjectAdapter object) {
+    }
+
+    public void initializeField(final ObjectAdapter object, final Results rs) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMappingAbstract.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMappingAbstract.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMappingAbstract.java
new file mode 100644
index 0000000..ad2aefb
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/IdMappingAbstract.java
@@ -0,0 +1,112 @@
+/*
+ *  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;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+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.RootOidDefault;
+import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+
+public class IdMappingAbstract {
+    private String column;
+
+    protected void setColumn(final String column) {
+        this.column = Sql.identifier(column);
+    }
+
+    protected String getColumn() {
+        return column;
+    }
+
+    public void appendWhereClause(final DatabaseConnector connector, final StringBuffer sql, final RootOid oid) {
+        sql.append(column);
+        sql.append(" = ");
+        appendObjectId(connector, sql, oid);
+    }
+
+    public void appendObjectId(final DatabaseConnector connector, final StringBuffer sql, final RootOid oid) {
+        sql.append("?");
+        connector.addToQueryValues(primaryKey(oid));
+    }
+
+    public void appendCreateColumnDefinitions(final StringBuffer sql) {
+        sql.append(column);
+        sql.append(" ");
+        sql.append(Defaults.TYPE_PK() + " NOT NULL PRIMARY KEY");
+    }
+
+    public void appendColumnDefinitions(final StringBuffer sql) {
+        sql.append(column);
+        sql.append(" ");
+        sql.append(Defaults.TYPE_PK());
+    }
+
+    public void appendColumnNames(final StringBuffer sql) {
+        sql.append(column);
+    }
+
+    public void appendInsertValues(final DatabaseConnector connector, final StringBuffer sql, final ObjectAdapter object) {
+        if (object == null) {
+            sql.append("NULL");
+        } else {
+            appendObjectId(connector, sql, (RootOid) object.getOid());
+            // sql.append(connector.addToQueryValues(primaryKeyAsObject(object.getOid())));
+        }
+    }
+
+    public String primaryKey(final RootOid oid) {
+        return oid.getIdentifier();
+    }
+
+    public TypedOid recreateOid(final Results rs, final ObjectSpecification specification) {
+        final Object object = rs.getObject(column);
+        if (object == null) {
+            return null;
+        }
+        final int id = ((Integer) object).intValue();
+        return new RootOidDefault(specification.getSpecId(), "" + id, Oid.State.PERSISTENT);
+    }
+
+    protected ObjectAdapter getAdapter(final ObjectSpecification spec, final Oid oid) {
+        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(oid);
+        if (adapter != null) {
+            return adapter;
+        }
+        // REVIEW: where the oid is a TypedOid, the following two lines could be replaced by
+        // getPersistenceSession().recreatePersistentAdapter(oid)
+        // is preferable, since then reuses the PojoRecreator impl defined within SqlPersistorInstaller
+        final Object recreatedPojo = spec.createObject();
+        return getPersistenceSession().mapRecreatedPojo(oid, recreatedPojo);
+    }
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MappingLookup.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MappingLookup.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MappingLookup.java
new file mode 100644
index 0000000..6e89454
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MappingLookup.java
@@ -0,0 +1,26 @@
+/*
+ *  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;
+
+public class MappingLookup {
+    // private ObjectMappingLookup classMappingLookup;
+    // private FieldMappingLookup fieldMappingLookup;
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MultipleResults.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MultipleResults.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MultipleResults.java
new file mode 100644
index 0000000..8e03e9f
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/MultipleResults.java
@@ -0,0 +1,24 @@
+/*
+ *  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;
+
+public interface MultipleResults {
+    Results nextResults();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMapping.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMapping.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMapping.java
new file mode 100644
index 0000000..7d0b3e2
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMapping.java
@@ -0,0 +1,57 @@
+/*
+ *  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;
+
+import java.util.Vector;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByPattern;
+
+public interface ObjectMapping {
+    void createObject(DatabaseConnector connector, ObjectAdapter object);
+
+    void destroyObject(DatabaseConnector connector, ObjectAdapter object);
+
+    Vector<ObjectAdapter> getInstances(DatabaseConnector connector, ObjectSpecification spec);
+
+    Vector<ObjectAdapter> getInstances(DatabaseConnector connector, ObjectSpecification spec, String title);
+
+    Vector<ObjectAdapter> getInstances(DatabaseConnector connector, ObjectSpecification spec, PersistenceQueryFindByPattern query);
+
+    ObjectAdapter getObject(DatabaseConnector connector, TypedOid typedOid);
+
+    boolean hasInstances(DatabaseConnector connector, ObjectSpecification cls);
+
+    void resolve(DatabaseConnector connector, ObjectAdapter object);
+
+    void resolveCollection(DatabaseConnector connector, ObjectAdapter object, ObjectAssociation field);
+
+    void save(DatabaseConnector connector, ObjectAdapter object);
+
+    void shutdown();
+
+    void startup(DatabaseConnector connection, ObjectMappingLookup objectMapperLookup);
+
+    boolean saveCollection(DatabaseConnector connection, ObjectAdapter parent, String fieldName);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingFactory.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingFactory.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingFactory.java
new file mode 100644
index 0000000..f70d267
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingFactory.java
@@ -0,0 +1,24 @@
+/*
+ *  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;
+
+public interface ObjectMappingFactory {
+    ObjectMapping createMapper(String className, String propertiesBase, FieldMappingLookup fieldMapperLookup, ObjectMappingLookup objectMapperLookup);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingLookup.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingLookup.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingLookup.java
new file mode 100644
index 0000000..985c305
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/ObjectMappingLookup.java
@@ -0,0 +1,151 @@
+/*
+ *  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;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebuggableWithTitle;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.factory.InstanceCreationException;
+import org.apache.isis.core.commons.factory.InstanceUtil;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.runtime.persistence.ObjectPersistenceException;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+public class ObjectMappingLookup implements DebuggableWithTitle {
+    private static final Logger LOG = Logger.getLogger(ObjectMappingLookup.class);
+    private DatabaseConnectorPool connectionPool;
+    private final Map<ObjectSpecification, ObjectMapping> mappings = new HashMap<ObjectSpecification, ObjectMapping>();
+    private ObjectMappingFactory objectMappingFactory;
+    private FieldMappingLookup fieldMappingLookup;
+
+    public ObjectMapping getMapping(final ObjectSpecification spec, final DatabaseConnector connection) {
+    	String fullName = spec.getFullIdentifier();
+        ObjectMapping mapping = mappings.get(spec);
+        if (mapping == null) {
+            final String propertiesBase = SqlObjectStore.BASE_NAME + ".automapper.default";
+            mapping = objectMappingFactory.createMapper(fullName, propertiesBase, fieldMappingLookup, this);
+            add(spec, mapping, connection);
+        }
+        LOG.debug("  mapper for " + spec.getSingularName() + " -> " + mapping);
+        if (mapping == null) {
+            throw new IsisException("No mapper for " + spec + " (no default mapper)");
+        }
+        return mapping;
+    }
+
+    public ObjectMapping getMapping(final ObjectAdapter object, final DatabaseConnector connection) {
+        return getMapping(object.getSpecification(), connection);
+    }
+
+    public void setConnectionPool(final DatabaseConnectorPool connectionPool) {
+        this.connectionPool = connectionPool;
+    }
+
+    // / ???
+    public void setObjectMappingFactory(final ObjectMappingFactory mapperFactory) {
+        this.objectMappingFactory = mapperFactory;
+    }
+
+    public void setValueMappingLookup(final FieldMappingLookup fieldMappingLookup) {
+        this.fieldMappingLookup = fieldMappingLookup;
+    }
+
+    private void add(final String className, final ObjectMapping mapper) {
+        final ObjectSpecification spec = IsisContext.getSpecificationLoader().loadSpecification(className);
+        if (spec.getProperties().size() == 0) {
+            throw new SqlObjectStoreException(spec.getFullIdentifier() + " has no fields to persist: " + spec);
+        }
+        add(spec, mapper, null);
+    }
+
+    public void add(final ObjectSpecification specification, final ObjectMapping mapper, DatabaseConnector connection) {
+        LOG.debug("add mapper " + mapper + " for " + specification);
+        if (connection == null) {
+            connection = connectionPool.acquire();
+        }
+        mapper.startup(connection, this);
+        connectionPool.release(connection);
+        mappings.put(specification, mapper);
+    }
+
+    public void init() {
+        fieldMappingLookup.init();
+
+        final String prefix = SqlObjectStore.BASE_NAME + ".mapper.";
+        final IsisConfiguration subset = IsisContext.getConfiguration().createSubset(prefix);
+        for (final String className : subset) {
+            final String value = subset.getString(className);
+
+            if (value.startsWith("auto.")) {
+                final String propertiesBase = SqlObjectStore.BASE_NAME + ".automapper." + value.substring(5) + ".";
+                add(className, objectMappingFactory.createMapper(className, propertiesBase, fieldMappingLookup, this));
+            } else if (value.trim().equals("auto")) {
+                final String propertiesBase = SqlObjectStore.BASE_NAME + ".automapper.default";
+                add(className, objectMappingFactory.createMapper(className, propertiesBase, fieldMappingLookup, this));
+            } else {
+                LOG.debug("mapper " + className + "=" + value);
+
+                try {
+                    add(className, InstanceUtil.createInstance(value, ObjectMapping.class));
+                } catch (final ObjectPersistenceException ex) {
+                    throw new InstanceCreationException("Failed to set up mapper for " + className, ex);
+                }
+            }
+        }
+    }
+
+    public void shutdown() {
+        for (final ObjectMapping mapping : mappings.values()) {
+            try {
+                mapping.shutdown();
+            } catch (final ObjectPersistenceException ex) {
+                LOG.error("Shutdown mapper " + mapping, ex);
+            }
+        }
+    }
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln("field mapping lookup", fieldMappingLookup);
+        debug.appendln("object mapping factory", objectMappingFactory);
+        debug.appendTitle("Mappings");
+        int i = 1;
+        for (final ObjectSpecification specification : mappings.keySet()) {
+            debug.appendln(i++ + ". " + specification.getShortIdentifier());
+            final ObjectMapping mapper = mappings.get(specification);
+            debug.indent();
+            debug.append(mapper);
+            debug.unindent();
+        }
+    }
+
+    @Override
+    public String debugTitle() {
+        return "Object Mapping Lookup";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Parameter.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Parameter.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Parameter.java
new file mode 100644
index 0000000..8b8f6f3
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Parameter.java
@@ -0,0 +1,30 @@
+/*
+ *  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;
+
+import org.apache.isis.runtimes.dflt.runtime.persistence.ObjectPersistenceException;
+
+public interface Parameter {
+    void setupParameter(int parameter, StoredProcedure procedure) throws ObjectPersistenceException;
+
+    // String getRestoreString();
+
+    void retrieve(int parameter, StoredProcedure procedure) throws ObjectPersistenceException;
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Results.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Results.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Results.java
new file mode 100644
index 0000000..156b900
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Results.java
@@ -0,0 +1,60 @@
+/*
+ *  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;
+
+import java.sql.Time;
+import java.util.Calendar;
+import java.util.Date;
+
+public interface Results {
+
+    void close();
+
+    int getInt(String columnName);
+
+    long getLong(String columnName);
+
+    double getDouble(String columnName);
+
+    String getString(String columnName);
+
+    Float getFloat(String columnName);
+
+    Object getShort(String columnName);
+
+    Object getBoolean(String columnName);
+
+    boolean next();
+
+    Date getJavaDateOnly(String dateColumn);
+
+    Time getJavaTimeOnly(String timeColumn);
+
+    Date getJavaDateTime(String lastActivityDateColumn, Calendar calendar);
+
+    org.apache.isis.applib.value.Date getDate(String columnName);
+
+    org.apache.isis.applib.value.Time getTime(String columnName);
+
+    Object getObject(String column);
+
+    Object getAsType(String columnName, Class<?> clazz);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Sql.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Sql.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Sql.java
new file mode 100644
index 0000000..172ea59
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/Sql.java
@@ -0,0 +1,108 @@
+/*
+ *  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;
+
+/**
+ * SQL functions, commands, names that are database dependent
+ */
+public class Sql {
+    private Sql() {
+    }
+
+    private static SqlMetaData metadata;
+
+    // public static String timestamp = "CURRENT_TIMESTAMP";
+
+    public static void setMetaData(final SqlMetaData metadata) {
+        Sql.metadata = metadata;
+    }
+
+    public static String escapeAndQuoteValue(final String encodedString) {
+        if (encodedString == null || encodedString.equals("NULL")) {
+            return "NULL";
+        }
+        // StringBuffer buffer = new StringBuffer("'");
+        final StringBuffer buffer = new StringBuffer(metadata.getQuoteString());
+        for (int i = 0; i < encodedString.length(); i++) {
+            final char c = encodedString.charAt(i);
+            if (c == '\'') {
+                buffer.append("\\'");
+            } else if (c == '\\') {
+                buffer.append("\\\\");
+            } else {
+                buffer.append(c);
+            }
+        }
+        // buffer.append("'");
+        buffer.append(metadata.getQuoteString());
+        final String string = buffer.toString();
+        return string;
+    }
+
+    public static String sqlName(final String name) {
+        // TODO need to deal with non-ascii (ie unicode characters)
+        return name.replace(' ', '_').toLowerCase();
+
+        /*
+         * int length = name.length(); StringBuffer convertedName = new
+         * StringBuffer(length); for (int i = 0; i < length; i++) { char ch =
+         * name.charAt(i); if (ch == ' ') { i++; //ch = name.charAt(i);
+         * //Character.toUpperCase(ch); ch = '_'; } convertedName.append(ch); }
+         * return convertedName.toString();
+         */
+    }
+
+    public static String sqlFieldName(final String name) {
+        final int length = name.length();
+        final StringBuffer convertedName = new StringBuffer(length);
+        boolean lastWasLowerCase = false;
+        for (int i = 0; i < length; i++) {
+            final char ch = name.charAt(i);
+            if (Character.isUpperCase(ch)) {
+                if (lastWasLowerCase) {
+                    convertedName.append('_');
+                }
+                lastWasLowerCase = false;
+            } else {
+                lastWasLowerCase = true;
+            }
+            convertedName.append(ch);
+        }
+        return sqlName(convertedName.toString());
+    }
+
+    public static String identifier(final String name) {
+        // return metadata.quoteIdentifier(name);
+        return tableIdentifier(name);
+    }
+
+    public static String tableIdentifier(final String name) {
+        if (metadata.isStoresMixedCaseIdentifiers()) {
+            return name;
+        } else if (metadata.isStoresLowerCaseIdentifiers()) {
+            return name.toLowerCase();
+        } else if (metadata.isStoresUpperCaseIdentifiers()) {
+            return name.toUpperCase();
+        } else {
+            throw new SqlObjectStoreException("No case preference set up: " + name);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlExecutionContext.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlExecutionContext.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlExecutionContext.java
new file mode 100644
index 0000000..c17621e
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlExecutionContext.java
@@ -0,0 +1,46 @@
+/*
+ *  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;
+
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.MessageBroker;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.UpdateNotifier;
+
+public class SqlExecutionContext implements PersistenceCommandContext {
+    private final DatabaseConnector connection;
+
+    public SqlExecutionContext(final DatabaseConnector connection, final IsisTransactionManager transactionManager, final MessageBroker messageBroker, final UpdateNotifier updateNotifier) {
+        this.connection = connection;
+    }
+
+    public DatabaseConnector getConnection() {
+        return connection;
+    }
+
+    @Override
+    public void start() {
+    }
+
+    @Override
+    public void end() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlIdentifierGenerator.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlIdentifierGenerator.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlIdentifierGenerator.java
new file mode 100644
index 0000000..30539d5
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlIdentifierGenerator.java
@@ -0,0 +1,147 @@
+/*
+ *  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;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.runtimes.dflt.runtime.persistence.ObjectPersistenceException;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.IdentifierGenerator;
+
+public class SqlIdentifierGenerator implements IdentifierGenerator {
+    
+    private final DatabaseConnectorPool connectionPool;
+    private final IdNumbers ids = new IdNumbers();
+
+    //////////////////////////////////////////////////////////////////
+    // constructor
+    //////////////////////////////////////////////////////////////////
+
+    public SqlIdentifierGenerator(final DatabaseConnectorPool connectionPool) {
+        this.connectionPool = connectionPool;
+    }
+
+    ///////////////////////////////////////////////////////
+    // API
+    ///////////////////////////////////////////////////////
+    
+    @Override
+    public String createAggregateLocalId(ObjectSpecId objectSpecId, final Object pojo, final ObjectAdapter parentAdapter) {
+        throw new SqlObjectStoreException("Aggregated objects are not supported in this store");
+    }
+
+    @Override
+    public String createTransientIdentifierFor(ObjectSpecId objectSpecId, final Object pojo) {
+        return ""+ids.nextTransientId();
+    }
+
+    @Override
+    public String createPersistentIdentifierFor(ObjectSpecId objectSpecId, Object pojo, RootOid transientRootOid) {
+        Assert.assertNotNull("No connection set up", connectionPool);
+        return "" + (int) ids.nextPersistentId(connectionPool);
+    }
+
+    
+    ///////////////////////////////////////////////////////
+    // Debug
+    ///////////////////////////////////////////////////////
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln(this.toString());
+        debug.indent();
+        ids.debugData(debug);
+        debug.unindent();
+    }
+
+    @Override
+    public String debugTitle() {
+        return "Sql Identifier Generator";
+    }
+}
+
+
+
+class IdNumbers {
+
+    private static final Logger LOG = Logger.getLogger(IdNumbers.class);
+
+    private static final String NUMBER_COLUMN = "number";
+    private static final String TABLE_NAME = "isis_admin_serial_id";
+    private static int BATCH_SIZE = 50;
+    private long transientNumber = -9999999;
+    private long lastId = 0;
+    private long newBatchAt = 0;
+
+    public synchronized long nextTransientId() {
+        return transientNumber++;
+    }
+
+    public synchronized long nextPersistentId(final DatabaseConnectorPool connectionPool) {
+        if (lastId > newBatchAt) {
+            throw new SqlObjectStoreException("ID exception, last id (" + lastId + ") past new batch boundary (" + newBatchAt + ")");
+        }
+        if (lastId == newBatchAt) {
+            prepareNewBatch(connectionPool);
+        }
+        lastId++;
+        return lastId;
+    }
+
+    private void prepareNewBatch(final DatabaseConnectorPool connectionPool) {
+        final DatabaseConnector db = connectionPool.acquire();
+        try {
+            final String tableName = Sql.tableIdentifier(TABLE_NAME);
+            final String numberColumn = Sql.identifier(NUMBER_COLUMN);
+            if (!db.hasTable(tableName)) {
+                lastId = 1;
+                newBatchAt = BATCH_SIZE;
+                db.update("create table " + tableName + " (" + numberColumn + " INTEGER)");
+                db.update("insert into " + tableName + " values (" + newBatchAt + ")");
+                LOG.debug("Initial ID batch created, from " + lastId + " to " + newBatchAt);
+            } else {
+                if (db.update("update " + tableName + " set " + numberColumn + " = " + numberColumn + " + " + BATCH_SIZE) != 1) {
+                    throw new SqlObjectStoreException("failed to update serial id table; no rows updated");
+                }
+                final Results rs = db.select("select " + numberColumn + " from " + tableName);
+                rs.next();
+                newBatchAt = rs.getLong(NUMBER_COLUMN); // TODO here
+                lastId = newBatchAt - BATCH_SIZE;
+                LOG.debug("New ID batch created, from " + lastId + " to " + newBatchAt);
+                rs.close();
+            }
+        } catch (final ObjectPersistenceException e) {
+            throw e;
+        } finally {
+            connectionPool.release(db);
+        }
+    }
+
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln("id", lastId);
+        debug.appendln("transient id", transientNumber);
+    }
+
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlMetaData.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlMetaData.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlMetaData.java
new file mode 100644
index 0000000..5184e14
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlMetaData.java
@@ -0,0 +1,36 @@
+/*
+ *  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;
+
+public interface SqlMetaData {
+    String getKeywords();
+
+    String getTimeDateFunctions();
+
+    boolean isStoresLowerCaseIdentifiers();
+
+    boolean isStoresMixedCaseIdentifiers();
+
+    boolean isStoresUpperCaseIdentifiers();
+
+    String getQuoteString();
+
+    String quoteIdentifier(String identifier);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/255ef514/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlObjectStore.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlObjectStore.java b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlObjectStore.java
new file mode 100644
index 0000000..b3a9eec
--- /dev/null
+++ b/component/objectstore/sql/sql-impl/src/main/java/org/apache/isis/runtimes/dflt/objectstores/sql/SqlObjectStore.java
@@ -0,0 +1,507 @@
+/*
+ *  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;
+
+import java.util.List;
+import java.util.Vector;
+
+import com.google.common.collect.Lists;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.core.commons.ensure.IsisAssertException;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.oid.CollectionOid;
+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.RootOidDefault;
+import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.ObjectStoreSpi;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.CreateObjectCommand;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommand;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.SaveObjectCommand;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindAllInstances;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByPattern;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByTitle;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceQuery;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.MessageBroker;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.UpdateNotifier;
+
+public final class SqlObjectStore implements ObjectStoreSpi {
+
+    private static final String TABLE_NAME = "isis_admin_services";
+    // private static final String ID_COLUMN = "id";
+    // private static final String PRIMARYKEY_COLUMN = "pk_id";
+    public static final String BASE_NAME = "isis.persistor.sql";
+    private static final Logger LOG = Logger.getLogger(SqlObjectStore.class);
+    private DatabaseConnectorPool connectionPool;
+    private ObjectMappingLookup objectMappingLookup;
+    private boolean isInitialized;
+
+    @Override
+    public String name() {
+        return "SQL Object Store";
+    }
+
+    @Override
+    public void open() {
+        Sql.setMetaData(connectionPool.acquire().getMetaData());
+
+        if (!isInitialized) {
+            Defaults.initialise(BASE_NAME, IsisContext.getConfiguration());
+            Defaults.setPkIdLabel(Sql.identifier(Defaults.getPkIdLabel()));
+            Defaults.setIdColumn(Sql.identifier(Defaults.getIdColumn()));
+        }
+
+        final DebugBuilder debug = new DebugString();
+        connectionPool.debug(debug);
+        LOG.info("Database: " + debug);
+
+        objectMappingLookup.init();
+
+        final DatabaseConnector connector = connectionPool.acquire();
+        final String tableIdentifier = Sql.tableIdentifier(TABLE_NAME);
+        isInitialized = connector.hasColumn(tableIdentifier, Defaults.getPkIdLabel());
+        if (!isInitialized) {
+            if (connector.hasTable(tableIdentifier)) {
+                final StringBuffer sql = new StringBuffer();
+                sql.append("drop table ");
+                sql.append(tableIdentifier);
+                connector.update(sql.toString());
+            }
+            final StringBuffer sql = new StringBuffer();
+            sql.append("create table ");
+            sql.append(tableIdentifier);
+            sql.append(" (");
+            sql.append(Defaults.getPkIdLabel());
+            sql.append(" int, ");
+            sql.append(Defaults.getIdColumn());
+            sql.append(" varchar(255)");
+            sql.append(")");
+            connector.update(sql.toString());
+        }
+    }
+
+    @Override
+    public boolean isFixturesInstalled() {
+        return isInitialized;
+    }
+
+    @Override
+    public void registerService(final RootOid rootOid) {
+        final DatabaseConnector connector = connectionPool.acquire();
+
+        final StringBuffer sql = new StringBuffer();
+        sql.append("insert into ");
+        sql.append(Sql.tableIdentifier(TABLE_NAME));
+        sql.append(" (");
+        sql.append(Defaults.getPkIdLabel());
+        sql.append(", ");
+        sql.append(Defaults.getIdColumn());
+        sql.append(") values (?,?)");
+
+        final RootOidDefault sqlOid = (RootOidDefault) rootOid;
+        connector.addToQueryValues(sqlOid.getIdentifier());
+        connector.addToQueryValues(rootOid.getObjectSpecId().asString());
+
+        connector.insert(sql.toString());
+        connectionPool.release(connector);
+    }
+
+    @Override
+    public void reset() {
+    }
+
+    @Override
+    public void close() {
+        objectMappingLookup.shutdown();
+        connectionPool.shutdown();
+    }
+
+    @Override
+    public void startTransaction() {
+        executeSql(Defaults.START_TRANSACTION());
+    }
+
+    @Override
+    public void abortTransaction() {
+        executeSql(Defaults.ABORT_TRANSACTION());
+    }
+
+    @Override
+    public void endTransaction() {
+        executeSql(Defaults.COMMIT_TRANSACTION());
+    }
+
+    private void executeSql(String sql) {
+        final DatabaseConnector connector = connectionPool.acquire();
+        try {
+            connector.begin();
+            connector.update(sql);
+            connector.commit();
+            // connector.close();
+        } finally {
+            connectionPool.release(connector);
+        }
+    }
+
+    @Override
+    public CreateObjectCommand createCreateObjectCommand(final ObjectAdapter object) {
+        return new CreateObjectCommand() {
+            @Override
+            public void execute(final PersistenceCommandContext context) {
+                final DatabaseConnector connection = ((SqlExecutionContext) context).getConnection();
+                LOG.debug("  create object " + object);
+                final ObjectMapping mapping = objectMappingLookup.getMapping(object, connection);
+                mapping.createObject(connection, object);
+            }
+
+            @Override
+            public ObjectAdapter onAdapter() {
+                return object;
+            }
+
+            @Override
+            public String toString() {
+                return "CreateObjectCommand [object=" + object + "]";
+            }
+        };
+    }
+
+    @Override
+    public DestroyObjectCommand createDestroyObjectCommand(final ObjectAdapter object) {
+        return new DestroyObjectCommand() {
+            @Override
+            public void execute(final PersistenceCommandContext context) {
+                final DatabaseConnector connection = ((SqlExecutionContext) context).getConnection();
+                LOG.debug("  destroy object " + object);
+                final ObjectMapping mapping = objectMappingLookup.getMapping(object, connection);
+                mapping.destroyObject(connection, object);
+            }
+
+            @Override
+            public ObjectAdapter onAdapter() {
+                return object;
+            }
+
+            @Override
+            public String toString() {
+                return "DestroyObjectCommand [object=" + object + "]";
+            }
+        };
+    }
+
+    @Override
+    public SaveObjectCommand createSaveObjectCommand(final ObjectAdapter adapter) {
+        return new SaveObjectCommand() {
+            @Override
+            public void execute(final PersistenceCommandContext context) {
+                final DatabaseConnector connection = ((SqlExecutionContext) context).getConnection();
+                LOG.debug("  save object " + adapter.toString());
+
+                try {
+                    final ObjectSpecification adapterSpec = adapter.getSpecification();
+                    if (!adapterSpec.isParented()) {
+                        saveRootAdapter(adapter, connection);
+                    } else if(adapterSpec.isParentedOrFreeCollection()) { 
+                        saveParentedCollectionAdapter(adapter, connection);
+                    } else {
+                        throw new NotYetImplementedException("cannot yet persist aggregated objects: " + adapter.toString());
+                    }
+                } finally {
+                    connectionPool.release(connection);
+                }
+            }
+
+            private void saveRootAdapter(final ObjectAdapter adapter, final DatabaseConnector connection) {
+                final ObjectMapping mapping = objectMappingLookup.getMapping(adapter, connection);
+                mapping.save(connection, adapter);
+            }
+
+            private void saveParentedCollectionAdapter(final ObjectAdapter collectionAdapter, final DatabaseConnector connection) {
+                final ObjectAdapter parent = collectionAdapter.getAggregateRoot();
+                LOG.debug("change to internal collection being persisted through parent");
+   
+                final Oid oid = collectionAdapter.getOid();
+                final CollectionOid collectionOid = (CollectionOid) oid;
+                if (!(oid instanceof CollectionOid)) {
+                    throw new IsisAssertException("object should have a CollectionOid");
+                }
+                
+                final ObjectMapping mapping = objectMappingLookup.getMapping(parent, connection);
+                if (! mapping.saveCollection(connection, parent, collectionOid.getName()) ) {
+                    final ObjectMapping parentMapping = objectMappingLookup.getMapping(parent, connection);
+                    parentMapping.save(connection, collectionAdapter);
+                }
+            }
+
+            @Override
+            public ObjectAdapter onAdapter() {
+                return adapter;
+            }
+
+            @Override
+            public String toString() {
+                return "SaveObjectCommand [object=" + adapter + "]";
+            }
+
+        };
+    }
+
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendln("initialised", isInitialized);
+        debug.appendln("connection pool", connectionPool);
+        debug.appendln("Database:");
+        debug.indent();
+        connectionPool.debug(debug);
+        debug.unindent();
+        objectMappingLookup.debugData(debug);
+    }
+
+    @Override
+    public String debugTitle() {
+        return null;
+    }
+
+    @Override
+    public void execute(final List<PersistenceCommand> commands) {
+        final DatabaseConnector connector = connectionPool.acquire();
+        connector.begin();
+
+        final IsisTransactionManager transactionManager = IsisContext.getTransactionManager();
+        final MessageBroker messageBroker = IsisContext.getMessageBroker();
+        final UpdateNotifier updateNotifier = IsisContext.getUpdateNotifier();
+        final SqlExecutionContext context =
+            new SqlExecutionContext(connector, transactionManager, messageBroker, updateNotifier);
+        try {
+            for (final PersistenceCommand command : commands) {
+                command.execute(context);
+            }
+            connector.commit();
+        } catch (final IsisException e) {
+            LOG.warn("Failure during execution", e);
+            connector.rollback();
+            throw e;
+        } finally {
+            connectionPool.release(connector);
+        }
+    }
+
+    public boolean flush(final PersistenceCommand[] commands) {
+        return false;
+    }
+
+    @Override
+    public List<ObjectAdapter> loadInstancesAndAdapt(final PersistenceQuery query) {
+        if (query instanceof PersistenceQueryFindByTitle) {
+            return findByTitle((PersistenceQueryFindByTitle) query);
+        } else if (query instanceof PersistenceQueryFindAllInstances) {
+            return getAllInstances((PersistenceQueryFindAllInstances) query);
+        } else if (query instanceof PersistenceQueryFindByPattern) {
+            return findByPattern((PersistenceQueryFindByPattern) query);
+        } else {
+            throw new SqlObjectStoreException("Query type not supported: " + query);
+        }
+    }
+
+    private List<ObjectAdapter> findByPattern(final PersistenceQueryFindByPattern query) {
+        final ObjectSpecification specification = query.getSpecification();// query.getPattern().getSpecification();//
+                                                                           // getSpecification();
+        final DatabaseConnector connector = connectionPool.acquire();
+        try {
+            final List<ObjectAdapter> matchingInstances = Lists.newArrayList();
+
+            addSpecQueryInstances(specification, connector, query, matchingInstances);
+            return matchingInstances;
+
+        } finally {
+            connectionPool.release(connector);
+        }
+    }
+
+    private void addSpecQueryInstances(final ObjectSpecification specification, final DatabaseConnector connector,
+        final PersistenceQueryFindByPattern query, final List<ObjectAdapter> matchingInstances) {
+
+        if (specification.isAbstract() == false) {
+            final ObjectMapping mapper = objectMappingLookup.getMapping(specification, connector);
+            final Vector<ObjectAdapter> instances = mapper.getInstances(connector, specification, query);
+            matchingInstances.addAll(instances);
+
+        }
+        if (specification.hasSubclasses()) {
+            final List<ObjectSpecification> subclasses = specification.subclasses();
+            for (final ObjectSpecification subclassSpec : subclasses) {
+                addSpecQueryInstances(subclassSpec, connector, query, matchingInstances);
+            }
+        }
+    }
+
+    private List<ObjectAdapter> getAllInstances(final PersistenceQueryFindAllInstances criteria) {
+        final ObjectSpecification spec = criteria.getSpecification();
+        return allInstances(spec);
+    }
+
+    private List<ObjectAdapter> allInstances(final ObjectSpecification spec) {
+        final DatabaseConnector connector = connectionPool.acquire();
+        final List<ObjectAdapter> matchingInstances = Lists.newArrayList();
+
+        addSpecInstances(spec, connector, matchingInstances);
+
+        connectionPool.release(connector);
+        return matchingInstances;
+    }
+
+    private void addSpecInstances(final ObjectSpecification spec, final DatabaseConnector connector,
+        final List<ObjectAdapter> matchingInstances) {
+
+        if (!spec.isAbstract()) {
+            final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connector);
+            final List<ObjectAdapter> instances = mapper.getInstances(connector, spec);
+            matchingInstances.addAll(instances);
+        }
+
+        if (spec.hasSubclasses()) {
+            final List<ObjectSpecification> subclasses = spec.subclasses();
+            for (final ObjectSpecification subclassSpec : subclasses) {
+                addSpecInstances(subclassSpec, connector, matchingInstances);
+            }
+        }
+
+    }
+
+    private List<ObjectAdapter> findByTitle(final PersistenceQueryFindByTitle criteria) {
+        final ObjectSpecification spec = criteria.getSpecification();
+        final DatabaseConnector connector = connectionPool.acquire();
+        final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connector);
+
+        final Vector<ObjectAdapter> instances = mapper.getInstances(connector, spec, criteria.getTitle());
+        connectionPool.release(connector);
+
+        return instances;
+    }
+
+
+    @Override
+    public ObjectAdapter loadInstanceAndAdapt(final TypedOid oid) {
+        final DatabaseConnector connection = connectionPool.acquire();
+        final ObjectSpecification objectSpec = getSpecificationLookup().lookupBySpecId(oid.getObjectSpecId());
+        final ObjectMapping mapper = objectMappingLookup.getMapping(objectSpec, connection);
+        final ObjectAdapter object = mapper.getObject(connection, oid);
+        connectionPool.release(connection);
+        return object;
+    }
+
+    @Override
+    public RootOid getOidForService(ObjectSpecification serviceSpec) {
+
+        final DatabaseConnector connector = connectionPool.acquire();
+        try {
+            final StringBuffer sql = new StringBuffer();
+            sql.append("select ");
+            sql.append(Defaults.getPkIdLabel());
+            sql.append(" from ");
+            sql.append(Sql.tableIdentifier(TABLE_NAME));
+            sql.append(" where ");
+            sql.append(Defaults.getIdColumn());
+            sql.append(" = ?");
+            connector.addToQueryValues(serviceSpec.getSpecId().asString());
+
+            final Results results = connector.select(sql.toString());
+            if (!results.next()) {
+                return null;
+            } 
+            final int id = results.getInt(Defaults.getPkIdLabel());
+            return RootOidDefault.create(serviceSpec.getSpecId(), ""+id);
+            
+        } finally {
+            connectionPool.release(connector);
+        }
+    }
+
+    @Override
+    public boolean hasInstances(final ObjectSpecification spec) {
+        final DatabaseConnector connection = connectionPool.acquire();
+        final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connection);
+        final boolean hasInstances = mapper.hasInstances(connection, spec);
+        connectionPool.release(connection);
+        return hasInstances;
+    }
+
+    @Override
+    public void resolveField(final ObjectAdapter object, final ObjectAssociation field) {
+        if (field.isOneToManyAssociation()) {
+            final DatabaseConnector connection = connectionPool.acquire();
+            final ObjectSpecification spec = object.getSpecification();
+            final ObjectMapping mapper = objectMappingLookup.getMapping(spec, connection);
+            mapper.resolveCollection(connection, object, field);
+            connectionPool.release(connection);
+        } else {
+            resolveImmediately(field.get(object));
+        }
+    }
+
+    @Override
+    public void resolveImmediately(final ObjectAdapter object) {
+        final DatabaseConnector connector = connectionPool.acquire();
+        final ObjectMapping mapping = objectMappingLookup.getMapping(object, connector);
+        mapping.resolve(connector, object);
+        connectionPool.release(connector);
+    }
+
+    ///////////////////////////////////////////////////////////
+    // Dependencies (injected)
+    ///////////////////////////////////////////////////////////
+
+    public void setConnectionPool(final DatabaseConnectorPool connectionPool) {
+        this.connectionPool = connectionPool;
+    }
+
+    public void setMapperLookup(final ObjectMappingLookup mapperLookup) {
+        this.objectMappingLookup = mapperLookup;
+    }
+
+
+    ///////////////////////////////////////////////////////////
+    // Dependencies (from context)
+    ///////////////////////////////////////////////////////////
+    
+    protected AdapterManager getAdapterManager() {
+        return IsisContext.getPersistenceSession().getAdapterManager();
+    }
+
+    protected SpecificationLoader getSpecificationLookup() {
+        return IsisContext.getSpecificationLoader();
+    }
+
+}