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/08/29 16:59:06 UTC

svn commit: r1378595 - in /incubator/isis/trunk/framework/runtimes/dflt: objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/ objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/...

Author: danhaywood
Date: Wed Aug 29 14:59:05 2012
New Revision: 1378595

URL: http://svn.apache.org/viewvc?rev=1378595&view=rev
Log:
ISIS-14: fixing support for lazily loading.

Collections that are lazily loaded were not being synchronized with the framework
(ie it thought that the pojos were transient).

This fix extends the PojoRecreator interface to also be able to detect that
a pojo has actually been lazily loaded previously.

At the same time, have also improved the logging of the IsisLifecycleListener, and
have consolidated all the logic that pertains to keeping JDO and Isis in
sync into a new FrameworkSynchronizer component.  This is delegated to by
the IsisLifecycleListener, the ObjectStore and the PojoRecreator.

Added:
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java
Modified:
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusApplicationComponents.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusObjectStore.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java
    incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java
    incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/AdapterManagerDefault.java
    incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreator.java
    incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreatorDefault.java

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusApplicationComponents.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusApplicationComponents.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusApplicationComponents.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusApplicationComponents.java Wed Aug 29 14:59:05 2012
@@ -20,6 +20,7 @@ import org.datanucleus.store.schema.Sche
 
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
 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.objectstores.jdo.datanucleus.persistence.IsisLifecycleListener;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.embeddedonly.JdoEmbeddedOnlyFacet;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
@@ -30,7 +31,9 @@ public class DataNucleusApplicationCompo
 
     private final PersistenceManagerFactory persistenceManagerFactory;
     private final Map<String, JdoNamedQuery> namedQueryByName;
+    
     private final IsisLifecycleListener lifecycleListener;
+    private final FrameworkSynchronizer synchronizer;
 
 
     ///////////////////////////////////////////////////////////////////////////
@@ -46,9 +49,10 @@ public class DataNucleusApplicationCompo
 
         namedQueryByName = Collections.unmodifiableMap(catalogNamedQueries(objectSpecs));
 
-        lifecycleListener = new IsisLifecycleListener();
+        synchronizer = new FrameworkSynchronizer();
+        lifecycleListener = new IsisLifecycleListener(synchronizer);
     }
-
+    
     private void createSchema(final Map<String, String> props, final Set<String> classesToBePersisted) {
         final JDOPersistenceManagerFactory jdopmf = (JDOPersistenceManagerFactory)persistenceManagerFactory;
         final NucleusContext nucleusContext = jdopmf.getNucleusContext();
@@ -100,6 +104,15 @@ public class DataNucleusApplicationCompo
 
 
     ///////////////////////////////////////////////////////////////////////////
+    // FrameworkSynchronizer
+    ///////////////////////////////////////////////////////////////////////////
+
+    public FrameworkSynchronizer getFrameworkSynchronizer() {
+        return synchronizer;
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////
     //
     ///////////////////////////////////////////////////////////////////////////
     
@@ -127,4 +140,5 @@ public class DataNucleusApplicationCompo
         lifecycleListener.setSuspended(false);
     }
 
+
 }

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusObjectStore.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusObjectStore.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusObjectStore.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/DataNucleusObjectStore.java Wed Aug 29 14:59:05 2012
@@ -39,6 +39,8 @@ import org.apache.isis.core.metamodel.sp
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpiAware;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer.CalledFrom;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.IsisLifecycleListener;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.commands.DataNucleusCreateObjectCommand;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.commands.DataNucleusDeleteObjectCommand;
@@ -108,8 +110,7 @@ public class DataNucleusObjectStore impl
     private TransactionMode transactionMode;
 
     
-    // TODO: review this, want to reuse
-    private final IsisLifecycleListener lifecycleListener = new IsisLifecycleListener();
+    private final FrameworkSynchronizer frameworkSynchronizer;
 
     public DataNucleusObjectStore(ObjectAdapterFactory adapterFactory, DataNucleusApplicationComponents applicationComponents) {
         ensureThatArg(adapterFactory, is(notNullValue()));
@@ -120,6 +121,7 @@ public class DataNucleusObjectStore impl
 
         this.adapterFactory = adapterFactory;
         this.applicationComponents = applicationComponents;
+        this.frameworkSynchronizer = applicationComponents.getFrameworkSynchronizer();
     }
 
     @Override
