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 08:30:04 UTC
[39/58] [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;
+ }
+
+}