isis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From danhayw...@apache.org
Subject [14/51] [partial] ISIS-188: moving components into correct directories.
Date Thu, 06 Dec 2012 11:09:55 GMT
http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
new file mode 100644
index 0000000..5a90808
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
@@ -0,0 +1,261 @@
+/*
+ *  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.jdo.datanucleus;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+import org.apache.isis.core.commons.components.Installer;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapterFactory;
+import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
+import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.progmodel.facets.object.ignore.jdo.RemoveJdoEnhancementTypesFacetFactory;
+import org.apache.isis.core.progmodel.facets.object.ignore.jdo.RemoveJdoPrefixedMethodsFacetFactory;
+import org.apache.isis.runtimes.dflt.bytecode.identity.objectfactory.ObjectFactoryBasic;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.applib.AuditService;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.bytecode.DataNucleusTypesClassSubstitutor;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.adaptermanager.DataNucleusPojoRecreator;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.spi.DataNucleusIdentifierGenerator;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.spi.DataNucleusSimplePersistAlgorithm;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.spi.DataNucleusTransactionManager;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.auditable.AuditableAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.auditable.AuditableMarkerInterfaceFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.datastoreidentity.JdoDatastoreIdentityAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.discriminator.JdoDiscriminatorAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.embeddedonly.JdoEmbeddedOnlyAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.query.JdoQueryAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.prop.primarykey.JdoPrimaryKeyAnnotationFacetFactory;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.specloader.validator.JdoMetaModelValidator;
+import org.apache.isis.runtimes.dflt.runtime.installerregistry.installerapi.PersistenceMechanismInstallerAbstract;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.ObjectStoreSpi;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.algorithm.PersistAlgorithm;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.TransactionalResource;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.IdentifierGenerator;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.ObjectFactory;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSessionFactory;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.EnlistedObjectDirtying;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransactionManager;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+/**
+ * Configuration files are read in the usual fashion (as per {@link Installer#getConfigurationResources()}, ie will consult all of:
+ * <ul>
+ * <li><tt>persistor_datanucleus.properties</tt>
+ * <li><tt>persistor.properties</tt>
+ * <li><tt>isis.properties</tt>
+ * </ul>
+ * 
+ * <p>
+ * With respect to configuration, all properties under {@value #ISIS_CONFIG_PREFIX} prefix are passed 
+ * through verbatim to the DataNucleus runtime. For example:
+ * <table>
+ * <tr><th>Isis Property</th><th>DataNucleus Property</th></tr>
+ * <tr><td><tt>isis.persistor.datanucleus.impl.datanucleus.foo.Bar</tt></td><td><tt>datanucleus.foo.Bar</tt></td></tr>
+ * </table>
+ *
+ */
+public class DataNucleusPersistenceMechanismInstaller extends PersistenceMechanismInstallerAbstract {
+
+    private static final Predicate<Object> LOCATE_AUDIT_SERVICE = new Predicate<Object>() {
+
+        @Override
+        public boolean apply(Object input) {
+            return input instanceof AuditService;
+        }
+    };
+
+    public static final String NAME = "datanucleus";
+    private static final String ISIS_CONFIG_PREFIX = "isis.persistor.datanucleus.impl";
+
+    private DataNucleusApplicationComponents applicationComponents = null;
+
+    // only search once
+    private boolean searchedForAuditService;
+    private AuditService auditService;
+    
+    public DataNucleusPersistenceMechanismInstaller() {
+        super(NAME);
+    }
+
+    
+    ////////////////////////////////////////////////////////////////////////
+    // createObjectStore
+    ////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected ObjectStoreSpi createObjectStore(IsisConfiguration configuration, ObjectAdapterFactory adapterFactory, AdapterManagerSpi adapterManager) {
+        createDataNucleusApplicationComponentsIfRequired(configuration);
+        return new DataNucleusObjectStore(adapterFactory, applicationComponents);
+    }
+
+    private void createDataNucleusApplicationComponentsIfRequired(IsisConfiguration configuration) {
+        if(applicationComponents != null) {
+            return;
+        }
+        
+        final IsisConfiguration dataNucleusConfig = configuration.createSubset(ISIS_CONFIG_PREFIX);
+        final Map<String, String> props = dataNucleusConfig.asMap();
+        addDataNucleusPropertiesIfRequired(props);
+        
+        applicationComponents = new DataNucleusApplicationComponents(props, getSpecificationLoader().allSpecifications());
+    }
+
+
+    private static void addDataNucleusPropertiesIfRequired(
+            final Map<String, String> props) {
+        putIfNotPresent(props, "javax.jdo.PersistenceManagerFactoryClass", "org.datanucleus.api.jdo.JDOPersistenceManagerFactory");
+        
+        putIfNotPresent(props, "javax.jdo.option.ConnectionDriverName", "org.hsqldb.jdbcDriver");
+        putIfNotPresent(props, "javax.jdo.option.ConnectionURL", "jdbc:hsqldb:mem:test");
+        putIfNotPresent(props, "javax.jdo.option.ConnectionUserName", "sa");
+        putIfNotPresent(props, "javax.jdo.option.ConnectionPassword", "");
+        
+        putIfNotPresent(props, "datanucleus.autoCreateSchema", "true");
+        putIfNotPresent(props, "datanucleus.validateSchema", "true");
+        putIfNotPresent(props, "datanucleus.cache.level2.type", "none");
+    }
+
+
+    private static void putIfNotPresent(
+        final Map<String, String> props,
+        String key,
+        String value) {
+        if(!props.containsKey(key)) {
+            props.put(key, value);
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    // createPersistenceSession
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public PersistenceSession createPersistenceSession(PersistenceSessionFactory persistenceSessionFactory) {
+        PersistenceSession persistenceSession = super.createPersistenceSession(persistenceSessionFactory);
+        searchAndCacheAuditServiceIfNotAlreadyDoneSo(persistenceSessionFactory);
+        return persistenceSession;
+    }
+
+    private void searchAndCacheAuditServiceIfNotAlreadyDoneSo(PersistenceSessionFactory persistenceSessionFactory) {
+        if(searchedForAuditService) {
+            return;
+        } 
+        List<Object> services = persistenceSessionFactory.getServices();
+        final Optional<Object> optionalService = Iterables.tryFind(services, LOCATE_AUDIT_SERVICE);
+        if(optionalService.isPresent()) {
+            auditService = (AuditService) optionalService.get();
+        }
+        searchedForAuditService = true;
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    // PersistenceSessionFactoryDelegate impl
+    ////////////////////////////////////////////////////////////////////////
+
+    @Override
+    protected PersistAlgorithm createPersistAlgorithm(IsisConfiguration configuration) {
+        return new DataNucleusSimplePersistAlgorithm();
+    }
+    
+    @Override
+    public IdentifierGenerator createIdentifierGenerator(IsisConfiguration configuration) {
+        return new DataNucleusIdentifierGenerator();
+    }
+
+    @Override
+    public ClassSubstitutor createClassSubstitutor(IsisConfiguration configuration) {
+        return new DataNucleusTypesClassSubstitutor();
+    }
+
+    @Override
+    public void refineProgrammingModel(ProgrammingModel programmingModel, IsisConfiguration configuration) {
+        addJdoFacetFactoriesTo(programmingModel);
+        addDataNucleusFacetFactoriesTo(programmingModel);
+    }
+
+    private void addJdoFacetFactoriesTo(ProgrammingModel baseProgrammingModel) {
+        baseProgrammingModel.addFactory(JdoPersistenceCapableAnnotationFacetFactory.class);
+        baseProgrammingModel.addFactory(JdoDatastoreIdentityAnnotationFacetFactory.class);
+        baseProgrammingModel.addFactory(JdoEmbeddedOnlyAnnotationFacetFactory.class);
+
+        baseProgrammingModel.addFactory(JdoPrimaryKeyAnnotationFacetFactory.class);
+        baseProgrammingModel.addFactory(JdoDiscriminatorAnnotationFacetFactory.class);
+
+        baseProgrammingModel.addFactory(JdoQueryAnnotationFacetFactory.class);
+        
+        baseProgrammingModel.addFactory(AuditableAnnotationFacetFactory.class);
+        baseProgrammingModel.addFactory(AuditableMarkerInterfaceFacetFactory.class);
+    }
+
+    private void addDataNucleusFacetFactoriesTo(ProgrammingModel baseProgrammingModel) {
+        baseProgrammingModel.addFactory(RemoveJdoEnhancementTypesFacetFactory.class);
+        baseProgrammingModel.addFactory(RemoveJdoPrefixedMethodsFacetFactory.class);
+    }
+
+    @Override
+    public void refineMetaModelValidator(MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
+        metaModelValidator.add(new JdoMetaModelValidator());
+    }
+
+
+    @Override
+    protected IsisTransactionManager createTransactionManager(final EnlistedObjectDirtying persistor, final TransactionalResource objectStore) {
+        return new DataNucleusTransactionManager(persistor, objectStore, auditService);
+    }
+
+    @Override
+    public ObjectFactory createObjectFactory(IsisConfiguration configuration) {
+        return new ObjectFactoryBasic();
+    }
+
+    @Override
+    public DataNucleusPojoRecreator createPojoRecreator(IsisConfiguration configuration) {
+        return new DataNucleusPojoRecreator();
+    }
+
+
+
+
+    
+    ////////////////////////////////////////////////////////////////////////
+    // Dependencies
+    ////////////////////////////////////////////////////////////////////////
+    
+    protected SpecificationLoaderSpi getSpecificationLoader() {
+        return IsisContext.getSpecificationLoader();
+    }
+
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/JdoRuntimeException.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/JdoRuntimeException.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/JdoRuntimeException.java
new file mode 100644
index 0000000..031f5b8
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/JdoRuntimeException.java
@@ -0,0 +1,34 @@
+/*
+ *  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.jdo.datanucleus;
+
+public class JdoRuntimeException extends RuntimeException {
+
+    private static final long serialVersionUID = 1L;
+
+    public JdoRuntimeException() {
+        super();
+    }
+
+    public JdoRuntimeException(String arg0) {
+        super(arg0);
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/bytecode/DataNucleusTypesClassSubstitutor.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/bytecode/DataNucleusTypesClassSubstitutor.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/bytecode/DataNucleusTypesClassSubstitutor.java
new file mode 100644
index 0000000..32f5502
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/bytecode/DataNucleusTypesClassSubstitutor.java
@@ -0,0 +1,40 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.bytecode;
+
+import org.apache.isis.core.metamodel.specloader.classsubstitutor.CglibEnhanced;
+import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutorAbstract;
+
+public class DataNucleusTypesClassSubstitutor extends ClassSubstitutorAbstract {
+
+    /**
+     * If {@link CglibEnhanced} then return superclass, else as per
+     * {@link ClassSubstitutorAbstract#getClass(Class) superclass'}
+     * implementation.
+     */
+    @Override
+    public Class<?> getClass(final Class<?> cls) {
+        if(cls.getName().startsWith("org.datanucleus")) {
+            return getClass(cls.getSuperclass());
+        }
+        return super.getClass(cls);
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/metamodel/JdoPropertyUtils.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/metamodel/JdoPropertyUtils.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/metamodel/JdoPropertyUtils.java
new file mode 100644
index 0000000..5773943
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/metamodel/JdoPropertyUtils.java
@@ -0,0 +1,68 @@
+/*
+ *  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.jdo.datanucleus.metamodel;
+
+import java.text.MessageFormat;
+import java.util.List;
+
+import javax.jdo.annotations.PrimaryKey;
+
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.util.JdoPrimaryKeyPropertyFilter;
+
+public final class JdoPropertyUtils {
+
+    private JdoPropertyUtils() {
+    }
+
+    /**
+     * Searches for the property annotated with {@link PrimaryKey}.
+     * <p>
+     * Returns the {@link OneToOneAssociation} if there is precisely one; else
+     * <tt>null</tt>.
+     * 
+     * @see JdoPrimaryKeyPropertyFilter
+     */
+    public static OneToOneAssociation getPrimaryKeyPropertyFor(final ObjectSpecification objectSpec) {
+        return getPropertyFor(objectSpec, "@PrimaryKey", new JdoPrimaryKeyPropertyFilter());
+    }
+
+    public static boolean hasPrimaryKeyProperty(final ObjectSpecification objectSpec) {
+        return getPrimaryKeyPropertyFor(objectSpec) != null;
+    }
+    
+    private static OneToOneAssociation getPropertyFor(final ObjectSpecification objSpec, final String annotationName, final Filter<ObjectAssociation> filter) {
+        if (objSpec == null || !objSpec.containsFacet(JdoPersistenceCapableFacet.class)) {
+            return null;
+        }
+        final List<? extends ObjectAssociation> propertyList = objSpec.getAssociations(filter);
+        if (propertyList.size() == 0) {
+            return JdoPropertyUtils.getPropertyFor(objSpec.superclass(), annotationName, filter);
+        }
+        if (propertyList.size() > 1) {
+            throw new IllegalStateException(MessageFormat.format("Shouldn''t have more than one property annotated with {0} (''{1}'')", annotationName, objSpec.getFullIdentifier()));
+        }
+        return (OneToOneAssociation) propertyList.get(0);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java
new file mode 100644
index 0000000..992a65d
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java
@@ -0,0 +1,342 @@
+/*
+ *  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.jdo.datanucleus.persistence;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManager;
+import javax.jdo.spi.PersistenceCapable;
+
+import org.apache.log4j.Logger;
+import org.datanucleus.api.jdo.NucleusJDOHelper;
+
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.exceptions.IsisException;
+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.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackUtils;
+import org.apache.isis.core.metamodel.facets.object.callbacks.PersistedCallbackFacet;
+import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedCallbackFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.DataNucleusObjectStore;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.spi.JdoObjectIdSerializer;
+import org.apache.isis.runtimes.dflt.runtime.persistence.PersistorUtil;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.OidGenerator;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.runtimes.dflt.runtime.system.transaction.IsisTransaction;
+
+public class FrameworkSynchronizer {
+
+    private static final Logger LOG = Logger.getLogger(FrameworkSynchronizer.class);
+
+    /**
+     * Categorises where called from.
+     * 
+     * <p>
+     * Just used for logging.
+     */
+    public enum CalledFrom {
+        EVENT_LOAD, EVENT_STORE, EVENT_PREDIRTY, OS_QUERY, OS_RESOLVE, OS_LAZILYLOADED
+    }
+
+
+    public void postLoadProcessingFor(final PersistenceCapable pojo, CalledFrom calledFrom) {
+
+        withLogging(pojo, new Runnable() {
+            @Override
+            public void run() {
+                final Version datastoreVersion = getVersionIfAny(pojo);
+                
+                final RootOid oid ;
+                ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
+                if(adapter != null) {
+                    ensureRootObject(pojo);
+                    oid = (RootOid) adapter.getOid();
+
+                    final Version previousVersion = adapter.getVersion();
+
+                    // sync the pojo held by the adapter with that just loaded
+                    getPersistenceSession().remapRecreatedPojo(adapter, pojo);
+
+                    // since there was already an adapter, do concurrency check
+                    if(previousVersion != null && datastoreVersion != null) {
+                        if(previousVersion.different(datastoreVersion)) {
+                            getCurrentTransaction().addException(new ConcurrencyException(getAuthenticationSession().getUserName(), oid, previousVersion, datastoreVersion));
+                        }
+                    }
+                } else {
+                    final OidGenerator oidGenerator = getOidGenerator();
+                    oid = oidGenerator.createPersistent(pojo, null);
+                    
+                    // it appears to be possible that there is already an adapter for this Oid, 
+                    // ie from ObjectStore#resolveImmediately()
+                    adapter = getAdapterManager().getAdapterFor(oid);
+                    if(adapter != null) {
+                        getPersistenceSession().remapRecreatedPojo(adapter, pojo);
+                    } else {
+                        adapter = getPersistenceSession().mapRecreatedPojo(oid, pojo);
+                    }
+                }
+                if(!adapter.isResolved()) {
+                    PersistorUtil.startResolving(adapter);
+                    PersistorUtil.toEndState(adapter);
+                }
+                adapter.setVersion(datastoreVersion);
+
+                ensureFrameworksInAgreement(pojo);
+            }
+        }, calledFrom);
+    }
+
+
+    public void postStoreProcessingFor(final PersistenceCapable pojo, CalledFrom calledFrom) {
+        withLogging(pojo, new Runnable() {
+            @Override
+            public void run() {
+                ensureRootObject(pojo);
+                
+                // assert is persistent
+                if(!pojo.jdoIsPersistent()) {
+                    throw new IllegalStateException("Pojo JDO state is not persistent! pojo dnOid: " + JDOHelper.getObjectId(pojo));
+                }
+
+                final ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
+                final RootOid isisOid = (RootOid) adapter.getOid();
+                
+                Class<? extends CallbackFacet> callbackFacetClass;
+                if (isisOid.isTransient()) {
+                    final RootOid persistentOid = getOidGenerator().createPersistent(pojo, isisOid);
+                    
+                    getPersistenceSession().remapAsPersistent(adapter, persistentOid);
+
+                    callbackFacetClass = PersistedCallbackFacet.class;
+                } else {
+                    callbackFacetClass = UpdatedCallbackFacet.class;
+                }
+                
+                Utils.clearDirtyFor(adapter);
+                
+                Version versionIfAny = getVersionIfAny(pojo);
+                adapter.setVersion(versionIfAny);
+                CallbackUtils.callCallback(adapter, callbackFacetClass);
+
+                ensureFrameworksInAgreement(pojo);
+            }
+        }, calledFrom);
+    }
+
+    public void preDirtyProcessingFor(final PersistenceCapable pojo, CalledFrom calledFrom) {
+        withLogging(pojo, new Runnable() {
+            @Override
+            public void run() {
+                final IsisTransaction transaction = getCurrentTransaction();
+                final ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
+                
+                if(adapter.isTransient()) {
+                    // seen this happen in the case when there's a 1<->m bidirectional collection, and we're
+                    // attaching the child object, which is being persisted by DN as a result of persistence-by-reachability,
+                    // and it "helpfully" sets up the parent attribute on the child, causing this callback to fire.
+                    // 
+                    // however, at the same time, Isis has only queued up a CreateObjectCommand for the transient object, but it
+                    // hasn't yet executed, so thinks that the adapter is still transient. 
+                    return;
+                }
+                transaction.auditDirty(adapter);
+
+                ensureRootObject(pojo);
+                ensureFrameworksInAgreement(pojo);
+            }
+        }, calledFrom);
+    }
+
+
+    
+    public ObjectAdapter lazilyLoaded(final PersistenceCapable pojo, CalledFrom calledFrom) {
+        return withLogging(pojo, new Callable<ObjectAdapter>() {
+            @Override
+            public ObjectAdapter call() {
+                if(getJdoPersistenceManager().getObjectId(pojo) == null) {
+                    return null;
+                }
+                final RootOid oid = getPersistenceSession().getOidGenerator().createPersistent(pojo, null);
+                final ObjectAdapter adapter = getPersistenceSession().mapRecreatedPojo(oid, pojo);
+                return adapter;
+            }
+        }, calledFrom);
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Helpers
+    // /////////////////////////////////////////////////////////
+    
+    private <T> T withLogging(PersistenceCapable pojo, Callable<T> runnable, CalledFrom calledFrom) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(logString(calledFrom, LoggingLocation.ENTRY, pojo));
+        }
+        try {
+            return runnable.call();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug(logString(calledFrom, LoggingLocation.EXIT, pojo));
+            }
+        }
+    }
+    
+    private void withLogging(PersistenceCapable pojo, final Runnable runnable, CalledFrom calledFrom) {
+        withLogging(pojo, new Callable<Void>() {
+
+            @Override
+            public Void call() throws Exception {
+                runnable.run();
+                return null;
+            }
+            
+        }, calledFrom);
+    }
+    
+    private String logString(CalledFrom calledFrom, LoggingLocation location, PersistenceCapable pojo) {
+        final AdapterManager adapterManager = getAdapterManager();
+        final ObjectAdapter adapter = adapterManager.getAdapterFor(pojo);
+        // initial spaces just to look better in log when wrapped by IsisLifecycleListener...
+        return calledFrom.name() + " " + location.prefix + " oid=" + (adapter !=null? adapter.getOid(): "(null)") + " ,pojo " + pojo;
+    }
+
+
+    // /////////////////////////////////////////////////////////
+    // Helpers
+    // /////////////////////////////////////////////////////////
+
+    void ensureFrameworksInAgreement(final PersistenceCapable pojo) {
+        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
+        final Oid oid = adapter.getOid();
+
+        if(!pojo.jdoIsPersistent()) {
+            // make sure the adapter is transient
+            if (!adapter.getResolveState().isTransient()) {
+                throw new IsisException(MessageFormat.format("adapter oid={0} has resolve state in invalid state; should be transient but is {1}; pojo: {2}", oid, adapter.getResolveState(), pojo));
+            }
+
+            // make sure the oid is transient
+            if (!oid.isTransient()) {
+                throw new IsisException(MessageFormat.format("adapter oid={0} has oid in invalid state; should be transient; pojo: {1}", oid, pojo));
+            }
+
+        } else {
+            // make sure the adapter is persistent
+            if (!adapter.getResolveState().representsPersistent()) {
+                throw new IsisException(MessageFormat.format("adapter oid={0} has resolve state in invalid state; should be in a persistent but is {1}; pojo: {2}", oid, adapter.getResolveState(), pojo));
+            }
+
+            // make sure the oid is persistent
+            if (oid.isTransient()) {
+                throw new IsisException(MessageFormat.format("adapter oid={0} has oid in invalid state; should be persistent; pojo: {1}", oid, pojo));
+            }
+        }
+    }
+
+    // make sure the entity is known to Isis and is a root
+    // TODO: will probably need to handle aggregated entities at some point...
+    void ensureRootObject(final PersistenceCapable pojo) {
+        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
+        if(adapter == null) {
+            throw new IsisException(MessageFormat.format("Object not yet known to Isis: {0}", pojo));
+        }
+        final Oid oid = adapter.getOid();
+        if (!(oid instanceof RootOid)) {
+            throw new IsisException(MessageFormat.format("Not a RootOid: oid={0}, for {1}", oid, pojo));
+        }
+    }
+
+    private Version getVersionIfAny(final PersistenceCapable pojo) {
+        return Utils.getVersionIfAny(pojo, getAuthenticationSession());
+    }
+
+    @SuppressWarnings("unused")
+    private static Filter<ObjectAssociation> dirtyFieldFilterFor(final PersistenceCapable pojo) {
+        String[] dirtyFields = NucleusJDOHelper.getDirtyFields(pojo, JDOHelper.getPersistenceManager(pojo));
+        final List<String> dirtyFieldList = Arrays.asList(dirtyFields);
+        Filter<ObjectAssociation> dirtyFieldsFilter = new Filter<ObjectAssociation>() {
+            @Override
+            public boolean accept(final ObjectAssociation t) {
+                String id = t.getId();
+                return dirtyFieldList.contains(id);
+            }};
+        return dirtyFieldsFilter;
+    }
+
+    @SuppressWarnings("unused")
+    private void ensureObjectNotLoaded(final PersistenceCapable pojo) {
+        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
+        if(adapter != null) {
+            final Oid oid = adapter.getOid();
+            throw new IsisException(MessageFormat.format("Object is already mapped in Isis: oid={0}, for {1}", oid, pojo));
+        }
+    }
+
+
+    
+    // /////////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // /////////////////////////////////////////////////////////
+
+    protected AdapterManager getAdapterManager() {
+        return getPersistenceSession().getAdapterManager();
+    }
+
+    protected OidGenerator getOidGenerator() {
+        return getPersistenceSession().getOidGenerator();
+    }
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected AuthenticationSession getAuthenticationSession() {
+        return IsisContext.getAuthenticationSession();
+    }
+
+    protected IsisTransaction getCurrentTransaction() {
+        return IsisContext.getCurrentTransaction();
+    }
+
+    protected PersistenceManager getJdoPersistenceManager() {
+        final DataNucleusObjectStore objectStore = getObjectStore();
+        return objectStore.getPersistenceManager();
+    }
+
+    protected DataNucleusObjectStore getObjectStore() {
+        return (DataNucleusObjectStore) IsisContext.getPersistenceSession().getObjectStore();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java
new file mode 100644
index 0000000..2465d37
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java
@@ -0,0 +1,266 @@
+/*
+ *  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.jdo.datanucleus.persistence;
+
+import java.util.Map;
+
+import javax.jdo.listener.AttachLifecycleListener;
+import javax.jdo.listener.ClearLifecycleListener;
+import javax.jdo.listener.CreateLifecycleListener;
+import javax.jdo.listener.DeleteLifecycleListener;
+import javax.jdo.listener.DetachLifecycleListener;
+import javax.jdo.listener.DirtyLifecycleListener;
+import javax.jdo.listener.InstanceLifecycleEvent;
+import javax.jdo.listener.LoadLifecycleListener;
+import javax.jdo.listener.StoreLifecycleListener;
+import javax.jdo.spi.PersistenceCapable;
+
+import com.google.common.collect.Maps;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer.CalledFrom;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+
+public class IsisLifecycleListener implements AttachLifecycleListener, ClearLifecycleListener, CreateLifecycleListener, DeleteLifecycleListener, DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLifecycleListener, SuspendableListener {
+
+    private static final Logger LOG = Logger.getLogger(IsisLifecycleListener.class);
+    
+    private final FrameworkSynchronizer synchronizer;
+    
+    public IsisLifecycleListener(FrameworkSynchronizer synchronizer) {
+        this.synchronizer = synchronizer;
+    }
+
+
+    /////////////////////////////////////////////////////////////////////////
+    // callbacks
+    /////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void postCreate(final InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableNoop(event));
+    }
+
+    @Override
+    public void preAttach(final InstanceLifecycleEvent event) {
+        withLogging(Phase.PRE, event, new RunnableEnsureFrameworksInAgreement(event));
+    }
+
+    @Override
+    public void postAttach(final InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableEnsureFrameworksInAgreement(event));
+    }
+
+    @Override
+    public void postLoad(final InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableAbstract(event){
+            @Override
+            protected void doRun() {
+                final PersistenceCapable pojo = Utils.persistenceCapableFor(event);
+                synchronizer.postLoadProcessingFor(pojo, CalledFrom.EVENT_LOAD);
+            }});
+    }
+
+	@Override
+    public void preStore(InstanceLifecycleEvent event) {
+        withLogging(Phase.PRE, event, new RunnableNoop(event));
+    }
+
+    @Override
+    public void postStore(InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableAbstract(event){
+            @Override
+            protected void doRun() {
+                final PersistenceCapable pojo = Utils.persistenceCapableFor(event);
+                synchronizer.postStoreProcessingFor(pojo, CalledFrom.EVENT_STORE);
+
+            }});
+    }
+
+    @Override
+    public void preDirty(InstanceLifecycleEvent event) {
+        withLogging(Phase.PRE, event, new RunnableAbstract(event){
+            @Override
+            protected void doRun() {
+                final PersistenceCapable pojo = Utils.persistenceCapableFor(event);
+                synchronizer.preDirtyProcessingFor(pojo, CalledFrom.EVENT_PREDIRTY);
+            }});
+    }
+
+    @Override
+    public void postDirty(InstanceLifecycleEvent event) {
+        
+        // cannot assert on the frameworks being in agreement, due to the scenario documented
+        // in the FrameworkSynchronizer#preDirtyProcessing(...)
+        //
+        // 1<->m bidirectional, persistence-by-reachability
+        
+        withLogging(Phase.POST, event, new RunnableNoop(event));
+    }    
+
+    @Override
+    public void preDelete(InstanceLifecycleEvent event) {
+        withLogging(Phase.PRE, event, new RunnableEnsureFrameworksInAgreement(event));
+    }
+
+    @Override
+    public void postDelete(InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableEnsureFrameworksInAgreement(event));
+    }
+
+    /**
+     * Does nothing, not important event for Isis to track.
+     */
+    @Override
+    public void preClear(InstanceLifecycleEvent event) {
+        // ignoring, not important to us
+    }
+
+    /**
+     * Does nothing, not important event for Isis to track.
+     */
+    @Override
+    public void postClear(InstanceLifecycleEvent event) {
+        // ignoring, not important to us
+    }
+
+    @Override
+    public void preDetach(InstanceLifecycleEvent event) {
+        withLogging(Phase.PRE, event, new RunnableEnsureFrameworksInAgreement(event));
+    }
+
+    @Override
+    public void postDetach(InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableEnsureFrameworksInAgreement(event));
+    }
+
+    
+    /////////////////////////////////////////////////////////////////////////
+    // withLogging
+    /////////////////////////////////////////////////////////////////////////
+
+    private void withLogging(Phase phase, InstanceLifecycleEvent event, Runnable runnable) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug(logString(phase, LoggingLocation.ENTRY, event));
+        }
+        try {
+            runnable.run();
+        } finally {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug(logString(phase, LoggingLocation.EXIT, event));
+            }
+        }
+    }
+    
+    private abstract class RunnableAbstract implements Runnable {
+        final InstanceLifecycleEvent event;
+        public RunnableAbstract(final InstanceLifecycleEvent event) {
+            this.event = event;
+        }
+        @Override
+        public void run() {
+            if (isSuspended()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(" [currently suspended - ignoring]");
+                }
+                return;
+            }
+            doRun();
+        }
+        
+        protected abstract void doRun(); 
+    }
+    
+    private class RunnableNoop extends RunnableAbstract {
+        RunnableNoop(InstanceLifecycleEvent event) {
+            super(event);
+        }
+        protected void doRun() {} 
+    }
+    
+    private class RunnableEnsureFrameworksInAgreement extends RunnableAbstract {
+        RunnableEnsureFrameworksInAgreement(InstanceLifecycleEvent event) {
+            super(event);
+        }
+        protected void doRun() {
+            final PersistenceCapable pojo = Utils.persistenceCapableFor(event);
+            synchronizer.ensureRootObject(pojo);
+            synchronizer.ensureFrameworksInAgreement(pojo);
+        } 
+    }
+    
+
+    // /////////////////////////////////////////////////////////
+    // SuspendListener
+    // /////////////////////////////////////////////////////////
+
+    private boolean suspended;
+
+
+    @Override
+    public boolean isSuspended() {
+        return suspended;
+    }
+
+    @Override
+    public void setSuspended(boolean suspended) {
+        this.suspended = suspended;
+    }
+
+    // /////////////////////////////////////////////////////////
+    // Logging
+    // /////////////////////////////////////////////////////////
+
+    private enum Phase {
+        PRE, POST
+    }
+
+    private static Map<Integer, LifecycleEventType> events = Maps.newHashMap();
+
+    private enum LifecycleEventType {
+        CREATE(0), LOAD(1), STORE(2), CLEAR(3), DELETE(4), DIRTY(5), DETACH(6), ATTACH(7);
+
+        private LifecycleEventType(int code) {
+            events.put(code, this);
+        }
+
+        public static LifecycleEventType lookup(int code) {
+            return events.get(code);
+        }
+    }
+
+    private String logString(Phase phase, LoggingLocation location, InstanceLifecycleEvent event) {
+        final PersistenceCapable pojo = Utils.persistenceCapableFor(event);
+        final AdapterManager adapterManager = getAdapterManager();
+        final ObjectAdapter adapter = adapterManager.getAdapterFor(pojo);
+        return phase + " " + location.prefix + " " + LifecycleEventType.lookup(event.getEventType()) + ": oid=" + (adapter !=null? adapter.getOid(): "(null)") + " ,pojo " + pojo;
+    }
+
+    
+    // /////////////////////////////////////////////////////////
+    // Dependencies (from context)
+    // /////////////////////////////////////////////////////////
+
+    protected AdapterManager getAdapterManager() {
+        return IsisContext.getPersistenceSession().getAdapterManager();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java
new file mode 100644
index 0000000..c21c501
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java
@@ -0,0 +1,27 @@
+/*
+ *  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.jdo.datanucleus.persistence;
+
+public enum LoggingLocation {
+    ENTRY(">>"), EXIT("<<");
+    final String prefix;
+    private LoggingLocation(String prefix) {
+        this.prefix = prefix;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/SuspendableListener.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/SuspendableListener.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/SuspendableListener.java
new file mode 100644
index 0000000..8ed4942
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/SuspendableListener.java
@@ -0,0 +1,27 @@
+/*
+ *  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.jdo.datanucleus.persistence;
+
+public interface SuspendableListener {
+
+    boolean isSuspended();
+
+    void setSuspended(boolean suspend);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java
new file mode 100644
index 0000000..76c2986
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/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.runtimes.dflt.objectstores.jdo.datanucleus.persistence;
+
+import java.util.Date;
+
+import javax.jdo.listener.InstanceLifecycleEvent;
+import javax.jdo.spi.PersistenceCapable;
+
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.version.SerialNumberVersion;
+import org.apache.isis.core.metamodel.adapter.version.Version;
+
+public class Utils {
+
+    @SuppressWarnings("unused")
+    private static Object jdoObjectIdFor(InstanceLifecycleEvent event) {
+        PersistenceCapable persistenceCapable = Utils.persistenceCapableFor(event);
+        Object jdoObjectId = persistenceCapable.jdoGetObjectId();
+        return jdoObjectId;
+    }
+
+    static PersistenceCapable persistenceCapableFor(InstanceLifecycleEvent event) {
+        return (PersistenceCapable)event.getSource();
+    }
+
+    static void clearDirtyFor(final ObjectAdapter adapter) {
+        adapter.getSpecification().clearDirty(adapter);
+    }
+
+    static Version getVersionIfAny(final PersistenceCapable pojo, final AuthenticationSession authenticationSession) {
+        Object jdoVersion = pojo.jdoGetVersion();
+        if(jdoVersion instanceof Long) {
+            return SerialNumberVersion.create((Long) jdoVersion, authenticationSession.getUserName(), new Date()); 
+        } 
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java
new file mode 100644
index 0000000..854ca67
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java
@@ -0,0 +1,62 @@
+/*
+ *  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.jdo.datanucleus.persistence.adaptermanager;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.DataNucleusObjectStore;
+import org.apache.isis.runtimes.dflt.runtime.persistence.adaptermanager.PojoRecreator;
+import org.apache.isis.runtimes.dflt.runtime.persistence.adaptermanager.PojoRecreatorDefault;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.isis.runtimes.dflt.runtime.system.persistence.PersistenceSession;
+
+public class DataNucleusPojoRecreator implements PojoRecreator {
+
+    private final PojoRecreator delegate = new PojoRecreatorDefault();
+    
+    @Override
+    public Object recreatePojo(TypedOid oid) {
+        if(oid.isTransient()) {
+            return delegate.recreatePojo(oid);
+        }
+        return getObjectStore().loadPojo(oid);
+    }
+
+    
+    @Override
+    public ObjectAdapter lazilyLoaded(Object pojo) {
+        return getObjectStore().lazilyLoaded(pojo);
+    }
+
+    ///////////////////////////////
+    
+
+    protected PersistenceSession getPersistenceSession() {
+        return IsisContext.getPersistenceSession();
+    }
+
+    protected DataNucleusObjectStore getObjectStore() {
+        return (DataNucleusObjectStore) getPersistenceSession().getObjectStore();
+    }
+
+    
+    
+    
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/AbstractDataNucleusObjectCommand.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/AbstractDataNucleusObjectCommand.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/AbstractDataNucleusObjectCommand.java
new file mode 100644
index 0000000..7258e8e
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/AbstractDataNucleusObjectCommand.java
@@ -0,0 +1,44 @@
+/*
+ *  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.jdo.datanucleus.persistence.commands;
+
+import javax.jdo.PersistenceManager;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandAbstract;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+
+public abstract class AbstractDataNucleusObjectCommand extends PersistenceCommandAbstract {
+    
+    private final PersistenceManager persistenceManager;
+
+    AbstractDataNucleusObjectCommand(final ObjectAdapter adapter,
+            final PersistenceManager persistenceManager) {
+        super(adapter);
+        this.persistenceManager = persistenceManager;
+        
+    }
+
+    protected PersistenceManager getPersistenceManager() {
+        return persistenceManager;
+    }
+    
+    public abstract void execute(final PersistenceCommandContext context);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusCreateObjectCommand.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusCreateObjectCommand.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusCreateObjectCommand.java
new file mode 100644
index 0000000..7f82da9
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusCreateObjectCommand.java
@@ -0,0 +1,61 @@
+/*
+ *  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.jdo.datanucleus.persistence.commands;
+
+import javax.jdo.PersistenceManager;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.CreateObjectCommand;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+
+public class DataNucleusCreateObjectCommand extends AbstractDataNucleusObjectCommand implements CreateObjectCommand {
+
+    private static final Logger LOG = Logger
+            .getLogger(DataNucleusCreateObjectCommand.class);
+
+    public DataNucleusCreateObjectCommand(ObjectAdapter adapter, PersistenceManager persistenceManager) {
+        super(adapter, persistenceManager);
+    }
+
+
+    @Override
+    public void execute(final PersistenceCommandContext context) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("create object - executing command for: " + onAdapter());
+        }
+        final ObjectAdapter adapter = onAdapter();
+        if(!adapter.isTransient()) {
+            // this could happen if DN's persistence-by-reachability has already caused the domainobject
+            // to be persisted.  It's Isis adapter will have been updated as a result of the postStore
+            // lifecycle callback, so in essence there's nothing to be done.
+            return;
+        }
+        final Object domainObject = adapter.getObject();
+
+        getPersistenceManager().makePersistent(domainObject);
+    }
+
+    @Override
+    public String toString() {
+        return "CreateObjectCommand [adapter=" + onAdapter() + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusDeleteObjectCommand.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusDeleteObjectCommand.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusDeleteObjectCommand.java
new file mode 100644
index 0000000..7e7fbb9
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusDeleteObjectCommand.java
@@ -0,0 +1,50 @@
+/*
+ *  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.jdo.datanucleus.persistence.commands;
+
+import javax.jdo.PersistenceManager;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.DestroyObjectCommand;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+
+public class DataNucleusDeleteObjectCommand extends AbstractDataNucleusObjectCommand implements DestroyObjectCommand {
+
+    private static final Logger LOG = Logger.getLogger(DataNucleusDeleteObjectCommand.class);
+
+    public DataNucleusDeleteObjectCommand(ObjectAdapter adapter, PersistenceManager persistenceManager) {
+        super(adapter, persistenceManager);
+    }
+
+    @Override
+    public void execute(final PersistenceCommandContext context) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("destroy object - executing command for " + onAdapter());
+        }
+        getPersistenceManager().deletePersistent(onAdapter().getObject());
+    }
+
+    @Override
+    public String toString() {
+        return "DestroyObjectCommand [adapter=" + onAdapter() + "]";
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusUpdateObjectCommand.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusUpdateObjectCommand.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusUpdateObjectCommand.java
new file mode 100644
index 0000000..97cd650
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/commands/DataNucleusUpdateObjectCommand.java
@@ -0,0 +1,51 @@
+/*
+ *  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.jdo.datanucleus.persistence.commands;
+
+import javax.jdo.PersistenceManager;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommandContext;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.SaveObjectCommand;
+
+public class DataNucleusUpdateObjectCommand extends AbstractDataNucleusObjectCommand implements SaveObjectCommand {
+    private static final Logger LOG = Logger
+            .getLogger(DataNucleusDeleteObjectCommand.class);
+
+    public DataNucleusUpdateObjectCommand(ObjectAdapter adapter, PersistenceManager persistenceManager) {
+        super(adapter, persistenceManager);
+    }
+
+    @Override
+    public void execute(final PersistenceCommandContext context) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("save object - executing command for: " + onAdapter());
+        }
+        
+        // TODO: this might be a no-op; JDO doesn't seem to have an equivalent of JPA's merge() ...
+        // getEntityManager().merge(onAdapter().getObject());
+    }
+
+    @Override
+    public String toString() {
+        return "SaveObjectCommand [adapter=" + onAdapter() + "]";
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java
new file mode 100644
index 0000000..92722fa
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.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.runtimes.dflt.objectstores.jdo.datanucleus.persistence.queries;
+
+import java.util.List;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindAllInstances;
+
+public class PersistenceQueryFindAllInstancesProcessor extends PersistenceQueryProcessorAbstract<PersistenceQueryFindAllInstances> {
+
+    private static final Logger LOG = Logger.getLogger(PersistenceQueryFindAllInstancesProcessor.class);
+
+    public PersistenceQueryFindAllInstancesProcessor(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
+    }
+
+    public List<ObjectAdapter> process(final PersistenceQueryFindAllInstances persistenceQuery) {
+
+        final ObjectSpecification specification = persistenceQuery.getSpecification();
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("getInstances: class=" + specification.getFullIdentifier());
+        }
+        
+        Class<?> cls = specification.getCorrespondingClass();
+        final Query query = getPersistenceManager().newQuery(cls);
+        
+        final List<?> pojos = (List<?>) query.execute();
+        return loadAdapters(specification, pojos);
+    }
+}
+
+// Copyright (c) Naked Objects Group Ltd.

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java
new file mode 100644
index 0000000..c37fcc0
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java
@@ -0,0 +1,59 @@
+/*
+ *  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.jdo.datanucleus.persistence.queries;
+
+import java.util.List;
+
+import javax.jdo.PersistenceManager;
+
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByPattern;
+
+public class PersistenceQueryFindByPatternProcessor extends
+        PersistenceQueryProcessorAbstract<PersistenceQueryFindByPattern> {
+
+    public PersistenceQueryFindByPatternProcessor(
+            final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
+    }
+
+    public List<ObjectAdapter> process(
+            final PersistenceQueryFindByPattern persistenceQuery) {
+
+        
+
+        
+//        final Object pojoPattern = persistenceQuery.getPattern().getObject();
+//        
+//        final CriteriaBuilder criteriaBuilder = getEntityManager().getCriteriaBuilder();
+//        
+//        
+//        final CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
+//        
+//        final Query query = getEntityManager().createQuery(criteriaQuery);
+//        final List<?> results = query.getResultList();
+//        return loadAdapters(persistenceQuery.getSpecification(), results);
+        
+        throw new NotYetImplementedException();
+    }
+}
+
+// Copyright (c) Naked Objects Group Ltd.

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java
new file mode 100644
index 0000000..d919ddd
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java
@@ -0,0 +1,63 @@
+/*
+ *  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.jdo.datanucleus.persistence.queries;
+
+import java.util.List;
+
+import javax.jdo.PersistenceManager;
+
+import org.apache.isis.core.commons.exceptions.NotYetImplementedException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindByTitle;
+
+public class PersistenceQueryFindByTitleProcessor extends PersistenceQueryProcessorAbstract<PersistenceQueryFindByTitle> {
+
+    public PersistenceQueryFindByTitleProcessor(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
+    }
+
+    public List<ObjectAdapter> process(final PersistenceQueryFindByTitle persistenceQuery) {
+        final ObjectSpecification objectSpec = persistenceQuery.getSpecification();
+        final Class<?> correspondingClass = objectSpec.getCorrespondingClass();
+        return process(persistenceQuery, correspondingClass);
+    }
+
+    private <Z> List<ObjectAdapter> process(final PersistenceQueryFindByTitle persistenceQuery, Class<Z> correspondingClass) {
+        // TODO
+        throw new NotYetImplementedException();
+
+//        final CriteriaQuery<Z> criteriaQuery = getEntityManager().getCriteriaBuilder().createQuery(correspondingClass);
+//
+//        final ObjectSpecification objectSpec = persistenceQuery.getSpecification();
+//        final Root<Z> from = criteriaQuery.from(correspondingClass);
+//        
+//        final EntityType<Z> model = from.getModel();
+//        final SingularAttribute<? super Z, String> titleAttribute = model.getSingularAttribute("title", String.class);
+//        final Path<String> titlePath = from.get(titleAttribute);
+//        titlePath.equals(persistenceQuery.getTitle());
+//        
+//        final TypedQuery<Z> query = getPersistenceManager().createQuery(criteriaQuery);
+//        final List<Z> pojos = query.getResultList();
+//        return loadAdapters(objectSpec, pojos);
+    }
+}
+
+// Copyright (c) Naked Objects Group Ltd.

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java
new file mode 100644
index 0000000..101ad9b
--- /dev/null
+++ b/framework/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java
@@ -0,0 +1,97 @@
+/*
+ *  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.jdo.datanucleus.persistence.queries;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+
+import com.google.common.collect.Maps;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.services.container.query.QueryCardinality;
+import org.apache.isis.core.metamodel.spec.ObjectAdapterUtils;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.DataNucleusObjectStore;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.metamodel.JdoPropertyUtils;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer;
+import org.apache.isis.runtimes.dflt.runtime.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
+
+public class PersistenceQueryFindUsingApplibQueryProcessor extends PersistenceQueryProcessorAbstract<PersistenceQueryFindUsingApplibQueryDefault> {
+    
+    public PersistenceQueryFindUsingApplibQueryProcessor(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
+    }
+
+    public List<ObjectAdapter> process(final PersistenceQueryFindUsingApplibQueryDefault persistenceQuery) {
+        final String queryName = persistenceQuery.getQueryName();
+        final Map<String, Object> map = unwrap(persistenceQuery.getArgumentsAdaptersByParameterName());
+        final QueryCardinality cardinality = persistenceQuery.getCardinality();
+        final ObjectSpecification objectSpec = persistenceQuery.getSpecification();
+        
+        final List<?> results;
+        if((objectSpec.getFullIdentifier() + "#pk").equals(queryName)) {
+            // special case handling
+            final Class<?> cls = objectSpec.getCorrespondingClass();
+            if(!JdoPropertyUtils.hasPrimaryKeyProperty(objectSpec)) {
+                throw new UnsupportedOperationException("cannot search by primary key for DataStore-assigned entities");
+            }
+            final OneToOneAssociation pkOtoa = JdoPropertyUtils.getPrimaryKeyPropertyFor(objectSpec);
+            String pkOtoaId = pkOtoa.getId();
+            final String filter = pkOtoaId + "==" + map.get(pkOtoaId);
+            final Query jdoQuery = getPersistenceManager().newQuery(cls, filter);
+            results = (List<?>) jdoQuery.execute();
+        } else {
+            results = getResults(objectSpec, queryName, map, cardinality);
+        }
+        
+        return loadAdapters(objectSpec, results);
+    }
+
+    private List<?> getResults(ObjectSpecification objectSpec, final String queryName, final Map<String, Object> argumentsByParameterName, final QueryCardinality cardinality) {
+        
+        final PersistenceManager persistenceManager = getJdoObjectStore().getPersistenceManager();
+        final Class<?> cls = objectSpec.getCorrespondingClass();
+        final Query jdoQuery = persistenceManager.newNamedQuery(cls, queryName);
+        
+        final List<?> results = (List<?>) jdoQuery.executeWithMap(argumentsByParameterName);
+        if (cardinality == QueryCardinality.MULTIPLE) {
+            return results;
+        }
+        return results.isEmpty()?Collections.emptyList():results.subList(0, 1);
+    }
+
+    private static Map<String, Object> unwrap(final Map<String, ObjectAdapter> argumentAdaptersByParameterName) {
+        final Map<String, Object> argumentsByParameterName = Maps.newHashMap();
+        for (final String parameterName : argumentAdaptersByParameterName.keySet()) {
+            final ObjectAdapter argumentAdapter = argumentAdaptersByParameterName.get(parameterName);
+            final Object argument = ObjectAdapterUtils.unwrapObject(argumentAdapter);
+            argumentsByParameterName.put(parameterName, argument);
+        }
+        return argumentsByParameterName;
+    }
+
+
+}
+
+// Copyright (c) Naked Objects Group Ltd.


Mime
View raw message