@@ -163,7 +165,6 @@ public class DataNucleusObjectStore impl
         }
 
         persistenceManager.close();
-
         state = State.CLOSED;
     }
 
@@ -173,10 +174,10 @@ public class DataNucleusObjectStore impl
     }
 
     private void addPersistenceQueryProcessors(final PersistenceManager persistenceManager) {
-        persistenceQueryProcessorByClass.put(PersistenceQueryFindAllInstances.class, new PersistenceQueryFindAllInstancesProcessor(persistenceManager));
-        persistenceQueryProcessorByClass.put(PersistenceQueryFindByTitle.class, new PersistenceQueryFindByTitleProcessor(persistenceManager));
-        persistenceQueryProcessorByClass.put(PersistenceQueryFindByPattern.class, new PersistenceQueryFindByPatternProcessor(persistenceManager));
-        persistenceQueryProcessorByClass.put(PersistenceQueryFindUsingApplibQueryDefault.class, new PersistenceQueryFindUsingApplibQueryProcessor(persistenceManager));
+        persistenceQueryProcessorByClass.put(PersistenceQueryFindAllInstances.class, new PersistenceQueryFindAllInstancesProcessor(persistenceManager, frameworkSynchronizer));
+        persistenceQueryProcessorByClass.put(PersistenceQueryFindByTitle.class, new PersistenceQueryFindByTitleProcessor(persistenceManager, frameworkSynchronizer));
+        persistenceQueryProcessorByClass.put(PersistenceQueryFindByPattern.class, new PersistenceQueryFindByPatternProcessor(persistenceManager, frameworkSynchronizer));
+        persistenceQueryProcessorByClass.put(PersistenceQueryFindUsingApplibQueryDefault.class, new PersistenceQueryFindUsingApplibQueryProcessor(persistenceManager, frameworkSynchronizer));
     }
 
     // ///////////////////////////////////////////////////////////////////////
@@ -354,10 +355,12 @@ public class DataNucleusObjectStore impl
         return getPersistenceSession().mapRecreatedPojo(oid, pojo);
     }
 
+    
+    
+    /////////////////////////////////////////////////////////////
+    // delegated to by PojoRecreator
+    /////////////////////////////////////////////////////////////
 
-    /**
-     * not API.
-     */
     public Object loadPojo(final TypedOid oid) {
     	
         // REVIEW: does it make sense to get these directly?  not sure, so for now have decided to fail fast. 
@@ -383,6 +386,14 @@ public class DataNucleusObjectStore impl
     }
 
     
