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/13 01:01:07 UTC

[33/52] [partial] ISIS-188: renaming packages in line with groupId:artifactId

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/MySqlIntegrationTest.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/MySqlIntegrationTest.java b/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/MySqlIntegrationTest.java
new file mode 100644
index 0000000..eab01ea
--- /dev/null
+++ b/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/MySqlIntegrationTest.java
@@ -0,0 +1,56 @@
+/*
+ *  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.objectstore.sql;
+
+import java.util.Properties;
+
+import org.apache.isis.objectstore.sql.SqlObjectStore;
+import org.apache.isis.objectstore.sql.common.SqlIntegrationTestData;
+
+public class MySqlIntegrationTest extends SqlIntegrationTestData {
+
+    /**/
+    @Override
+    public Properties getProperties() {
+        Properties properties = super.getProperties();
+        if (properties == null) {
+            // Only used if *sql.properties is not found
+            properties = new Properties();
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.driver", "com.mysql.jdbc.Driver");
+            // properties.put(SqlObjectStore.BASE_NAME + ".jdbc.connection",
+            // "jdbc:mysql://abacus/noftest&useTimezone=true&serverTimezone=GMT");
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.connection", "jdbc:mysql://abacus/noftest&useLegacyDatetimeCode=false");
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.user", "nof");
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.jdbc.password", "");
+        }
+        return properties;
+    }
+
+    /**/
+
+    @Override
+    public String getPropertiesFilename() {
+        return "mysql.properties";
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/PostgreSqlIntegrationTest.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/PostgreSqlIntegrationTest.java b/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/PostgreSqlIntegrationTest.java
new file mode 100644
index 0000000..5540fd9
--- /dev/null
+++ b/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/objectstore/sql/PostgreSqlIntegrationTest.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.objectstore.sql;
+
+import java.util.Properties;
+
+import org.apache.isis.objectstore.sql.SqlObjectStore;
+import org.apache.isis.objectstore.sql.common.SqlIntegrationTestData;
+
+public class PostgreSqlIntegrationTest extends SqlIntegrationTestData {
+
+    @Override
+    public Properties getProperties() {
+        Properties properties = super.getProperties();
+        if (properties == null) {
+            properties = new Properties();
+            // Only used if src/test/config/postgresql.properties does not
+            // exist.
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.driver", "org.postgresql.Driver");
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.connection", "jdbc:postgresql://abacus/noftest");
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.user", "nof");
+            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.password", "");
+
+            // properties.put(SqlObjectStore.BASE_NAME + ".datatypes.timestamp",
+            // "TIMESTAMP");
+            // properties.put(SqlObjectStore.BASE_NAME + ".datatypes.datetime",
+            // "TIMESTAMP");
+        }
+        return properties;
+    }
+
+    @Override
+    public String getPropertiesFilename() {
+        return "postgresql.properties";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/MySqlIntegrationTest.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/MySqlIntegrationTest.java b/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/MySqlIntegrationTest.java
deleted file mode 100644
index 6f44816..0000000
--- a/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/MySqlIntegrationTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  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.Properties;
-
-import org.apache.isis.runtimes.dflt.objectstores.sql.common.SqlIntegrationTestData;
-
-public class MySqlIntegrationTest extends SqlIntegrationTestData {
-
-    /**/
-    @Override
-    public Properties getProperties() {
-        Properties properties = super.getProperties();
-        if (properties == null) {
-            // Only used if *sql.properties is not found
-            properties = new Properties();
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.driver", "com.mysql.jdbc.Driver");
-            // properties.put(SqlObjectStore.BASE_NAME + ".jdbc.connection",
-            // "jdbc:mysql://abacus/noftest&useTimezone=true&serverTimezone=GMT");
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.connection", "jdbc:mysql://abacus/noftest&useLegacyDatetimeCode=false");
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.user", "nof");
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.jdbc.password", "");
-        }
-        return properties;
-    }
-
-    /**/
-
-    @Override
-    public String getPropertiesFilename() {
-        return "mysql.properties";
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/PostgreSqlIntegrationTest.java
----------------------------------------------------------------------
diff --git a/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/PostgreSqlIntegrationTest.java b/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/PostgreSqlIntegrationTest.java
deleted file mode 100644
index 1ecdd33..0000000
--- a/component/objectstore/sql/sql-tests-served/src/test/java/org/apache/isis/runtimes/dflt/objectstores/sql/PostgreSqlIntegrationTest.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  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.Properties;
-
-import org.apache.isis.runtimes.dflt.objectstores.sql.common.SqlIntegrationTestData;
-
-public class PostgreSqlIntegrationTest extends SqlIntegrationTestData {
-
-    @Override
-    public Properties getProperties() {
-        Properties properties = super.getProperties();
-        if (properties == null) {
-            properties = new Properties();
-            // Only used if src/test/config/postgresql.properties does not
-            // exist.
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.driver", "org.postgresql.Driver");
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.connection", "jdbc:postgresql://abacus/noftest");
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.user", "nof");
-            properties.put(SqlObjectStore.BASE_NAME + ".jdbc.password", "");
-
-            // properties.put(SqlObjectStore.BASE_NAME + ".datatypes.timestamp",
-            // "TIMESTAMP");
-            // properties.put(SqlObjectStore.BASE_NAME + ".datatypes.datetime",
-            // "TIMESTAMP");
-        }
-        return properties;
-    }
-
-    @Override
-    public String getPropertiesFilename() {
-        return "postgresql.properties";
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlObjectStore.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlObjectStore.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlObjectStore.java
new file mode 100644
index 0000000..68a9abe
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlObjectStore.java
@@ -0,0 +1,460 @@
+/*
+ *  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.objectstore.xml;
+
+import java.text.MessageFormat;
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.commons.debug.DebugBuilder;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.xml.XmlFile;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ResolveState;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+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.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
+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.core.runtime.persistence.ObjectNotFoundException;
+import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
+import org.apache.isis.core.runtime.persistence.PersistorUtil;
+import org.apache.isis.core.runtime.persistence.objectstore.ObjectStoreSpi;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.SaveObjectCommand;
+import org.apache.isis.core.runtime.persistence.query.PersistenceQueryBuiltIn;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+import org.apache.isis.core.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.core.runtime.system.persistence.PersistenceQuery;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.objectstore.xml.internal.clock.Clock;
+import org.apache.isis.objectstore.xml.internal.commands.XmlCreateObjectCommand;
+import org.apache.isis.objectstore.xml.internal.commands.XmlDestroyObjectCommand;
+import org.apache.isis.objectstore.xml.internal.commands.XmlUpdateObjectCommand;
+import org.apache.isis.objectstore.xml.internal.data.CollectionData;
+import org.apache.isis.objectstore.xml.internal.data.Data;
+import org.apache.isis.objectstore.xml.internal.data.DataManager;
+import org.apache.isis.objectstore.xml.internal.data.ListOfRootOid;
+import org.apache.isis.objectstore.xml.internal.data.ObjectData;
+import org.apache.isis.objectstore.xml.internal.data.ObjectDataVector;
+import org.apache.isis.objectstore.xml.internal.data.xml.Utils;
+import org.apache.isis.objectstore.xml.internal.data.xml.XmlDataManager;
+import org.apache.isis.objectstore.xml.internal.services.ServiceManager;
+import org.apache.isis.objectstore.xml.internal.services.xml.XmlServiceManager;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+public class XmlObjectStore implements ObjectStoreSpi {
+
+    private static final Logger LOG = Logger.getLogger(XmlObjectStore.class);
+    private static final String XMLOS_DIR = ConfigurationConstants.ROOT + "xmlos.dir";
+    private final DataManager dataManager;
+    private final ServiceManager serviceManager;
+    private boolean isFixturesInstalled;
+
+    public XmlObjectStore(final IsisConfiguration configuration) {
+        final String charset = Utils.lookupCharset(configuration);
+        final String directory = configuration.getString(XMLOS_DIR, "xml/objects");
+        final XmlFile xmlFile = new XmlFile(charset, directory);
+        dataManager = new XmlDataManager(xmlFile);
+        serviceManager = new XmlServiceManager(xmlFile);
+        serviceManager.loadServices();
+    }
+
+    public XmlObjectStore(final DataManager dataManager, final ServiceManager serviceManager) {
+        this.dataManager = dataManager;
+        this.serviceManager = serviceManager;
+        serviceManager.loadServices();
+    }
+
+    // /////////////////////////////////////////////////////////
+    // name
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public String name() {
+        return "XML";
+    }
+
+    // /////////////////////////////////////////////////////////
+    // close
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public void close() {
+        LOG.info("close " + this);
+    }
+
+    // /////////////////////////////////////////////////////////
+    // reset
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public void reset() {
+    }
+
+    // /////////////////////////////////////////////////////////
+    // init, shutdown, finalize
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public boolean hasInstances(final ObjectSpecification cls) {
+        LOG.debug("checking instance of " + cls);
+        final ObjectData data = new ObjectData(RootOidDefault.create(cls.getSpecId(), "---dummy-value-never-used---"), null);
+        return dataManager.numberOfInstances(data) > 0;
+    }
+
+    @Override
+    public void open() throws ObjectPersistenceException {
+        isFixturesInstalled = dataManager.isFixturesInstalled();
+    }
+
+    @Override
+    public boolean isFixturesInstalled() {
+        return isFixturesInstalled;
+    }
+
+    private void initObject(final ObjectAdapter adapter, final ObjectData data) {
+        if (!adapter.canTransitionToResolving()) {
+            return;
+        } 
+        try {
+            PersistorUtil.startResolving(adapter);
+            final List<ObjectAssociation> fields = adapter.getSpecification().getAssociations();
+            for (int i = 0; i < fields.size(); i++) {
+                final ObjectAssociation field = fields.get(i);
+                if (field.isNotPersisted()) {
+                    continue;
+                }
+
+                final ObjectSpecification fieldSpecification = field.getSpecification();
+                if (fieldSpecification.isEncodeable()) {
+                    final EncodableFacet encoder = fieldSpecification.getFacet(EncodableFacet.class);
+                    ObjectAdapter value;
+                    final String valueData = data.value(field.getId());
+                    if (valueData != null) {
+                        if (valueData.equals("NULL")) {
+                            value = null;
+                        } else {
+                            value = encoder.fromEncodedString(valueData);
+                        }
+                        ((OneToOneAssociation) field).initAssociation(adapter, value);
+                    }
+                } else if (field.isOneToManyAssociation()) {
+                    initObjectSetupCollection(adapter, data, field);
+                } else if (field.isOneToOneAssociation()) {
+                    initObjectSetupReference(adapter, data, field);
+                }
+            }
+            adapter.setVersion(data.getVersion());
+        } finally {
+            PersistorUtil.toEndState(adapter);
+        }
+    }
+
+    private void initObjectSetupReference(final ObjectAdapter object, final ObjectData data, final ObjectAssociation field) {
+    	
+        final RootOid referencedOid = (RootOidDefault) data.get(field.getId());
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("setting up field " + field + " with " + referencedOid);
+        }
+        if (referencedOid == null) {
+            return;
+        }
+
+        final Data fieldData = dataManager.loadData(referencedOid);
+
+        final ObjectAdapter referencedAdapter = getAdapterManager().adapterFor(referencedOid);
+        if (fieldData == null) {
+            if (!referencedAdapter.isDestroyed()) {
+                referencedAdapter.changeState(ResolveState.DESTROYED);
+            }
+            LOG.warn("No data found for " + referencedOid + " so field '" + field.getName() + "' not set in object '" + object.titleString() + "'");
+        }
+        ((OneToOneAssociation) field).initAssociation(object, referencedAdapter);
+
+        // REVIEW: what was this commented out code for?
+        /*
+         * if (loadedObjects().isLoaded(referenceOid)) { ObjectAdapter
+         * loadedObject = loadedObjects().getLoadedObject(referenceOid);
+         * LOG.debug("using loaded object " + loadedObject);
+         * object.initAssociation((OneToOneAssociation) field, loadedObject); }
+         * else { ObjectAdapter fieldObject; Data fieldData = (Data)
+         * dataManager.loadData((SerialOid) referenceOid);
+         * 
+         * if (fieldData != null) { fieldObject = (ObjectAdapter)
+         * specFor(fieldData).acquireInstance(); } else { fieldObject =
+         * (ObjectAdapter) field.getSpecification().acquireInstance(); }
+         * 
+         * fieldObject.setOid(referenceOid);
+         * 
+         * if (fieldObject instanceof CollectionAdapter) {
+         * fieldObject.setResolved(); }
+         * 
+         * loadedObjects().loaded(fieldObject);
+         * object.initAssociation((OneToOneAssociation) field, fieldObject); }
+         */
+    }
+
+    private void initObjectSetupCollection(final ObjectAdapter objectAdapter, final ObjectData data, final ObjectAssociation field) {
+        /*
+         * The internal collection is already a part of the object, and
+         * therefore cannot be recreated, but its oid must be set
+         */
+        final ListOfRootOid refs = (ListOfRootOid) data.get(field.getId());
+        
+        final ObjectAdapter collectionAdapter = field.get(objectAdapter);
+        if (!collectionAdapter.canTransitionToResolving()) {
+            return;
+        } 
+        
+        try {
+            PersistorUtil.startResolving(collectionAdapter);
+            final int size = refs == null ? 0 : refs.size();
+            final ObjectAdapter[] elements = new ObjectAdapter[size];
+            for (int j = 0; j < size; j++) {
+                final RootOid elementOid = refs.elementAt(j);
+                ObjectAdapter adapter;
+                adapter = getAdapterManager().getAdapterFor(elementOid);
+                if (adapter == null) {
+                    adapter = loadInstanceAndAdapt(elementOid);
+                }
+                elements[j] = adapter;
+            }
+            final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collectionAdapter);
+            facet.init(collectionAdapter, elements);
+        } finally {
+            PersistorUtil.toEndState(collectionAdapter);
+        }
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Transaction Management
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public void startTransaction() {
+        LOG.debug("start transaction");
+    }
+
+    @Override
+    public void endTransaction() {
+        LOG.debug("end transaction");
+    }
+
+    @Override
+    public void abortTransaction() {
+        LOG.debug("transaction aborted");
+    }
+
+    // /////////////////////////////////////////////////////////
+    // createXxxCommands
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public CreateObjectCommand createCreateObjectCommand(final ObjectAdapter object) {
+        return new XmlCreateObjectCommand(object, dataManager);
+    }
+
+    @Override
+    public SaveObjectCommand createSaveObjectCommand(final ObjectAdapter object) {
+        return new XmlUpdateObjectCommand(object, dataManager);
+    }
+
+    @Override
+    public DestroyObjectCommand createDestroyObjectCommand(final ObjectAdapter object) {
+        return new XmlDestroyObjectCommand(object, dataManager);
+    }
+
+    // /////////////////////////////////////////////////////////
+    // execute, flush
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public void execute(final List<PersistenceCommand> commands) {
+        LOG.debug("start execution of transaction");
+        for (final PersistenceCommand command : commands) {
+            command.execute(null);
+        }
+        LOG.debug("end execution");
+    }
+
+    // /////////////////////////////////////////////////////////
+    // getObject, resolveImmediately, resolveField
+    // /////////////////////////////////////////////////////////
+
+
+    @Override
+    public ObjectAdapter loadInstanceAndAdapt(final TypedOid oid) {
+        LOG.debug("getObject " + oid);
+        final Data data = dataManager.loadData((RootOidDefault) oid);
+        LOG.debug("  data read " + data);
+
+        ObjectAdapter object;
+
+        if (data instanceof ObjectData) {
+            object = recreateAdapter((ObjectData) data);
+        } else if (data instanceof CollectionData) {
+            throw new IsisException();
+        } else {
+            throw new ObjectNotFoundException(oid);
+        }
+        return object;
+    }
+
+    @Override
+    public void resolveField(final ObjectAdapter object, final ObjectAssociation field) {
+        final ObjectAdapter reference = field.get(object);
+        resolveImmediately(reference);
+    }
+
+    @Override
+    public void resolveImmediately(final ObjectAdapter object) {
+        final ObjectData data = (ObjectData) dataManager.loadData((RootOidDefault) object.getOid());
+        Assert.assertNotNull("Not able to read in data during resolve", object, data);
+        initObject(object, data);
+    }
+
+    /*
+     * The ObjectData holds all references for internal collections, so the
+     * object should haves its internal collection populated by this method.
+     */
+    private ObjectAdapter recreateAdapter(final ObjectData data) {
+        final RootOid oid = data.getRootOid();
+        final ObjectAdapter adapter = getAdapterManager().adapterFor(oid);
+        initObject(adapter, data);
+        return adapter;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // getInstances, allInstances
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public List<ObjectAdapter> loadInstancesAndAdapt(final PersistenceQuery persistenceQuery) {
+
+        if (!(persistenceQuery instanceof PersistenceQueryBuiltIn)) {
+            throw new IllegalArgumentException(MessageFormat.format("Provided PersistenceQuery not supported; was {0}; " + "the XML object store only supports {1}", persistenceQuery.getClass().getName(), PersistenceQueryBuiltIn.class.getName()));
+        }
+        final PersistenceQueryBuiltIn builtIn = (PersistenceQueryBuiltIn) persistenceQuery;
+
+        final ObjectSpecification objSpec = builtIn.getSpecification();
+        LOG.debug("getInstances of " + objSpec + " where " + builtIn);
+        final RootOid oid = RootOidDefault.create(objSpec.getSpecId(), "dummy");
+        final ObjectData patternData = new ObjectData(oid, null);
+        return getInstances(patternData, builtIn);
+    }
+
+    private List<ObjectAdapter> getInstances(final ObjectData patternData, final PersistenceQueryBuiltIn persistenceQuery) {
+        final ObjectDataVector data = dataManager.getInstances(patternData);
+        final List<ObjectAdapter> instances = Lists.newArrayList();
+        
+        for (int i = 0; i < data.size(); i++) {
+            final ObjectData instanceData = data.element(i);
+            if(LOG.isDebugEnabled()) {
+                LOG.debug("instance data " + instanceData);
+            }
+
+            final RootOid oid = instanceData.getRootOid();
+
+            final ObjectAdapter adapter = getAdapterManager().adapterFor(oid);
+            if(LOG.isDebugEnabled()) {
+                LOG.debug("recreated instance " + adapter);
+            }
+            initObject(adapter, instanceData);
+
+            if (persistenceQuery == null || persistenceQuery.matches(adapter)) {
+                instances.add(adapter);
+            }
+        }
+        return instances;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // services
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public RootOid getOidForService(ObjectSpecification serviceSpec) {
+        return serviceManager.getOidForService(serviceSpec.getSpecId());
+    }
+
+    @Override
+    public void registerService(final RootOid rootOid) {
+        serviceManager.registerService(rootOid);
+    }
+
+    // /////////////////////////////////////////////////////////
+    // debugging
+    // /////////////////////////////////////////////////////////
+
+    @Override
+    public void debugData(final DebugBuilder debug) {
+        debug.appendTitle("Business Objects");
+        debug.appendln(dataManager.getDebugData());
+    }
+
+    @Override
+    public String debugTitle() {
+        return "XML Object Store";
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Dependencies (injected)
+    // /////////////////////////////////////////////////////////
+
+    /**
+     * Set the clock used to generate sequence numbers and last changed dates
+     * for version objects.
+     */
+    public void setClock(final Clock clock) {
+        FileVersion.setClock(clock);
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Dependencies (from singleton)
+    // /////////////////////////////////////////////////////////
+
+    protected SpecificationLoaderSpi getSpecificationLookup() {
+        return IsisContext.getSpecificationLoader();
+    }
+
+    private AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlPersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlPersistenceMechanismInstaller.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlPersistenceMechanismInstaller.java
new file mode 100644
index 0000000..d3c430f
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/XmlPersistenceMechanismInstaller.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.objectstore.xml;
+
+import java.util.Date;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapterFactory;
+import org.apache.isis.core.runtime.installerregistry.installerapi.PersistenceMechanismInstallerAbstract;
+import org.apache.isis.core.runtime.persistence.objectstore.ObjectStoreSpi;
+import org.apache.isis.core.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.core.runtime.system.persistence.IdentifierGenerator;
+import org.apache.isis.core.runtime.system.persistence.IdentifierGeneratorDefault;
+import org.apache.isis.objectstore.xml.internal.clock.DefaultClock;
+
+public class XmlPersistenceMechanismInstaller extends PersistenceMechanismInstallerAbstract {
+
+    public static final String NAME = "xml";
+    
+    private XmlObjectStore objectStore;
+
+    public XmlPersistenceMechanismInstaller() {
+        super(NAME);
+    }
+
+    @Override
+    protected ObjectStoreSpi createObjectStore(final IsisConfiguration configuration, final ObjectAdapterFactory objectFactory, final AdapterManagerSpi adapterManager) {
+        if (objectStore == null) {
+            objectStore = new XmlObjectStore(configuration);
+            objectStore.setClock(new DefaultClock());
+        }
+        return objectStore;
+    }
+
+    @Override
+    public IdentifierGenerator createIdentifierGenerator(final IsisConfiguration configuration) {
+        final long currentTime = new Date().getTime();
+        return new IdentifierGeneratorDefault(currentTime);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/Clock.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/Clock.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/Clock.java
new file mode 100644
index 0000000..8d31534
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/Clock.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.objectstore.xml.internal.clock;
+
+public interface Clock {
+
+    long getTime();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/DefaultClock.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/DefaultClock.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/DefaultClock.java
new file mode 100644
index 0000000..81bb4cc
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/clock/DefaultClock.java
@@ -0,0 +1,28 @@
+/*
+ *  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.objectstore.xml.internal.clock;
+
+public class DefaultClock implements Clock {
+    @Override
+    public long getTime() {
+        return System.currentTimeMillis();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/AbstractXmlPersistenceCommand.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/AbstractXmlPersistenceCommand.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/AbstractXmlPersistenceCommand.java
new file mode 100644
index 0000000..69f99e3
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/AbstractXmlPersistenceCommand.java
@@ -0,0 +1,98 @@
+/*
+ *  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.objectstore.xml.internal.commands;
+
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
+import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommandAbstract;
+import org.apache.isis.objectstore.xml.internal.data.DataManager;
+import org.apache.isis.objectstore.xml.internal.data.ObjectData;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+abstract class AbstractXmlPersistenceCommand extends PersistenceCommandAbstract {
+    private static final Logger LOG = Logger.getLogger(AbstractXmlPersistenceCommand.class);
+
+    private final DataManager dataManager;
+
+    public AbstractXmlPersistenceCommand(final ObjectAdapter adapter, final DataManager dataManager) {
+        super(adapter);
+        this.dataManager = dataManager;
+    }
+
+    protected DataManager getDataManager() {
+        return dataManager;
+    }
+
+    protected ObjectData createObjectData(final ObjectAdapter adapter, final boolean ensurePersistent) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("compiling object data for " + adapter);
+        }
+
+        final ObjectSpecification adapterSpec = adapter.getSpecification();
+        final ObjectData data = new ObjectData((RootOidDefault) adapter.getOid(), adapter.getVersion());
+
+        final List<ObjectAssociation> associations = adapterSpec.getAssociations();
+        for (final ObjectAssociation association : associations) {
+            if (association.isNotPersisted()) {
+                continue;
+            }
+
+            final ObjectAdapter associatedObject = association.get(adapter);
+            final boolean isEmpty = association.isEmpty(adapter);
+            final String associationId = association.getId();
+
+            if (association.isOneToManyAssociation()) {
+                saveCollection(associationId, data, associatedObject, ensurePersistent);
+            } else if (association.getSpecification().isEncodeable()) {
+                saveEncoded(data, associationId, associatedObject, isEmpty);
+            } else if (association.isOneToOneAssociation()) {
+                saveReference(data, associationId, associatedObject, ensurePersistent);
+            }
+        }
+
+        return data;
+    }
+
+    private void saveReference(final ObjectData data, final String associationId, final ObjectAdapter associatedObject, final boolean ensurePersistent) {
+        data.addAssociation(associatedObject, associationId, ensurePersistent);
+    }
+
+    private void saveCollection(final String associationId, final ObjectData data, final ObjectAdapter associatedObject, final boolean ensurePersistent) {
+        data.addInternalCollection(associatedObject, associationId, ensurePersistent);
+    }
+
+    private void saveEncoded(final ObjectData data, final String associationId, final ObjectAdapter associatedObject, final boolean isEmpty) {
+        if (associatedObject == null || isEmpty) {
+            data.saveValue(associationId, isEmpty, null);
+        } else {
+            final EncodableFacet facet = associatedObject.getSpecification().getFacet(EncodableFacet.class);
+            final String encodedValue = facet.toEncodedString(associatedObject);
+            data.saveValue(associationId, isEmpty, encodedValue);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlCreateObjectCommand.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlCreateObjectCommand.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlCreateObjectCommand.java
new file mode 100644
index 0000000..9912730
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlCreateObjectCommand.java
@@ -0,0 +1,54 @@
+/*
+ *  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.objectstore.xml.internal.commands;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.CreateObjectCommand;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+import org.apache.isis.objectstore.xml.internal.data.DataManager;
+import org.apache.isis.objectstore.xml.internal.data.ObjectData;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+public final class XmlCreateObjectCommand extends AbstractXmlPersistenceCommand implements CreateObjectCommand {
+    private static final Logger LOG = Logger.getLogger(XmlCreateObjectCommand.class);
+
+    public XmlCreateObjectCommand(final ObjectAdapter adapter, final DataManager dataManager) {
+        super(adapter, dataManager);
+    }
+
+    @Override
+    public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("  create object " + onAdapter());
+        }
+        final String user = getAuthenticationSession().getUserName();
+        onAdapter().setVersion(FileVersion.create(user));
+        final ObjectData data = createObjectData(onAdapter(), true);
+        getDataManager().insertObject(data);
+    }
+
+    @Override
+    public String toString() {
+        return "CreateObjectCommand [object=" + onAdapter() + "]";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlDestroyObjectCommand.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlDestroyObjectCommand.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlDestroyObjectCommand.java
new file mode 100644
index 0000000..736d2eb
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlDestroyObjectCommand.java
@@ -0,0 +1,52 @@
+/*
+ *  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.objectstore.xml.internal.commands;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.RootOidDefault;
+import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+import org.apache.isis.objectstore.xml.internal.data.DataManager;
+
+public final class XmlDestroyObjectCommand extends AbstractXmlPersistenceCommand implements DestroyObjectCommand {
+    private static final Logger LOG = Logger.getLogger(XmlDestroyObjectCommand.class);
+
+    public XmlDestroyObjectCommand(final ObjectAdapter adapter, final DataManager dataManager) {
+        super(adapter, dataManager);
+    }
+
+    @Override
+    public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("  destroy object " + onAdapter());
+        }
+        final RootOidDefault oid = (RootOidDefault) onAdapter().getOid();
+        getDataManager().remove(oid);
+        onAdapter().setVersion(null);
+    }
+
+    @Override
+    public String toString() {
+        return "DestroyObjectCommand [object=" + onAdapter() + "]";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlUpdateObjectCommand.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlUpdateObjectCommand.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlUpdateObjectCommand.java
new file mode 100644
index 0000000..9ca300d
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/commands/XmlUpdateObjectCommand.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.objectstore.xml.internal.commands;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+import org.apache.isis.core.runtime.persistence.objectstore.transaction.SaveObjectCommand;
+import org.apache.isis.objectstore.xml.internal.data.Data;
+import org.apache.isis.objectstore.xml.internal.data.DataManager;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+public final class XmlUpdateObjectCommand extends AbstractXmlPersistenceCommand implements SaveObjectCommand {
+
+    private static final Logger LOG = Logger.getLogger(XmlUpdateObjectCommand.class);
+
+    public XmlUpdateObjectCommand(final ObjectAdapter adapter, final DataManager dataManager) {
+        super(adapter, dataManager);
+    }
+
+    @Override
+    public void execute(final PersistenceCommandContext context) throws ObjectPersistenceException {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("  save object " + onAdapter());
+        }
+        final String user = getAuthenticationSession().getUserName();
+        onAdapter().setVersion(FileVersion.create(user));
+
+        final Data data = createObjectData(onAdapter(), true);
+        getDataManager().save(data);
+    }
+
+    @Override
+    public String toString() {
+        return "SaveObjectCommand [object=" + onAdapter() + "]";
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/CollectionData.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/CollectionData.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/CollectionData.java
new file mode 100644
index 0000000..e45b034
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/CollectionData.java
@@ -0,0 +1,52 @@
+/*
+ *  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.objectstore.xml.internal.data;
+
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+/**
+ * A logical collection of elements of a specified type
+ */
+public class CollectionData extends Data {
+    private final ListOfRootOid elements = new ListOfRootOid();
+
+    public CollectionData(final RootOid oid, final Version version) {
+        super(oid, version);
+    }
+
+    public void addElement(final RootOid elementOid) {
+        elements.add(elementOid);
+    }
+
+    public void removeElement(final RootOid elementOid) {
+        elements.remove(elementOid);
+    }
+
+    public ListOfRootOid references() {
+        return elements;
+    }
+
+    @Override
+    public String toString() {
+        return "CollectionData[type=" + getObjectSpecId() + ",elements=" + elements + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/Data.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/Data.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/Data.java
new file mode 100644
index 0000000..baa48fd
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/Data.java
@@ -0,0 +1,80 @@
+/*
+ *  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.objectstore.xml.internal.data;
+
+import com.google.common.base.Objects;
+
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.SpecificationLoader;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+public abstract class Data {
+    
+    private final RootOid oid;
+    private final Version version;
+
+    Data(final RootOid oid, final Version version) {
+        this.oid = oid;
+        this.version = version;
+    }
+
+    public RootOid getRootOid() {
+        return oid;
+    }
+
+    public Version getVersion() {
+        return version;
+    }
+
+    public ObjectSpecification getSpecification(SpecificationLoader specificationLookup) {
+        final ObjectSpecId objectSpecId = oid.getObjectSpecId();
+        return specificationLookup.lookupBySpecId(objectSpecId);
+    }
+
+    public ObjectSpecId getObjectSpecId() {
+        return getRootOid().getObjectSpecId();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj instanceof Data) {
+            final Data data = (Data) obj;
+            return Objects.equal(data.getObjectSpecId(), getObjectSpecId()) && Objects.equal(data.oid, oid);
+        }
+
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int h = 17;
+        h = 37 * h + getObjectSpecId().hashCode();
+        h = 37 * h + oid.hashCode();
+        return h;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/DataManager.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/DataManager.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/DataManager.java
new file mode 100644
index 0000000..4f3ab9b
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/DataManager.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.objectstore.xml.internal.data;
+
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
+import org.apache.isis.core.runtime.persistence.ObjectPersistenceException;
+
+public interface DataManager {
+
+    void shutdown();
+
+    /**
+     * Return data for all instances that match the pattern.
+     */
+    public ObjectDataVector getInstances(final ObjectData pattern);
+
+    /**
+     * Return the number of instances that match the specified data
+     */
+    public int numberOfInstances(final ObjectData pattern);
+
+    public Data loadData(final RootOid oid);
+
+    /**
+     * Save the data for an object and adds the reference to a list of instances
+     */
+    void insertObject(ObjectData data);
+
+    void remove(RootOid oid) throws ObjectNotFoundException, ObjectPersistenceException;
+
+    /**
+     * Save the data for latter retrieval.
+     */
+    void save(Data data);
+
+    String getDebugData();
+
+    boolean isFixturesInstalled();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ListOfRootOid.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ListOfRootOid.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ListOfRootOid.java
new file mode 100644
index 0000000..459d218
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ListOfRootOid.java
@@ -0,0 +1,75 @@
+/*
+ *  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.objectstore.xml.internal.data;
+
+import java.util.List;
+
+import com.google.common.collect.Lists;
+
+import org.apache.isis.core.commons.lang.ToString;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+
+public class ListOfRootOid {
+    
+    private final List<RootOid> elements = Lists.newArrayList();
+
+    public void add(final RootOid oid) {
+        elements.add(oid);
+    }
+
+    public void remove(final RootOid oid) {
+        elements.remove(oid);
+    }
+
+    public int size() {
+        return elements.size();
+    }
+
+    public RootOid elementAt(final int index) {
+        return elements.get(index);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj instanceof ListOfRootOid) {
+            return ((ListOfRootOid) obj).elements.equals(elements);
+        }
+
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        int h = 17;
+        h = 37 * h + elements.hashCode();
+        return h;
+    }
+
+    @Override
+    public String toString() {
+        final ToString str = new ToString(this);
+        str.append("refs", elements);
+        return str.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectData.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectData.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectData.java
new file mode 100644
index 0000000..cd1e682
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectData.java
@@ -0,0 +1,158 @@
+/*
+ *  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.objectstore.xml.internal.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+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.version.Version;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+import org.apache.isis.objectstore.xml.internal.version.FileVersion;
+
+/**
+ * A logical collection of elements of a specified type
+ */
+public class ObjectData extends Data {
+    private final Map<String, Object> fieldById;
+
+    public ObjectData(final RootOid oid, final Version version) {
+        super(oid, version);
+        fieldById = new HashMap<String, Object>();
+    }
+
+    public Iterable<String> fields() {
+        return fieldById.keySet();
+    }
+
+    // ////////////////////////////////////////////////////////
+    // id
+    // ////////////////////////////////////////////////////////
+
+    public String id(final String fieldId) {
+        final Object field = get(fieldId);
+        return field == null ? null : "" + ((RootOidDefault) field).getIdentifier();
+    }
+
+    // ////////////////////////////////////////////////////////
+    // value
+    // ////////////////////////////////////////////////////////
+
+    public void set(final String fieldId, final String value) {
+        fieldById.put(fieldId, value);
+    }
+
+    public void saveValue(final String fieldId, final boolean isEmpty, final String encodedString) {
+        if (isEmpty) {
+            fieldById.remove(fieldId);
+        } else {
+            fieldById.put(fieldId, encodedString);
+        }
+    }
+
+    public String value(final String fieldId) {
+        return (String) get(fieldId);
+    }
+
+    // ////////////////////////////////////////////////////////
+    // reference
+    // ////////////////////////////////////////////////////////
+
+    public Object get(final String fieldId) {
+        return fieldById.get(fieldId);
+    }
+
+    public void set(final String fieldId, final Object oid) {
+        if (oid == null) {
+            fieldById.remove(fieldId);
+        } else {
+            fieldById.put(fieldId, oid);
+        }
+    }
+
+    // ////////////////////////////////////////////////////////
+    // collection
+    // ////////////////////////////////////////////////////////
+
+    public void initCollection(final String fieldId) {
+        fieldById.put(fieldId, new ListOfRootOid());
+    }
+
+    public void addElement(final String fieldId, final RootOidDefault elementOid) {
+        if (!fieldById.containsKey(fieldId)) {
+            throw new IsisException("Field " + fieldId + " not found  in hashtable");
+        }
+
+        final ListOfRootOid v = (ListOfRootOid) fieldById.get(fieldId);
+        v.add(elementOid);
+    }
+
+    public ListOfRootOid elements(final String fieldId) {
+        return (ListOfRootOid) fieldById.get(fieldId);
+    }
+
+    public void addAssociation(final ObjectAdapter fieldContent, final String fieldId, final boolean ensurePersistent) {
+        final boolean notAlreadyPersistent = fieldContent != null && fieldContent.isTransient();
+        if (ensurePersistent && notAlreadyPersistent) {
+            throw new IllegalStateException("Cannot save an object that is not persistent: " + fieldContent);
+        }
+        // LOG.debug("adding reference field " + fieldId +" " + fieldContent);
+        set(fieldId, fieldContent == null ? null : fieldContent.getOid());
+    }
+
+    public void addInternalCollection(final ObjectAdapter collection, final String fieldId, final boolean ensurePersistent) {
+        /*
+         * if (ensurePersistent && collection != null && collection.getOid() ==
+         * null) { throw new
+         * IllegalStateException("Cannot save a collection that is not persistent: "
+         * + collection); }
+         */
+
+        initCollection(fieldId);
+
+        // int size = collection.size();
+
+        final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collection);
+        for (final ObjectAdapter element : facet.iterable(collection)) {
+            // LOG.debug("adding element to internal collection field " +
+            // fieldId +" " + element);
+            final Object elementOid = element.getOid();
+            if (elementOid == null) {
+                throw new IllegalStateException("Element is not persistent " + element);
+            }
+
+            addElement(fieldId, (RootOidDefault) elementOid);
+        }
+    }
+
+    // ////////////////////////////////////////////////////////
+    // toString
+    // ////////////////////////////////////////////////////////
+
+    @Override
+    public String toString() {
+        return "ObjectData[type=" + getObjectSpecId() + ",oid=" + getRootOid() + ",fields=" + fieldById + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectDataVector.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectDataVector.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectDataVector.java
new file mode 100644
index 0000000..83942cf
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/ObjectDataVector.java
@@ -0,0 +1,42 @@
+/*
+ *  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.objectstore.xml.internal.data;
+
+import java.util.Vector;
+
+public class ObjectDataVector {
+    Vector elements = new Vector();
+
+    public void addElement(final ObjectData instanceData) {
+        elements.addElement(instanceData);
+    }
+
+    public int size() {
+        return elements.size();
+    }
+
+    public ObjectData element(final int i) {
+        return (ObjectData) elements.elementAt(i);
+    }
+
+    public boolean contains(final ObjectData data) {
+        return elements.contains(data);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/PersistorException.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/PersistorException.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/PersistorException.java
new file mode 100644
index 0000000..e81a9d2
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/PersistorException.java
@@ -0,0 +1,42 @@
+/*
+ *  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.objectstore.xml.internal.data;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+
+public class PersistorException extends IsisException {
+    private static final long serialVersionUID = 1L;
+
+    public PersistorException() {
+        super();
+    }
+
+    public PersistorException(final String message) {
+        super(message);
+    }
+
+    public PersistorException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+    public PersistorException(final Throwable cause) {
+        super(cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/951a0fe4/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/xml/Utils.java
----------------------------------------------------------------------
diff --git a/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/xml/Utils.java b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/xml/Utils.java
new file mode 100644
index 0000000..7c39d1e
--- /dev/null
+++ b/component/objectstore/xml/src/main/java/org/apache/isis/objectstore/xml/internal/data/xml/Utils.java
@@ -0,0 +1,56 @@
+/*
+ *  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.objectstore.xml.internal.data.xml;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+
+public class Utils {
+    
+    private Utils(){}
+
+    public static final String ENCODING_PROPERTY = ConfigurationConstants.ROOT + "xmlos.encoding";
+    public static final String DEFAULT_ENCODING = "ISO-8859-1";
+
+    public static String lookupCharset(final IsisConfiguration configuration) {
+        return configuration.getString(ENCODING_PROPERTY, DEFAULT_ENCODING);
+    }
+
+    public static String attribute(final String name, final String value) {
+        return appendAttribute(new StringBuilder(), name, value).toString();
+    }
+
+    public static StringBuilder appendAttribute(StringBuilder buf, final String name, final String value) {
+        return buf.append(" ").append(name).append("=\"").append(value).append("\"");
+    }
+
+    public static Writer appendAttribute(Writer buf, final String name, final String value) throws IOException {
+        buf.append(" ");
+        buf.append(name);
+        buf.append("=\"");
+        buf.append(value);
+        buf.append("\"");
+        return buf;
+    }
+
+}