+    public ObjectAdapter lazilyLoaded(Object pojo) {
+        if(!(pojo instanceof PersistenceCapable)) {
+            return null;
+        } 
+        final PersistenceCapable persistenceCapable = (PersistenceCapable) pojo;
+        return frameworkSynchronizer.lazilyLoaded(persistenceCapable, CalledFrom.OS_LAZILYLOADED);
+    }
+
 
 
     /**
@@ -446,7 +457,7 @@ public class DataNucleusObjectStore impl
         // listener, but (with JPA impl) found it was required if we were ever to 
         // get an eager left-outer-join as the result of a refresh (sounds possible).
         
-        lifecycleListener.postLoadProcessingFor((PersistenceCapable) domainObject);
+        frameworkSynchronizer.postLoadProcessingFor((PersistenceCapable) domainObject, CalledFrom.OS_RESOLVE);
     }
 
     /**
@@ -535,6 +546,8 @@ public class DataNucleusObjectStore impl
         return adapters;
     }
 
+    
+
     // ///////////////////////////////////////////////////////////////////////
     // Services
     // ///////////////////////////////////////////////////////////////////////
@@ -693,4 +706,5 @@ public class DataNucleusObjectStore impl
         return IsisContext.getOidMarshaller();
     }
 
+
 }

Added: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java?rev=1378595&view=auto
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java (added)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/FrameworkSynchronizer.java Wed Aug 29 14:59:05 2012
@@ -0,0 +1,311 @@
+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.endResolving(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);
+                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() {
+                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 is in invalid state; should be {0} but is {1}", ResolveState.TRANSIENT, adapter.getResolveState()));
+            }
+
+            // make sure the oid is transient
+            if (!oid.isTransient()) {
+                throw new IsisException(MessageFormat.format("Not transient: oid={0}, for {1}", oid, pojo));
+            }
+
+        } else {
+            // make sure the adapter is persistent
+            if (!adapter.getResolveState().representsPersistent()) {
+                throw new IsisException(MessageFormat.format("adapter is in invalid state; should be in a persistent state but is {1}", ResolveState.RESOLVED, adapter.getResolveState()));
+            }
+
+            // make sure the oid is persistent
+            if (oid.isTransient()) {
+                throw new IsisException(MessageFormat.format("Transient: oid={0}, for {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();
+    }
+
+
+}

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/IsisLifecycleListener.java Wed Aug 29 14:59:05 2012
@@ -1,12 +1,7 @@
 package org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence;
 
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
 import java.util.Map;
 
-import javax.jdo.JDOHelper;
 import javax.jdo.listener.AttachLifecycleListener;
 import javax.jdo.listener.ClearLifecycleListener;
 import javax.jdo.listener.CreateLifecycleListener;
@@ -18,348 +13,185 @@ import javax.jdo.listener.LoadLifecycleL
 import javax.jdo.listener.StoreLifecycleListener;
 import javax.jdo.spi.PersistenceCapable;
 
-import org.apache.isis.applib.filter.Filter;
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.exceptions.IsisException;
+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.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.SerialNumberVersion;
-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.runtime.persistence.PersistorUtil;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer.CalledFrom;
 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;
-import org.apache.log4j.Logger;
-import org.datanucleus.api.jdo.NucleusJDOHelper;
-
-import com.google.common.collect.Maps;
 
 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
     /////////////////////////////////////////////////////////////////////////
-    
-    private boolean suspended;
 
     @Override
-    public void postCreate(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
+    public void postCreate(final InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableNoop(event));
     }
 
     @Override
-    public void preAttach(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.PRE, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
+    public void preAttach(final InstanceLifecycleEvent event) {
+        withLogging(Phase.PRE, event, new RunnableEnsureFrameworksInAgreement(event));
     }
 
     @Override
-    public void postAttach(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
+    public void postAttach(final InstanceLifecycleEvent event) {
+        withLogging(Phase.POST, event, new RunnableEnsureFrameworksInAgreement(event));
     }
 
     @Override
-    public void postLoad(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-        
-        final PersistenceCapable pojo = persistenceCapableFor(event);
-        postLoadProcessingFor(pojo);
+    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);
+            }});
     }
 
-	public void postLoadProcessingFor(final PersistenceCapable pojo) {
-
-		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.endResolving(adapter);
-        }
-        adapter.setVersion(datastoreVersion);
-
-        ensureFrameworksInAgreement(pojo);
-	}
-
 	@Override
     public void preStore(InstanceLifecycleEvent event) {
-
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.PRE, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
+        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);
 
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            LOG.debug(" [currently suspended - ignoring]");
-            return;
-        }
-
-        ensureRootObject(event);
-        
-        
-        final PersistenceCapable pojo = persistenceCapableFor(event);
-
-        // 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;
-        }
-        
-        clearDirtyFor(adapter);
-        
-        Version versionIfAny = getVersionIfAny(pojo);
-        adapter.setVersion(versionIfAny);
-        CallbackUtils.callCallback(adapter, callbackFacetClass);
-
-        ensureFrameworksInAgreement(event);
+            }});
     }
 
     @Override
     public void preDirty(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.PRE, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-
-        final PersistenceCapable pojo = persistenceCapableFor(event);
-        
-        final IsisTransaction transaction = getCurrentTransaction();
-        final ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
-        transaction.auditDirty(adapter);
-
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(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) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-        
-
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
-    }
-    
-    
-
-
+        withLogging(Phase.POST, event, new RunnableEnsureFrameworksInAgreement(event));
+    }    
 
     @Override
     public void preDelete(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.PRE, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-        
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
+        withLogging(Phase.PRE, event, new RunnableEnsureFrameworksInAgreement(event));
     }
 
     @Override
     public void postDelete(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-        
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
+        withLogging(Phase.POST, event, new RunnableEnsureFrameworksInAgreement(event));
     }
 
+    /**
+     * Does nothing, not important event for Isis to track.
+     */
     @Override
     public void preClear(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.PRE, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-        
-        //TODO: not sure about the lifecycle of clear
-        //ensureRootObject(event);
-        //ensureFrameworksInAgreement(event);
+        // ignoring, not important to us
     }
 
+    /**
+     * Does nothing, not important event for Isis to track.
+     */
     @Override
     public void postClear(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
-        }
-        if (isSuspended()) {
-            if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
-            }
-            return;
-        }
-        
-        //TODO: not sure about the lifecycle of clear
-        //ensureRootObject(event);
-        //ensureFrameworksInAgreement(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.PRE, event));
+            LOG.debug(logString(phase, LoggingLocation.ENTRY, event));
         }
-        if (isSuspended()) {
+        try {
+            runnable.run();
+        } finally {
             if (LOG.isDebugEnabled()) {
-            	LOG.debug(" [currently suspended - ignoring]");
+                LOG.debug(logString(phase, LoggingLocation.EXIT, event));
             }
-            return;
         }
-
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
     }
-
-    @Override
-    public void postDetach(InstanceLifecycleEvent event) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug(logString(Phase.POST, event));
+    
+    private abstract class RunnableAbstract implements Runnable {
+        final InstanceLifecycleEvent event;
+        public RunnableAbstract(final InstanceLifecycleEvent event) {
+            this.event = event;
         }
-        if (isSuspended()) {
-            LOG.debug(" [currently suspended - ignoring]");
-            return;
+        @Override
+        public void run() {
+            if (isSuspended()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug(" [currently suspended - ignoring]");
+                }
+                return;
+            }
+            doRun();
         }
         
-        ensureRootObject(event);
-        ensureFrameworksInAgreement(event);
+        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;
@@ -371,67 +203,13 @@ public class IsisLifecycleListener imple
     }
 
     // /////////////////////////////////////////////////////////
-    // Helpers
+    // Logging
     // /////////////////////////////////////////////////////////
 
-    private void ensureFrameworksInAgreement(InstanceLifecycleEvent event) {
-        final PersistenceCapable pojo = persistenceCapableFor(event);
-        ensureFrameworksInAgreement(pojo);
-    }
-
-	private 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 is in invalid state; should be {0} but is {1}", ResolveState.TRANSIENT, adapter.getResolveState()));
-            }
-
-            // make sure the oid is transient
-            if (!oid.isTransient()) {
-                throw new IsisException(MessageFormat.format("Not transient: oid={0}, for {1}", oid, pojo));
-            }
-
-        } else {
-            // make sure the adapter is persistent
-            if (!adapter.getResolveState().representsPersistent()) {
-                throw new IsisException(MessageFormat.format("adapter is in invalid state; should be in a persistent state but is {1}", ResolveState.RESOLVED, adapter.getResolveState()));
-            }
-
-            // make sure the oid is persistent
-            if (oid.isTransient()) {
-                throw new IsisException(MessageFormat.format("Transient: oid={0}, for {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...
-    private void ensureRootObject(InstanceLifecycleEvent event) {
-        final PersistenceCapable pojo = persistenceCapableFor(event);
-        ensureRootObject(pojo);
-    }
-
-	private 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 enum Phase {
         PRE, POST
     }
-    
+
     private static Map<Integer, LifecycleEventType> events = Maps.newHashMap();
 
     private enum LifecycleEventType {
@@ -446,83 +224,19 @@ public class IsisLifecycleListener imple
         }
     }
 
-    private static String logString(Phase phase, InstanceLifecycleEvent event) {
-        return phase + " " + LifecycleEventType.lookup(event.getEventType()) + ": pojo " + event.getSource();
-    }
-
-    private static void clearDirtyFor(final ObjectAdapter adapter) {
-        adapter.getSpecification().clearDirty(adapter);
-    }
-
-    private static PersistenceCapable persistenceCapableFor(InstanceLifecycleEvent event) {
-        return (PersistenceCapable)event.getSource();
-    }
-
-    @SuppressWarnings("unused")
-    private static Object jdoObjectIdFor(InstanceLifecycleEvent event) {
-        PersistenceCapable persistenceCapable = persistenceCapableFor(event);
-        Object jdoObjectId = persistenceCapable.jdoGetObjectId();
-        return jdoObjectId;
-    }
-
-    private Version getVersionIfAny(final PersistenceCapable pojo) {
-        Object jdoVersion = pojo.jdoGetVersion();
-        if(jdoVersion instanceof Long) {
-            return SerialNumberVersion.create((Long) jdoVersion, getAuthenticationSession().getUserName(), new Date()); 
-        } 
-        return null;
+    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;
     }
 
-
-    
-    @SuppressWarnings("unused")
-    private 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(InstanceLifecycleEvent event) {
-        final PersistenceCapable pojo = persistenceCapableFor(event);
-        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();
+        return IsisContext.getPersistenceSession().getAdapterManager();
     }
-
-    protected PersistenceSession getPersistenceSession() {
-        return IsisContext.getPersistenceSession();
-    }
-
-    protected AuthenticationSession getAuthenticationSession() {
-        return IsisContext.getAuthenticationSession();
-    }
-
-    protected IsisTransaction getCurrentTransaction() {
-        return IsisContext.getCurrentTransaction();
-    }
-
-
 }

Added: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java?rev=1378595&view=auto
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java (added)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/LoggingLocation.java Wed Aug 29 14:59:05 2012
@@ -0,0 +1,9 @@
+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

Added: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java?rev=1378595&view=auto
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java (added)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/Utils.java Wed Aug 29 14:59:05 2012
@@ -0,0 +1,38 @@
+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;
+    }
+
+}

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/adaptermanager/DataNucleusPojoRecreator.java Wed Aug 29 14:59:05 2012
@@ -1,5 +1,6 @@
 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;
@@ -13,6 +14,12 @@ public class DataNucleusPojoRecreator im
         return getObjectStore().loadPojo(oid);
     }
 
+    
+    @Override
+    public ObjectAdapter lazilyLoaded(Object pojo) {
+        return getObjectStore().lazilyLoaded(pojo);
+    }
+
     ///////////////////////////////
     
 
@@ -23,6 +30,8 @@ public class DataNucleusPojoRecreator im
     protected DataNucleusObjectStore getObjectStore() {
         return (DataNucleusObjectStore) getPersistenceSession().getObjectStore();
     }
+
+    
     
     
 }

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindAllInstancesProcessor.java Wed Aug 29 14:59:05 2012
@@ -9,14 +9,15 @@ 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) {
-        super(persistenceManager);
+    public PersistenceQueryFindAllInstancesProcessor(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
     }
 
     public List<ObjectAdapter> process(final PersistenceQueryFindAllInstances persistenceQuery) {

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByPatternProcessor.java Wed Aug 29 14:59:05 2012
@@ -6,14 +6,15 @@ 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) {
-        super(persistenceManager);
+            final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
     }
 
     public List<ObjectAdapter> process(

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindByTitleProcessor.java Wed Aug 29 14:59:05 2012
@@ -7,12 +7,13 @@ 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) {
-        super(persistenceManager);
+    public PersistenceQueryFindByTitleProcessor(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
     }
 
     public List<ObjectAdapter> process(final PersistenceQueryFindByTitle persistenceQuery) {

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryFindUsingApplibQueryProcessor.java Wed Aug 29 14:59:05 2012
@@ -16,12 +16,13 @@ import org.apache.isis.core.metamodel.sp
 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) {
-        super(persistenceManager);
+    public PersistenceQueryFindUsingApplibQueryProcessor(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
+        super(persistenceManager, frameworkSynchronizer);
     }
 
     public List<ObjectAdapter> process(final PersistenceQueryFindUsingApplibQueryDefault persistenceQuery) {

Modified: incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/objectstores/jdo/jdo-datanucleus/src/main/java/org/apache/isis/runtimes/dflt/objectstores/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java Wed Aug 29 14:59:05 2012
@@ -15,6 +15,8 @@ import org.apache.isis.core.metamodel.ad
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.DataNucleusObjectStore;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer;
+import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.FrameworkSynchronizer.CalledFrom;
 import org.apache.isis.runtimes.dflt.objectstores.jdo.datanucleus.persistence.IsisLifecycleListener;
 import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
 import org.apache.isis.runtimes.dflt.runtime.system.persistence.AdapterManagerSpi;
@@ -24,13 +26,12 @@ import org.apache.isis.runtimes.dflt.run
 public abstract class PersistenceQueryProcessorAbstract<T extends PersistenceQuery>
         implements PersistenceQueryProcessor<T> {
 
-    // TODO: review this, want to reuse
-    private final IsisLifecycleListener isisLifecycleListener = new IsisLifecycleListener();
-
     private final PersistenceManager persistenceManager;
+    private final FrameworkSynchronizer frameworkSynchronizer;
 
-    protected PersistenceQueryProcessorAbstract(final PersistenceManager persistenceManager) {
+    protected PersistenceQueryProcessorAbstract(final PersistenceManager persistenceManager, final FrameworkSynchronizer frameworkSynchronizer) {
         this.persistenceManager = persistenceManager;
+        this.frameworkSynchronizer = frameworkSynchronizer;
     }
 
     protected PersistenceManager getPersistenceManager() {
@@ -61,7 +62,7 @@ public abstract class PersistenceQueryPr
         for (final Object pojo : pojos) {
         	// ought not to be necessary, however for some queries it seems that the 
         	// lifecycle listener is not called
-        	isisLifecycleListener.postLoadProcessingFor((PersistenceCapable) pojo);
+        	frameworkSynchronizer.postLoadProcessingFor((PersistenceCapable) pojo, CalledFrom.OS_QUERY);
             ObjectAdapter adapter = getAdapterManager().getAdapterFor(pojo);
             Assert.assertNotNull(adapter);
             adapters.add(adapter);

Modified: incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/AdapterManagerDefault.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/AdapterManagerDefault.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/AdapterManagerDefault.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/AdapterManagerDefault.java Wed Aug 29 14:59:05 2012
@@ -171,6 +171,13 @@ public class AdapterManagerDefault imple
             return adapter;
         }
         
+        // pojo may have been lazily loaded by object store, but we haven't yet seen it
+        final ObjectAdapter lazilyLoadedAdapter = pojoRecreator.lazilyLoaded(pojo);
+        if(lazilyLoadedAdapter != null) {
+            return lazilyLoadedAdapter;
+        }
+        
+        
         // need to create (and possibly map) the adapter.
         final ObjectSpecification objSpec = getSpecificationLoader().loadSpecification(pojo.getClass());
         

Modified: incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreator.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreator.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreator.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreator.java Wed Aug 29 14:59:05 2012
@@ -1,9 +1,22 @@
 package org.apache.isis.runtimes.dflt.runtime.persistence.adaptermanager;
 
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
 
 public interface PojoRecreator {
 
     Object recreatePojo(final TypedOid oid);
+
+    /**
+     * Return an adapter, if possible, for a pojo that was instantiated by the
+     * object store as a result of lazily loading, but which hasn't yet been seen
+     * by the Isis framework.
+     * 
+     * <p>
+     * For example, in the case of JDO object store, downcast to <tt>PersistenceCapable</tt>
+     * and 'look inside' its state.
+     */
+
+    ObjectAdapter lazilyLoaded(Object pojo);
     
 }

Modified: incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreatorDefault.java
URL: http://svn.apache.org/viewvc/incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreatorDefault.java?rev=1378595&r1=1378594&r2=1378595&view=diff
==============================================================================
--- incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreatorDefault.java (original)
+++ incubator/isis/trunk/framework/runtimes/dflt/runtime/src/main/java/org/apache/isis/runtimes/dflt/runtime/persistence/adaptermanager/PojoRecreatorDefault.java Wed Aug 29 14:59:05 2012
@@ -1,5 +1,6 @@
 package org.apache.isis.runtimes.dflt.runtime.persistence.adaptermanager;
 
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
@@ -17,4 +18,13 @@ public class PojoRecreatorDefault implem
         return IsisContext.getSpecificationLoader();
     }
 
+
+    /**
+     * Default implementation simply returns <tt>null</tt>.
+     */
+    @Override
+    public ObjectAdapter lazilyLoaded(Object pojo) {
+        return null;
+    }
+
 }