You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2018/09/04 20:26:00 UTC

[isis] 18/24: ISIS-1976: let PersistenceSession no longer implement AdapterManager

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch ISIS-1976-rethink-object-adapters
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 9ef889fdbc7909ffc0db48256ebf7c36b3cb28fc
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Sep 4 05:34:57 2018 +0200

    ISIS-1976: let PersistenceSession no longer implement AdapterManager
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../core/metamodel/adapter/mgr/AdapterManager.java |  87 +++--
 .../system/persistence/IsisLifecycleListener.java  |   5 +-
 .../system/persistence/PersistenceSession5.java    | 369 +++------------------
 .../PersistenceSession5_ObjectAdapterProvider.java | 140 ++++++++
 .../queries/PersistenceQueryProcessorAbstract.java |   3 +-
 .../apache/isis/core/runtime/memento/Memento.java  |   3 +-
 .../system/persistence/PersistenceSession.java     |  40 ++-
 .../adaptermanager/ObjectAdapterContext.java       |  64 +++-
 .../ObjectAdapterContext_AdapterManager.java       | 189 +++++++++++
 .../ObjectAdapterContext_Consistency.java          | 119 +++++++
 .../ObjectAdapterContext_MementoSupport.java       | 246 ++++++++++++++
 .../adaptermanager/ObjectAdapterLegacy.java        | 212 ------------
 .../adaptermanager/RootAndCollectionAdapters.java  |   8 +-
 .../wicket/ConverterForObjectAdapter.java          |   8 +-
 .../wicket/ConverterForObjectAdapterMemento.java   |   8 +-
 15 files changed, 894 insertions(+), 607 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
index 0284fbe..70ad13e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/mgr/AdapterManager.java
@@ -23,11 +23,8 @@ import java.util.concurrent.Callable;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
-import org.apache.isis.core.metamodel.adapter.oid.Oid;
 
-public interface AdapterManager extends ObjectAdapterProvider {
+public interface AdapterManager /*extends ObjectAdapterProvider*/ {
 
 
     enum ConcurrencyChecking {
@@ -122,46 +119,46 @@ public interface AdapterManager extends ObjectAdapterProvider {
 
     // -- DEPRECATIONS
 
-    /**
-     * Enable RecreatableObjectFacet to 'temporarily' map an existing pojo to an oid.
-     * @deprecated don't expose caching
-     */
-    @Programmatic @Deprecated
-    ObjectAdapter addRecreatedPojoToCache(Oid oid, Object recreatedPojo);
-
-    /**
-     * Enable RecreatableObjectFacet to remove a 'temporarily' mapped adapter for a pojo.
-     * @deprecated don't expose caching
-     */
-    @Programmatic @Deprecated
-    void removeAdapterFromCache(ObjectAdapter adapter);
-
-    
-    /**
-     * Gets the {@link ObjectAdapter adapter} for the specified domain object if
-     * it exists in the identity map.
-     *
-     * <p>
-     * Provided by the <tt>AdapterManager</tt> when used by framework.
-     *
-     * @param pojo
-     *            - must not be <tt>null</tt>
-     * @return adapter, or <tt>null</tt> if doesn't exist.
-     * @deprecated don't expose caching
-     */
-    @Programmatic @Deprecated
-    ObjectAdapter lookupAdapterFor(Object pojo);
-
-    /**
-     * Gets the {@link ObjectAdapter adapter} for the {@link Oid} if it exists
-     * in the identity map.
-     *
-     * @param oid
-     *            - must not be <tt>null</tt>
-     * @return adapter, or <tt>null</tt> if doesn't exist.
-     * @deprecated don't expose caching
-     */
-    @Programmatic @Deprecated
-    ObjectAdapter lookupAdapterFor(Oid oid);
+//    /**
+//     * Enable RecreatableObjectFacet to 'temporarily' map an existing pojo to an oid.
+//     * @deprecated don't expose caching
+//     */
+//    @Programmatic @Deprecated
+//    ObjectAdapter addRecreatedPojoToCache(Oid oid, Object recreatedPojo);
+//
+//    /**
+//     * Enable RecreatableObjectFacet to remove a 'temporarily' mapped adapter for a pojo.
+//     * @deprecated don't expose caching
+//     */
+//    @Programmatic @Deprecated
+//    void removeAdapterFromCache(ObjectAdapter adapter);
+//
+//    
+//    /**
+//     * Gets the {@link ObjectAdapter adapter} for the specified domain object if
+//     * it exists in the identity map.
+//     *
+//     * <p>
+//     * Provided by the <tt>AdapterManager</tt> when used by framework.
+//     *
+//     * @param pojo
+//     *            - must not be <tt>null</tt>
+//     * @return adapter, or <tt>null</tt> if doesn't exist.
+//     * @deprecated don't expose caching
+//     */
+//    @Programmatic @Deprecated
+//    ObjectAdapter lookupAdapterFor(Object pojo);
+//
+//    /**
+//     * Gets the {@link ObjectAdapter adapter} for the {@link Oid} if it exists
+//     * in the identity map.
+//     *
+//     * @param oid
+//     *            - must not be <tt>null</tt>
+//     * @return adapter, or <tt>null</tt> if doesn't exist.
+//     * @deprecated don't expose caching
+//     */
+//    @Programmatic @Deprecated
+//    ObjectAdapter lookupAdapterFor(Oid oid);
 
 }
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/IsisLifecycleListener.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/IsisLifecycleListener.java
index 6634947..9713474 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/IsisLifecycleListener.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/IsisLifecycleListener.java
@@ -34,6 +34,8 @@ import com.google.common.collect.Maps;
 
 import org.datanucleus.enhancement.Persistable;
 
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
 public class IsisLifecycleListener
 implements AttachLifecycleListener, ClearLifecycleListener, CreateLifecycleListener, DeleteLifecycleListener,
 DetachLifecycleListener, DirtyLifecycleListener, LoadLifecycleListener, StoreLifecycleListener,
@@ -45,13 +47,12 @@ SuspendableListener {
     interface PersistenceSessionLifecycleManagement {
 
         void ensureRootObject(Persistable pojo);
-        void initializeMapAndCheckConcurrency(Persistable pojo);
+        ObjectAdapter initializeMapAndCheckConcurrency(Persistable pojo);
 
         void enlistCreatedAndRemapIfRequiredThenInvokeIsisInvokePersistingOrUpdatedCallback(Persistable pojo);
         void invokeIsisPersistingCallback(Persistable pojo);
         void enlistUpdatingAndInvokeIsisUpdatingCallback(Persistable pojo);
         void enlistDeletingAndInvokeIsisRemovingCallbackFacet(Persistable pojo);
-      //ObjectAdapter getAdapterFor(Persistable pojo);
     }
 
     private final PersistenceSessionLifecycleManagement persistenceSession;
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
index 6e278a2..9910f32 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
@@ -19,8 +19,6 @@
 package org.apache.isis.core.runtime.system.persistence;
 
 import static org.apache.isis.commons.internal.base._Casts.uncheckedCast;
-import static org.apache.isis.commons.internal.functions._Predicates.equalTo;
-import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Modifier;
@@ -57,7 +55,6 @@ import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
 import org.apache.isis.applib.services.iactn.Interaction;
-import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
@@ -65,7 +62,9 @@ import org.apache.isis.core.commons.ensure.Assert;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.factory.InstanceUtil;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
@@ -88,7 +87,6 @@ import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedCallbackFac
 import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatedLifecycleEventFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingCallbackFacet;
 import org.apache.isis.core.metamodel.facets.object.callbacks.UpdatingLifecycleEventFacet;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.metamodel.services.container.query.QueryCardinality;
@@ -97,7 +95,6 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.Contributed;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.runtime.persistence.FixturesInstalledFlag;
 import org.apache.isis.core.runtime.persistence.NotPersistableException;
 import org.apache.isis.core.runtime.persistence.ObjectNotFoundException;
@@ -111,6 +108,7 @@ import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindAllIns
 import org.apache.isis.core.runtime.persistence.query.PersistenceQueryFindUsingApplibQueryDefault;
 import org.apache.isis.core.runtime.services.RequestScopedService;
 import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext.MementoRecreateObjectSupport;
 import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy;
 import org.apache.isis.core.runtime.system.transaction.IsisTransaction;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
@@ -133,6 +131,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession5.class);
     private ObjectAdapterContext objectAdapterContext;
+    private PersistenceSession5_ObjectAdapterProvider objectAdapterProviderMixin;
 
     /**
      * Initialize the object store so that calls to this object store access
@@ -162,7 +161,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
 
         objectAdapterContext = ObjectAdapterLegacy.openContext(servicesInjector, authenticationSession, specificationLoader, this);
-
+        objectAdapterProviderMixin = new PersistenceSession5_ObjectAdapterProvider(this, objectAdapterContext);
+        
         persistenceManager = jdoPersistenceManagerFactory.getPersistenceManager();
 
         final IsisLifecycleListener.PersistenceSessionLifecycleManagement psLifecycleMgmt = this;
@@ -244,13 +244,13 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             }
         }
     }
-
+    
     @Override
     public List<ObjectAdapter> getServices() {
         final List<Object> services = servicesInjector.getRegisteredServices();
         final List<ObjectAdapter> serviceAdapters = _Lists.newArrayList();
         for (final Object servicePojo : services) {
-            ObjectAdapter serviceAdapter = lookupAdapterFor(servicePojo);
+            ObjectAdapter serviceAdapter = objectAdapterContext.lookupAdapterFor(servicePojo);
             if(serviceAdapter == null) {
                 throw new IllegalStateException("ObjectAdapter for service " + servicePojo + " does not exist?!?");
             }
@@ -382,9 +382,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         interaction.clear();
     }
 
-
-
-
     // -- QuerySubmitter impl, findInstancesInTransaction
     @Override
     public <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query) {
@@ -724,7 +721,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
         Objects.requireNonNull(oid);
 
-        final ObjectAdapter adapter = lookupAdapterFor(oid);
+        final ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(oid);
         if (adapter != null) {
             return adapter;
         }
@@ -736,14 +733,11 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                         LOG.debug("getObject; oid={}", oid);
 
                         final Object pojo = loadPersistentPojo(oid);
-                        return addRecreatedPojoToCache(oid, pojo);
+                        return objectAdapterContext.addRecreatedPojoToCache(oid, pojo);
                     }
                 });
     }
 
-
-
-
     // -- loadPersistentPojo
 
     private Object loadPersistentPojo(final RootOid rootOid) {
@@ -844,18 +838,16 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     // -- lazilyLoaded
 
-    private ObjectAdapter mapPersistent(final Persistable pojo) {
+    ObjectAdapter mapPersistent(final Persistable pojo) {
         if (persistenceManager.getObjectId(pojo) == null) {
             return null;
         }
         final RootOid oid = createPersistentOrViewModelOid(pojo);
-        final ObjectAdapter adapter = addRecreatedPojoToCache(oid, pojo);
+        final ObjectAdapter adapter = objectAdapterContext.addRecreatedPojoToCache(oid, pojo);
         return adapter;
     }
 
 
-
-
     // -- refreshRootInTransaction, refreshRoot, resolve
 
     /**
@@ -1089,10 +1081,10 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     @Override
     public ObjectAdapter getAggregateRoot(final ParentedCollectionOid collectionOid) {
         final Oid rootOid = collectionOid.getRootOid();
-        ObjectAdapter rootadapter = lookupAdapterFor(rootOid);
+        ObjectAdapter rootadapter = objectAdapterContext.lookupAdapterFor(rootOid);
         if(rootadapter == null) {
             final Oid parentOidNowPersisted = remappedFrom(rootOid);
-            rootadapter = lookupAdapterFor(parentOidNowPersisted);
+            rootadapter = objectAdapterContext.lookupAdapterFor(parentOidNowPersisted);
         }
         return rootadapter;
     }
@@ -1108,133 +1100,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     // -- AdapterManager implementation
 
     @Override
-    public ObjectAdapter lookupAdapterFor(final Object pojo) {
-        Objects.requireNonNull(pojo);
-
-        return objectAdapterContext.lookupAdapterByPojo(pojo);  
-    }
-
-    @Override
-    public ObjectAdapter lookupAdapterFor(final Oid oid) {
-        Objects.requireNonNull(oid);
-        ensureMapsConsistent(oid);
-
-        return objectAdapterContext.lookupAdapterById(oid);
-    }
-
-
-    private ObjectAdapter existingOrValueAdapter(Object pojo) {
-
-        // attempt to locate adapter for the pojo
-        ObjectAdapter adapter = lookupAdapterFor(pojo);
-        if (adapter != null) {
-            return adapter;
-        }
-
-        // pojo may have been lazily loaded by object store, but we haven't yet seen it
-        if (pojo instanceof Persistable) {
-            adapter = mapPersistent((Persistable) pojo);
-
-            // TODO: could return null if the pojo passed in !dnIsPersistent() || !dnIsDetached()
-            // in which case, we would ought to map as a transient object, rather than fall through and treat as a value?
-        } else {
-            adapter = null;
-        }
-
-        if(adapter != null) {
-            return adapter;
-        }
-
-        // need to create (and possibly map) the adapter.
-        final ObjectSpecification objSpec = specificationLoader.loadSpecification(pojo.getClass());
-
-        // we create value facets as standalone (so not added to maps)
-        if (objSpec.containsFacet(ValueFacet.class)) {
-            adapter = objectAdapterContext.getFactories().createStandaloneAdapter(pojo);
-            return adapter;
-        }
-
-        return null;
-    }
-
-
-
-    /**
-     * Fail early if any problems.
-     */
-    private void ensureMapsConsistent(final ObjectAdapter adapter) {
-        if (adapter.isValue()) {
-            return;
-        }
-        if (adapter.isParentedCollection()) {
-            return;
-        }
-        ensurePojoAdapterMapConsistent(adapter);
-        ensureOidAdapterMapConsistent(adapter);
-    }
-
-    /**
-     * Fail early if any problems.
-     * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
-     */
-    @Deprecated
-    private void ensureMapsConsistent(final Oid oid) {
-        Objects.requireNonNull(oid);
-
-        final ObjectAdapter adapter = objectAdapterContext.lookupAdapterById(oid);
-        if (adapter == null) {
-            return;
-        }
-        ensureOidAdapterMapConsistent(adapter);
-        ensurePojoAdapterMapConsistent(adapter);
-    }
-
-    private void ensurePojoAdapterMapConsistent(final ObjectAdapter adapter) {
-        final Object adapterPojo = adapter.getObject();
-        final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupAdapterByPojo(adapterPojo);
-
-        if(adapterPojo == null) {
-            // nothing to check
-            return;
-        }
-        ensureMapConsistent(adapter, adapterAccordingToMap, "PojoAdapterMap");
-    }
-
-    private void ensureOidAdapterMapConsistent(final ObjectAdapter adapter) {
-        final Oid adapterOid = adapter.getOid();
-        final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupAdapterById(adapterOid);
-
-        if(adapterOid == null) {
-            // nothing to check
-            return;
-        }
-        ensureMapConsistent(adapter, adapterAccordingToMap, "OidAdapterMap");
-    }
-
-    private void ensureMapConsistent(
-            final ObjectAdapter adapter,
-            final ObjectAdapter adapterAccordingToMap,
-            final String mapName) {
-
-        final Oid adapterOid = adapter.getOid();
-
-        // take care not to touch the pojo, since it might have been deleted.
-
-        if(adapterAccordingToMap == null) {
-            throw new IllegalStateException("mismatch in "
-                    + mapName
-                    + ": provided adapter's OID: " + adapterOid + "; but no adapter found in map");
-        }
-
-        ensureThatArg(
-                adapter, equalTo(adapterAccordingToMap),
-                ()->"mismatch in "
-                        + mapName
-                        + ": provided adapter's OID: " + adapterOid + ", \n"
-                        + "but map's adapter's OID was: " + adapterAccordingToMap.getOid());
-    }
-
-    @Override
     public ObjectAdapter adapterForAny(RootOid rootOid) {
 
         final ObjectSpecId specId = rootOid.getObjectSpecId();
@@ -1272,24 +1137,24 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     @Override
     public Map<RootOid, ObjectAdapter> adaptersFor(final List<RootOid> rootOids) {
-        return adaptersFor(rootOids, ConcurrencyChecking.NO_CHECK);
+        return adaptersFor(rootOids, AdapterManager.ConcurrencyChecking.NO_CHECK);
     }
 
     private Map<RootOid,ObjectAdapter> adaptersFor(
             final List<RootOid> rootOids,
-            final ConcurrencyChecking concurrencyChecking) {
+            final AdapterManager.ConcurrencyChecking concurrencyChecking) {
 
         final Map<RootOid, ObjectAdapter> adapterByOid = _Maps.newLinkedHashMap();
 
         List<RootOid> notYetLoadedOids = _Lists.newArrayList();
         for (RootOid rootOid : rootOids) {
             // attempt to locate adapter for the Oid
-            ObjectAdapter adapter = lookupAdapterFor(rootOid);
+            ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(rootOid);
             // handle view models or transient
             if (adapter == null) {
                 if (rootOid.isTransient() || rootOid.isViewModel()) {
                     final Object pojo = recreatePojoTransientOrViewModel(rootOid);
-                    adapter = addRecreatedPojoToCache(rootOid, pojo);
+                    adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
                     sync(concurrencyChecking, adapter, rootOid);
                 }
             }
@@ -1309,7 +1174,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
             if(pojo != null) {
                 ObjectAdapter adapter;
                 try {
-                    adapter = addRecreatedPojoToCache(rootOid, pojo);
+                    adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
                     adapterByOid.put(rootOid, adapter);
                 } catch(ObjectNotFoundException ex) {
                     throw ex; // just rethrow
@@ -1337,7 +1202,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      */
     @Override
     public ObjectAdapter adapterFor(final RootOid rootOid) {
-        return adapterFor(rootOid, ConcurrencyChecking.NO_CHECK);
+        return adapterFor(rootOid, AdapterManager.ConcurrencyChecking.NO_CHECK);
     }
 
 
@@ -1371,10 +1236,10 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     @Override
     public ObjectAdapter adapterFor(
             final RootOid rootOid,
-            final ConcurrencyChecking concurrencyChecking) {
+            final AdapterManager.ConcurrencyChecking concurrencyChecking) {
 
         // attempt to locate adapter for the Oid
-        ObjectAdapter adapter = lookupAdapterFor(rootOid);
+        ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(rootOid);
         if (adapter == null) {
             // else recreate
             try {
@@ -1384,7 +1249,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                 } else {
                     pojo = loadPersistentPojo(rootOid);
                 }
-                adapter = addRecreatedPojoToCache(rootOid, pojo);
+                adapter = objectAdapterContext.addRecreatedPojoToCache(rootOid, pojo);
             } catch(ObjectNotFoundException ex) {
                 throw ex; // just rethrow
             } catch(RuntimeException ex) {
@@ -1401,7 +1266,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
 
     private void sync(
-            final ConcurrencyChecking concurrencyChecking,
+            final AdapterManager.ConcurrencyChecking concurrencyChecking,
             final ObjectAdapter adapter, final RootOid rootOid) {
         // sync versions of original, with concurrency checking if required
         Oid adapterOid = adapter.getOid();
@@ -1419,7 +1284,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                             otherVersion != null &&
                             thisVersion.different(otherVersion)) {
 
-                        if(concurrencyCheckingGloballyEnabled && ConcurrencyChecking.isCurrentlyEnabled()) {
+                        if(concurrencyCheckingGloballyEnabled && AdapterManager.ConcurrencyChecking.isCurrentlyEnabled()) {
                             LOG.info("concurrency conflict detected on {} ({})", recreatedOid, otherVersion);
                             final String currentUser = authenticationSession.getUserName();
                             throw new ConcurrencyException(currentUser, recreatedOid, thisVersion, otherVersion);
@@ -1461,160 +1326,14 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return pojo;
     }
 
-    @Override
-    public ObjectAdapter adapterFor(final Object pojo) {
-
-        if(pojo == null) {
-            return null;
-        }
-        final ObjectAdapter existingOrValueAdapter = existingOrValueAdapter(pojo);
-        if(existingOrValueAdapter != null) {
-            return existingOrValueAdapter;
-        }
-
-        // Creates a new transient root {@link ObjectAdapter adapter} for the supplied domain
-        final RootOid rootOid = createTransientOrViewModelOid(pojo);
-        final ObjectAdapter newAdapter = objectAdapterContext.getFactories().createRootAdapter(pojo, rootOid);
-
-        return mapAndInjectServices(newAdapter);
-    }
-
-    @Override
-    public ObjectAdapter adapterFor(final Object pojo, final ObjectAdapter parentAdapter, final OneToManyAssociation collection) {
-
-        assert parentAdapter != null;
-        assert collection != null;
-
-        final ObjectAdapter existingOrValueAdapter = existingOrValueAdapter(pojo);
-        if(existingOrValueAdapter != null) {
-            return existingOrValueAdapter;
-        }
-
-        ensureMapsConsistent(parentAdapter);
-        
-        // the List, Set etc. instance gets wrapped in its own adapter
-        final ObjectAdapter newAdapter = objectAdapterContext.getFactories()
-                .createCollectionAdapter(pojo, parentAdapter, collection);
-
-        return mapAndInjectServices(newAdapter);
-    }
-
-
-
-    /**
-     * Either returns an existing {@link ObjectAdapter adapter} (as per
-     * {@link #lookupAdapterFor(Object)} or {@link #lookupAdapterFor(Oid)}), otherwise
-     * re-creates an adapter with the specified (persistent) {@link Oid}.
-     *
-     * <p>
-     * Typically called when the {@link Oid} is already known, that is, when
-     * resolving an already-persisted object. Is also available for
-     * <tt>Memento</tt> support however, so {@link Oid} could also represent a
-     * {@link Oid#isTransient() transient} object.
-     *
-     * @param oid
-     * @param recreatedPojo - already known to the object store impl, or a service
-     */
-    @Override
-    public ObjectAdapter addRecreatedPojoToCache(final Oid oid, final Object recreatedPojo) {
-
-        // attempt to locate adapter for the pojo
-        // REVIEW: this check is possibly redundant because the pojo will most likely
-        // have just been instantiated, so won't yet be in any maps
-        final ObjectAdapter adapterLookedUpByPojo = lookupAdapterFor(recreatedPojo);
-        if (adapterLookedUpByPojo != null) {
-            return adapterLookedUpByPojo;
-        }
-
-        // attempt to locate adapter for the Oid
-        final ObjectAdapter adapterLookedUpByOid = lookupAdapterFor(oid);
-        if (adapterLookedUpByOid != null) {
-            return adapterLookedUpByOid;
-        }
-
-        final ObjectAdapter createdAdapter = createRootOrAggregatedAdapter(oid, recreatedPojo);
-        return mapAndInjectServices(createdAdapter);
-    }
-
-    /**
-     * Removes the specified object from both the identity-adapter map, and the
-     * pojo-adapter map.
-     *
-     * <p>
-     * This indicates that the object is no longer in use, and therefore that no
-     * objects exists within the system.
-     *
-     * <p>
-     * If an {@link ObjectAdapter adapter} is removed while its pojo still is
-     * referenced then a subsequent interaction of that pojo will create a
-     * different {@link ObjectAdapter adapter}.
-     *
-     * <p>
-     * TODO: should do a cascade remove of any aggregated objects.
-     */
-    @Override
-    public void removeAdapterFromCache(final ObjectAdapter adapter) {
-        ensureMapsConsistent(adapter);
-        objectAdapterContext.removeAdapter(adapter);
-    }
-
-    
     /**
      * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
      */
     @Deprecated
     private void remapRecreatedPojo(ObjectAdapter adapter, final Object pojo) {
-        removeAdapterFromCache(adapter);
+        objectAdapterContext.removeAdapterFromCache(adapter);
         adapter.replacePojo(pojo);
-        mapAndInjectServices(adapter);
-    }
-
-
-    private ObjectAdapter createRootOrAggregatedAdapter(final Oid oid, final Object pojo) {
-        final ObjectAdapter createdAdapter;
-        if(oid instanceof RootOid) {
-            final RootOid rootOid = (RootOid) oid;
-            createdAdapter = objectAdapterContext.getFactories().createRootAdapter(pojo, rootOid);
-        } else /*if (oid instanceof CollectionOid)*/ {
-            final ParentedCollectionOid collectionOid = (ParentedCollectionOid) oid;
-            createdAdapter = objectAdapterContext.getFactories().createCollectionAdapter(pojo, collectionOid);
-        }
-        return createdAdapter;
-    }
-
-
-
-    private ObjectAdapter mapAndInjectServices(final ObjectAdapter adapter) {
-        // since the whole point of this method is to map an adapter that's just been created.
-        // so we *don't* call ensureMapsConsistent(adapter);
-
-        Assert.assertNotNull(adapter);
-        final Object pojo = adapter.getObject();
-        Assert.assertFalse("POJO Map already contains object", pojo, objectAdapterContext.containsAdapterForPojo(pojo));
-
-        if (LOG.isDebugEnabled()) {
-            // don't interact with the underlying object because may be a ghost
-            // and would trigger a resolve
-            // don't call toString() on adapter because calls hashCode on
-            // underlying object, may also trigger a resolve.
-            LOG.debug("adding identity for adapter with oid={}", adapter.getOid());
-        }
-
-        // value adapters are not mapped (but all others - root and aggregated adapters - are)
-        if (adapter.isValue()) {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("not mapping value adapter");
-            }
-            servicesInjector.injectServicesInto(pojo);
-            return adapter;
-        }
-
-        objectAdapterContext.addAdapterHonoringSpecImmutability(pojo, adapter);
-
-        // must inject after mapping, otherwise infinite loop
-        servicesInjector.injectServicesInto(pojo);
-
-        return adapter;
+        objectAdapterContext.mapAndInjectServices(adapter);
     }
 
     // -- TransactionManager delegate methods
@@ -1622,7 +1341,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return transactionManager.getCurrentTransaction();
     }
 
-
     // -- FrameworkSynchronizer delegate methods
 
     @Override
@@ -1636,7 +1354,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     }
 
     @Override
-    public void initializeMapAndCheckConcurrency(final Persistable pojo) {
+    public ObjectAdapter initializeMapAndCheckConcurrency(final Persistable pojo) {
         final Persistable pc = pojo;
 
         // need to do eagerly, because (if a viewModel then) a
@@ -1646,7 +1364,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final Version datastoreVersion = getVersionIfAny(pc);
 
         final RootOid originalOid;
-        ObjectAdapter adapter = lookupAdapterFor(pojo);
+        ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(pojo);
         if (adapter != null) {
             ensureRootObject(pojo);
             originalOid = (RootOid) adapter.getOid();
@@ -1666,7 +1384,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
                     otherVersion != null &&
                     thisVersion.different(otherVersion)) {
 
-                if (ConcurrencyChecking.isCurrentlyEnabled()) {
+                if (AdapterManager.ConcurrencyChecking.isCurrentlyEnabled()) {
                     LOG.info("concurrency conflict detected on {} ({})", thisOid, otherVersion);
                     final String currentUser = authenticationSession.getUserName();
                     final ConcurrencyException abortCause = new ConcurrencyException(currentUser, thisOid,
@@ -1682,11 +1400,11 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
             // it appears to be possible that there is already an adapter for this Oid,
             // ie from ObjectStore#resolveImmediately()
-            adapter = lookupAdapterFor(originalOid);
+            adapter = objectAdapterContext.lookupAdapterFor(originalOid);
             if (adapter != null) {
                 remapRecreatedPojo(adapter, pojo);
             } else {
-                adapter = addRecreatedPojoToCache(originalOid, pojo);
+                adapter = objectAdapterContext.addRecreatedPojoToCache(originalOid, pojo);
 
                 CallbackFacet.Util.callCallback(adapter, LoadedCallbackFacet.class);
                 postLifecycleEventIfRequired(adapter, LoadedLifecycleEventFacet.class);
@@ -1694,6 +1412,8 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         }
 
         adapter.setVersion(datastoreVersion);
+        
+        return objectAdapterContext.lookupAdapterFor(pojo);
     }
 
     // -- create...Oid (main API)
@@ -1701,7 +1421,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      * Create a new {@link Oid#isTransient() transient} {@link Oid} for the
      * supplied pojo, uniquely distinguishable from any other {@link Oid}.
      */
-    private final RootOid createTransientOrViewModelOid(final Object pojo) {
+    final RootOid createTransientOrViewModelOid(final Object pojo) {
         return newIdentifier(pojo, Type.TRANSIENT);
     }
 
@@ -1770,7 +1490,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
      */
     @Override
     public void invokeIsisPersistingCallback(final Persistable pojo) {
-        final ObjectAdapter adapter = lookupAdapterFor(pojo);
+        final ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(pojo);
         if (adapter == null) {
             // not expected.
             return;
@@ -1831,7 +1551,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
 
     @Override
     public void enlistUpdatingAndInvokeIsisUpdatingCallback(final Persistable pojo) {
-        ObjectAdapter adapter = lookupAdapterFor(pojo);
+        ObjectAdapter adapter = objectAdapterContext.lookupAdapterFor(pojo);
         if (adapter == null) {
             // seen this happen in the case when a parent entity (LeaseItem) has a collection of children
             // objects (LeaseTerm) for which we haven't had a loaded callback fired and so are not yet
@@ -1888,9 +1608,6 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         return Utils.getVersionIfAny(pojo, authenticationSession);
     }
 
-
-
-
     // -- DomainObjectServices impl
 
     @Override
@@ -1962,6 +1679,18 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     public ObjectAdapter adapterForViewModel(Object viewModelPojo, Function<ObjectSpecId, RootOid> rootOidFactory) {
         return objectAdapterContext.adapterForViewModel(viewModelPojo, rootOidFactory);
     }
+
+    @Override
+    public MementoRecreateObjectSupport mementoSupport() {
+        return objectAdapterContext.mementoSupport();
+    }
+    
+    @Override
+    public ObjectAdapterProvider getObjectAdapterProvider() {
+        return objectAdapterProviderMixin;
+    }
+
+
     
 }
 
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_ObjectAdapterProvider.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_ObjectAdapterProvider.java
new file mode 100644
index 0000000..5c8b85d
--- /dev/null
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5_ObjectAdapterProvider.java
@@ -0,0 +1,140 @@
+/*
+ *  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.core.runtime.system.persistence;
+
+import java.util.function.Function;
+
+import org.datanucleus.enhancement.Persistable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext;
+
+public class PersistenceSession5_ObjectAdapterProvider implements ObjectAdapterProvider {
+
+    private static final Logger LOG = LoggerFactory.getLogger(PersistenceSession5_ObjectAdapterProvider.class);
+
+    protected final PersistenceSession5 holder;
+    protected final ObjectAdapterContext objectAdapterContext;
+
+    // -- open
+
+    PersistenceSession5_ObjectAdapterProvider(PersistenceSession5 holder, ObjectAdapterContext objectAdapterContext) {
+        this.holder = holder;
+        this.objectAdapterContext = objectAdapterContext;
+    }
+
+    @Override
+    public ObjectAdapter adapterFor(Object pojo) {
+        //return holder.getObjectAdapterProvider().adapterFor(pojo);
+        
+        if(pojo == null) {
+            return null;
+        }
+        final ObjectAdapter existingOrValueAdapter = existingOrValueAdapter(pojo);
+        if(existingOrValueAdapter != null) {
+            return existingOrValueAdapter;
+        }
+
+        // Creates a new transient root {@link ObjectAdapter adapter} for the supplied domain
+        final RootOid rootOid = holder.createTransientOrViewModelOid(pojo);
+        final ObjectAdapter newAdapter = objectAdapterContext.getFactories().createRootAdapter(pojo, rootOid);
+
+        return objectAdapterContext.mapAndInjectServices(newAdapter);
+    }
+
+    @Override
+    public ObjectAdapter adapterFor(Object pojo, ObjectAdapter parentAdapter, OneToManyAssociation collection) {
+        //return holder.getObjectAdapterProvider().adapterFor(pojo, parentAdapter, collection);
+
+        assert parentAdapter != null;
+        assert collection != null;
+
+        final ObjectAdapter existingOrValueAdapter = existingOrValueAdapter(pojo);
+        if(existingOrValueAdapter != null) {
+            return existingOrValueAdapter;
+        }
+
+        objectAdapterContext.ensureMapsConsistent(parentAdapter);
+
+        // the List, Set etc. instance gets wrapped in its own adapter
+        final ObjectAdapter newAdapter = objectAdapterContext.getFactories()
+                .createCollectionAdapter(pojo, parentAdapter, collection);
+
+        return objectAdapterContext.mapAndInjectServices(newAdapter);
+    }
+
+    @Override
+    public ObjectSpecification specificationForViewModel(Object viewModelPojo) {
+        return objectAdapterContext.specificationForViewModel(viewModelPojo);
+    }
+
+    @Override
+    public ObjectAdapter adapterForViewModel(Object viewModelPojo, Function<ObjectSpecId, RootOid> rootOidFactory) {
+        return objectAdapterContext.adapterForViewModel(viewModelPojo, rootOidFactory);
+    }
+    
+    // -- HELPER
+    
+    protected ObjectAdapter existingOrValueAdapter(Object pojo) {
+
+        // attempt to locate adapter for the pojo
+        ObjectAdapter adapter = objectAdapterContext.lookupAdapterByPojo(pojo);
+        if (adapter != null) {
+            return adapter;
+        }
+
+        // pojo may have been lazily loaded by object store, but we haven't yet seen it
+        if (pojo instanceof Persistable) {
+            adapter = holder.mapPersistent((Persistable) pojo);
+
+            // TODO: could return null if the pojo passed in !dnIsPersistent() || !dnIsDetached()
+            // in which case, we would ought to map as a transient object, rather than fall through and treat as a value?
+        } else {
+            adapter = null;
+        }
+
+        if(adapter != null) {
+            return adapter;
+        }
+        
+        // need to create (and possibly map) the adapter.
+        final ObjectSpecification objSpec = holder.specificationLoader.loadSpecification(pojo.getClass());
+
+        // we create value facets as standalone (so not added to maps)
+        if (objSpec.containsFacet(ValueFacet.class)) {
+            adapter = objectAdapterContext.getFactories().createStandaloneAdapter(pojo);
+            return adapter;
+        }
+
+        return null;
+    }
+
+
+}
+
+
+
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java
index d972273..def59fd 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/queries/PersistenceQueryProcessorAbstract.java
@@ -55,8 +55,7 @@ implements PersistenceQueryProcessor<T> {
             ObjectAdapter adapter;
             if(pojo instanceof Persistable) {
                 // an entity
-                persistenceSession.initializeMapAndCheckConcurrency((Persistable) pojo);
-                adapter = persistenceSession.lookupAdapterFor(pojo);
+                adapter = persistenceSession.initializeMapAndCheckConcurrency((Persistable) pojo);
             } else {
                 // a value type
                 adapter = persistenceSession.adapterFor(pojo);
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java
index 9e1eedc..57d566e 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java
@@ -195,7 +195,8 @@ public class Memento implements Serializable {
         
         final Oid oid = getOid();
 
-        return ObjectAdapterLegacy.__Memento.recreateObject(spec, oid, data);
+        return getPersistenceSession().mementoSupport().recreateObject(spec, oid, data);
+                
     }
 
 
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index 4caa08d..aade4e5 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -18,6 +18,7 @@ package org.apache.isis.core.runtime.system.persistence;
 
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 
 import javax.jdo.PersistenceManager;
 
@@ -32,13 +33,16 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.PersistenceCommand;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.TransactionalResource;
 import org.apache.isis.core.runtime.runner.opts.OptionHandlerFixtureAbstract;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext.MementoRecreateObjectSupport;
 import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager;
 
-public interface PersistenceSession extends AdapterManager, TransactionalResource, SessionScopedComponent {
+public interface PersistenceSession extends ObjectAdapterProvider, TransactionalResource, SessionScopedComponent {
 
     // -- CONSTANTS
 
@@ -59,21 +63,38 @@ public interface PersistenceSession extends AdapterManager, TransactionalResourc
     public static final String DATANUCLEUS_PROPERTIES_ROOT = ROOT_KEY + "impl.";
 
 
-    // -- INTERFACE DECLARATION
+    // -- OBJECT ADAPTER PROVIDER
     
-    default ObjectAdapterProvider getObjectAdapterProvider() {
-        return this;
+    ObjectAdapterProvider getObjectAdapterProvider();
+    default ObjectAdapter adapterFor(Object domainObject) {
+        return getObjectAdapterProvider().adapterFor(domainObject);
+    }
+    default ObjectAdapter adapterFor(
+            final Object pojo,
+            final ObjectAdapter parentAdapter,
+            OneToManyAssociation collection) {
+        return getObjectAdapterProvider().adapterFor(pojo, parentAdapter, collection);
+    }
+    default ObjectSpecification specificationForViewModel(final Object viewModelPojo) {
+        return getObjectAdapterProvider().specificationForViewModel(viewModelPojo);
+    }
+    default ObjectAdapter adapterForViewModel(
+            final Object viewModelPojo, 
+            final Function<ObjectSpecId, RootOid> rootOidFactory) {
+        return getObjectAdapterProvider().adapterForViewModel(viewModelPojo, rootOidFactory);
     }
     
+    //---
+    
+    MementoRecreateObjectSupport mementoSupport();
+    
     ObjectAdapter adapterFor(RootOid rootOid);
-
-    ObjectAdapter adapterFor(RootOid oid, ConcurrencyChecking concurrencyChecking);
-
+    ObjectAdapter adapterFor(RootOid oid, AdapterManager.ConcurrencyChecking concurrencyChecking);
     ObjectAdapter adapterForAny(RootOid rootOid);
-
     Map<RootOid, ObjectAdapter> adaptersFor(List<RootOid> rootOids);
-
     <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query);
+    
+    // --
 
     void close();
 
@@ -155,5 +176,4 @@ public interface PersistenceSession extends AdapterManager, TransactionalResourc
     boolean isRepresentingPersistent(Object pojo);
     boolean isDestroyed(Object pojo);
 
-
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java
index c3cdc1d..29855e3 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext.java
@@ -27,7 +27,6 @@ import org.slf4j.LoggerFactory;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.ensure.IsisAssertException;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
@@ -39,6 +38,7 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtime.memento.Data;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 
 /**
@@ -51,9 +51,12 @@ public class ObjectAdapterContext {
     
     private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
     private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
-    private final AdapterManager adapterManager; //FIXME[ISIS-1976] remove
+    private final PersistenceSession persistenceSession; 
     private final ServicesInjector servicesInjector;
     private final SpecificationLoader specificationLoader;
+    private final ObjectAdapterContext_Consistency consistencyMixin;
+    private final ObjectAdapterContext_AdapterManager adapterManagerMixin;
+    private final ObjectAdapterContext_MementoSupport mementoSupportMixin;
     
     ObjectAdapterContext(
             ServicesInjector servicesInjector, 
@@ -61,7 +64,11 @@ public class ObjectAdapterContext {
             SpecificationLoader specificationLoader, 
             PersistenceSession persistenceSession) {
         
-        this.adapterManager = persistenceSession;
+        this.consistencyMixin = new ObjectAdapterContext_Consistency(this);
+        this.adapterManagerMixin = new ObjectAdapterContext_AdapterManager(this, persistenceSession);
+        this.mementoSupportMixin = new ObjectAdapterContext_MementoSupport(this, persistenceSession);
+        
+        this.persistenceSession = persistenceSession;
         this.servicesInjector = servicesInjector;
         this.specificationLoader = specificationLoader;
         
@@ -137,6 +144,16 @@ public class ObjectAdapterContext {
         pojoAdapterMap.remove(adapter);
     }
     
+    // -- CACHE CONSISTENCY
+    
+    public void ensureMapsConsistent(final ObjectAdapter adapter) {
+        consistencyMixin.ensureMapsConsistent(adapter);
+    }
+
+    public void ensureMapsConsistent(final Oid oid) {
+        consistencyMixin.ensureMapsConsistent(oid);
+    }
+    
     // -- FACTORIES
     
     public static interface ObjectAdapterFactories {
@@ -187,6 +204,38 @@ public class ObjectAdapterContext {
         return objectAdapterFactories;
     }
     
+    // -- ADAPTER MANAGER LEGACY
+    
+    public ObjectAdapter addRecreatedPojoToCache(Oid oid, Object recreatedPojo) {
+        return adapterManagerMixin.addRecreatedPojoToCache(oid, recreatedPojo);
+    }
+    
+    public ObjectAdapter mapAndInjectServices(final ObjectAdapter adapter) {
+        return adapterManagerMixin.mapAndInjectServices(adapter);
+    }
+    
+    public ObjectAdapter lookupAdapterFor(Object pojo) {
+        return adapterManagerMixin.lookupAdapterFor(pojo);
+    }
+    
+    public ObjectAdapter lookupAdapterFor(final Oid oid) {
+        return adapterManagerMixin.lookupAdapterFor(oid);
+    }
+    
+    public void removeAdapterFromCache(final ObjectAdapter adapter) {
+        adapterManagerMixin.removeAdapterFromCache(adapter);
+    }
+    
+    // -- MEMENTO SUPPORT
+    
+    public static interface MementoRecreateObjectSupport {
+        ObjectAdapter recreateObject(ObjectSpecification spec, Oid oid, Data data);
+    }
+    
+    public MementoRecreateObjectSupport mementoSupport() {
+        return mementoSupportMixin;
+    }
+    
     // ------------------------------------------------------------------------------------------------
     
     @Deprecated // don't expose caching
@@ -218,20 +267,20 @@ public class ObjectAdapterContext {
         final ObjectSpecification spec = viewModelAdapter.getSpecification();
         
         if(createdTemporaryAdapter[0]) {
-            adapterManager.removeAdapterFromCache(viewModelAdapter);
+            adapterManagerMixin.removeAdapterFromCache(viewModelAdapter);
         }
         return spec;
     }
 
     public ObjectAdapter adapterForViewModel(Object viewModelPojo, Function<ObjectSpecId, RootOid> rootOidFactory) {
-        ObjectAdapter viewModelAdapter = adapterManager.lookupAdapterFor(viewModelPojo);
+        ObjectAdapter viewModelAdapter = adapterManagerMixin.lookupAdapterFor(viewModelPojo);
         if(viewModelAdapter == null) {
             final ObjectSpecification objectSpecification = 
                     specificationLoader.loadSpecification(viewModelPojo.getClass());
             final ObjectSpecId objectSpecId = objectSpecification.getSpecId();
             final RootOid newRootOid = rootOidFactory.apply(objectSpecId);
 
-            viewModelAdapter = adapterManager.addRecreatedPojoToCache(newRootOid, viewModelPojo);
+            viewModelAdapter = adapterManagerMixin.addRecreatedPojoToCache(newRootOid, viewModelPojo);
         }
         return viewModelAdapter;
     }
@@ -252,7 +301,8 @@ public class ObjectAdapterContext {
         final ObjectAdapter rootAdapter = adapter.getAggregateRoot();  // TODO: REVIEW: think this is redundant; would seem this method is only ever called for roots anyway.
         final RootOid transientRootOid = (RootOid) rootAdapter.getOid();
 
-        final RootAndCollectionAdapters rootAndCollectionAdapters = new RootAndCollectionAdapters(adapter, session);
+        final RootAndCollectionAdapters rootAndCollectionAdapters = 
+                new RootAndCollectionAdapters(adapter, adapterManagerMixin);
 
         removeFromCache(rootAndCollectionAdapters, transientRootOid);
         
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_AdapterManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_AdapterManager.java
new file mode 100644
index 0000000..25febc8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_AdapterManager.java
@@ -0,0 +1,189 @@
+/*
+ *  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.core.runtime.system.persistence.adaptermanager;
+
+import java.util.Objects;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.ParentedCollectionOid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+
+/**
+ *  
+ * @since 2.0.0-M2
+ */
+class ObjectAdapterContext_AdapterManager {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_AdapterManager.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    private final ServicesInjector servicesInjector; 
+    
+    ObjectAdapterContext_AdapterManager(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession) {
+        this.objectAdapterContext = objectAdapterContext;
+        this.persistenceSession = persistenceSession;
+        this.servicesInjector = persistenceSession.getServicesInjector();
+    }
+    
+    /**
+     * Either returns an existing {@link ObjectAdapter adapter} (as per
+     * {@link #lookupAdapterFor(Object)} or {@link #lookupAdapterFor(Oid)}), otherwise
+     * re-creates an adapter with the specified (persistent) {@link Oid}.
+     *
+     * <p>
+     * Typically called when the {@link Oid} is already known, that is, when
+     * resolving an already-persisted object. Is also available for
+     * <tt>Memento</tt> support however, so {@link Oid} could also represent a
+     * {@link Oid#isTransient() transient} object.
+     *
+     * @param oid
+     * @param recreatedPojo - already known to the object store impl, or a service
+     */
+    //@Override
+    public ObjectAdapter addRecreatedPojoToCache(Oid oid, Object recreatedPojo) {
+        // attempt to locate adapter for the pojo
+        // REVIEW: this check is possibly redundant because the pojo will most likely
+        // have just been instantiated, so won't yet be in any maps
+        final ObjectAdapter adapterLookedUpByPojo = lookupAdapterFor(recreatedPojo);
+        if (adapterLookedUpByPojo != null) {
+            return adapterLookedUpByPojo;
+        }
+
+        // attempt to locate adapter for the Oid
+        final ObjectAdapter adapterLookedUpByOid = lookupAdapterFor(oid);
+        if (adapterLookedUpByOid != null) {
+            return adapterLookedUpByOid;
+        }
+
+        final ObjectAdapter createdAdapter = createRootOrAggregatedAdapter(oid, recreatedPojo);
+        return mapAndInjectServices(createdAdapter);
+    }
+
+    /**
+     * Removes the specified object from both the identity-adapter map, and the
+     * pojo-adapter map.
+     *
+     * <p>
+     * This indicates that the object is no longer in use, and therefore that no
+     * objects exists within the system.
+     *
+     * <p>
+     * If an {@link ObjectAdapter adapter} is removed while its pojo still is
+     * referenced then a subsequent interaction of that pojo will create a
+     * different {@link ObjectAdapter adapter}.
+     *
+     * <p>
+     * TODO: should do a cascade remove of any aggregated objects.
+     */
+    //@Override
+    void removeAdapterFromCache(final ObjectAdapter adapter) {
+        objectAdapterContext.ensureMapsConsistent(adapter);
+        objectAdapterContext.removeAdapter(adapter);
+    }
+
+    /**
+     * Gets the {@link ObjectAdapter adapter} for the specified domain object if
+     * it exists in the identity map.
+     *
+     * <p>
+     * Provided by the <tt>AdapterManager</tt> when used by framework.
+     *
+     * @param pojo
+     *            - must not be <tt>null</tt>
+     * @return adapter, or <tt>null</tt> if doesn't exist.
+     * @deprecated don't expose caching
+     */
+    //@Override
+    ObjectAdapter lookupAdapterFor(final Object pojo) {
+        Objects.requireNonNull(pojo);
+
+        return objectAdapterContext.lookupAdapterByPojo(pojo);  
+    }
+
+    /**
+     * Gets the {@link ObjectAdapter adapter} for the {@link Oid} if it exists
+     * in the identity map.
+     *
+     * @param oid
+     *            - must not be <tt>null</tt>
+     * @return adapter, or <tt>null</tt> if doesn't exist.
+     * @deprecated don't expose caching
+     */
+    //@Override
+    ObjectAdapter lookupAdapterFor(final Oid oid) {
+        Objects.requireNonNull(oid);
+        objectAdapterContext.ensureMapsConsistent(oid);
+
+        return objectAdapterContext.lookupAdapterById(oid);
+    }
+ 
+    ObjectAdapter mapAndInjectServices(final ObjectAdapter adapter) {
+        // since the whole point of this method is to map an adapter that's just been created.
+        // so we *don't* call ensureMapsConsistent(adapter);
+
+        Assert.assertNotNull(adapter);
+        final Object pojo = adapter.getObject();
+        Assert.assertFalse("POJO Map already contains object", pojo, objectAdapterContext.containsAdapterForPojo(pojo));
+
+        if (LOG.isDebugEnabled()) {
+            // don't interact with the underlying object because may be a ghost
+            // and would trigger a resolve
+            // don't call toString() on adapter because calls hashCode on
+            // underlying object, may also trigger a resolve.
+            LOG.debug("adding identity for adapter with oid={}", adapter.getOid());
+        }
+
+        // value adapters are not mapped (but all others - root and aggregated adapters - are)
+        if (adapter.isValue()) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("not mapping value adapter");
+            }
+            servicesInjector.injectServicesInto(pojo);
+            return adapter;
+        }
+
+        objectAdapterContext.addAdapterHonoringSpecImmutability(pojo, adapter);
+
+        // must inject after mapping, otherwise infinite loop
+        servicesInjector.injectServicesInto(pojo);
+
+        return adapter;
+    }
+    
+    ObjectAdapter createRootOrAggregatedAdapter(final Oid oid, final Object pojo) {
+        final ObjectAdapter createdAdapter;
+        if(oid instanceof RootOid) {
+            final RootOid rootOid = (RootOid) oid;
+            createdAdapter = objectAdapterContext.getFactories().createRootAdapter(pojo, rootOid);
+        } else /*if (oid instanceof CollectionOid)*/ {
+            final ParentedCollectionOid collectionOid = (ParentedCollectionOid) oid;
+            createdAdapter = objectAdapterContext.getFactories().createCollectionAdapter(pojo, collectionOid);
+        }
+        return createdAdapter;
+    }
+    
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Consistency.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Consistency.java
new file mode 100644
index 0000000..94b94d8
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Consistency.java
@@ -0,0 +1,119 @@
+/*
+ *  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.core.runtime.system.persistence.adaptermanager;
+
+import static org.apache.isis.commons.internal.functions._Predicates.equalTo;
+import static org.apache.isis.core.commons.ensure.Ensure.ensureThatArg;
+
+import java.util.Objects;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+
+/**
+ *  
+ * @since 2.0.0-M2
+ */
+class ObjectAdapterContext_Consistency {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_Consistency.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    
+    ObjectAdapterContext_Consistency(ObjectAdapterContext objectAdapterContext) {
+        this.objectAdapterContext = objectAdapterContext;
+    }
+
+    /**
+     * Fail early if any problems.
+     * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
+     */
+    protected void ensureMapsConsistent(final ObjectAdapter adapter) {
+        if (adapter.isValue()) {
+            return;
+        }
+        if (adapter.isParentedCollection()) {
+            return;
+        }
+        ensurePojoAdapterMapConsistent(adapter);
+        ensureOidAdapterMapConsistent(adapter);
+    }
+
+    /**
+     * Fail early if any problems.
+     * @deprecated https://issues.apache.org/jira/browse/ISIS-1976
+     */
+    protected void ensureMapsConsistent(final Oid oid) {
+        Objects.requireNonNull(oid);
+
+        final ObjectAdapter adapter = objectAdapterContext.lookupAdapterById(oid);
+        if (adapter == null) {
+            return;
+        }
+        ensureOidAdapterMapConsistent(adapter);
+        ensurePojoAdapterMapConsistent(adapter);
+    }
+
+    private void ensurePojoAdapterMapConsistent(final ObjectAdapter adapter) {
+        final Object adapterPojo = adapter.getObject();
+        final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupAdapterByPojo(adapterPojo);
+
+        if(adapterPojo == null) {
+            // nothing to check
+            return;
+        }
+        ensureMapConsistent(adapter, adapterAccordingToMap, "PojoAdapterMap");
+    }
+
+    private void ensureOidAdapterMapConsistent(final ObjectAdapter adapter) {
+        final Oid adapterOid = adapter.getOid();
+        final ObjectAdapter adapterAccordingToMap = objectAdapterContext.lookupAdapterById(adapterOid);
+
+        if(adapterOid == null) {
+            // nothing to check
+            return;
+        }
+        ensureMapConsistent(adapter, adapterAccordingToMap, "OidAdapterMap");
+    }
+
+    private void ensureMapConsistent(
+            final ObjectAdapter adapter,
+            final ObjectAdapter adapterAccordingToMap,
+            final String mapName) {
+
+        final Oid adapterOid = adapter.getOid();
+
+        // take care not to touch the pojo, since it might have been deleted.
+
+        if(adapterAccordingToMap == null) {
+            throw new IllegalStateException("mismatch in "
+                    + mapName
+                    + ": provided adapter's OID: " + adapterOid + "; but no adapter found in map");
+        }
+
+        ensureThatArg(
+                adapter, equalTo(adapterAccordingToMap),
+                ()->"mismatch in "
+                        + mapName
+                        + ": provided adapter's OID: " + adapterOid + ", \n"
+                        + "but map's adapter's OID was: " + adapterAccordingToMap.getOid());
+    }
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
new file mode 100644
index 0000000..d4a028d
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
@@ -0,0 +1,246 @@
+/*
+ *  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.core.runtime.system.persistence.adaptermanager;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
+import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
+import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
+import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.runtime.memento.CollectionData;
+import org.apache.isis.core.runtime.memento.Data;
+import org.apache.isis.core.runtime.memento.ObjectData;
+import org.apache.isis.core.runtime.memento.StandaloneData;
+import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterContext.MementoRecreateObjectSupport;
+
+/**
+ *  
+ * @since 2.0.0-M2
+ */
+class ObjectAdapterContext_MementoSupport implements MementoRecreateObjectSupport {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterContext_MementoSupport.class);
+    private final ObjectAdapterContext objectAdapterContext;
+    private final PersistenceSession persistenceSession;
+    
+    ObjectAdapterContext_MementoSupport(ObjectAdapterContext objectAdapterContext,
+            PersistenceSession persistenceSession) {
+        this.objectAdapterContext = objectAdapterContext;
+        this.persistenceSession = persistenceSession;
+    }
+
+    @Override
+    public ObjectAdapter recreateObject(ObjectSpecification spec, Oid oid, Data data) {
+        ObjectAdapter adapter;
+        
+        if (spec.isParentedOrFreeCollection()) {
+
+            final Object recreatedPojo = persistenceSession.instantiateAndInjectServices(spec);
+            adapter = objectAdapterContext.addRecreatedPojoToCache(oid, recreatedPojo);
+            populateCollection(adapter, (CollectionData) data);
+
+        } else {
+            Assert.assertTrue("oid must be a RootOid representing an object because spec is not a collection and cannot be a value", oid instanceof RootOid);
+            RootOid typedOid = (RootOid) oid;
+
+            // remove adapter if already in the adapter manager maps, because
+            // otherwise would (as a side-effect) update the version to that of the current.
+            adapter = objectAdapterContext.lookupAdapterFor(typedOid);
+            if(adapter != null) {
+                objectAdapterContext.removeAdapterFromCache(adapter);
+            }
+
+            // recreate an adapter for the original OID (with correct version)
+            adapter = persistenceSession.adapterFor(typedOid);
+
+            updateObject(adapter, data);
+        }
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("recreated object {}", adapter.getOid());
+        }
+        return adapter;
+    }
+
+    private ObjectAdapter recreateReference(Data data) {
+     // handle values
+        if (data instanceof StandaloneData) {
+            final StandaloneData standaloneData = (StandaloneData) data;
+            return standaloneData.getAdapter();
+        }
+
+        // reference to entity
+
+        Oid oid = data.getOid();
+        Assert.assertTrue("can only create a reference to an entity", oid instanceof RootOid);
+
+        final RootOid rootOid = (RootOid) oid;
+        final ObjectAdapter referencedAdapter = persistenceSession.adapterFor(rootOid);
+
+        if (data instanceof ObjectData) {
+            if (rootOid.isTransient()) {
+                updateObject(referencedAdapter, data);
+            }
+        }
+        return referencedAdapter;
+    }
+    
+    private void updateObject(final ObjectAdapter adapter, final Data data) {
+        final Object oid = adapter.getOid();
+        if (oid != null && !oid.equals(data.getOid())) {
+            throw new IllegalArgumentException("This memento can only be used to update the ObjectAdapter with the Oid " + data.getOid() + " but is " + oid);
+        }
+        if (!(data instanceof ObjectData)) {
+            throw new IsisException("Expected an ObjectData but got " + data.getClass());
+        }
+
+        updateFieldsAndResolveState(adapter, data);
+
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("object updated {}", adapter.getOid());
+        }
+    }
+    
+    private void populateCollection(final ObjectAdapter collectionAdapter, final CollectionData state) {
+        final ObjectAdapter[] initData = new ObjectAdapter[state.getElements().length];
+        int i = 0;
+        for (final Data elementData : state.getElements()) {
+            initData[i++] = recreateReference(elementData);
+        }
+        final CollectionFacet facet = collectionAdapter.getSpecification().getFacet(CollectionFacet.class);
+        facet.init(collectionAdapter, initData);
+    }
+    
+    private void updateFieldsAndResolveState(final ObjectAdapter objectAdapter, final Data data) {
+
+        boolean dataIsTransient = data.getOid().isTransient();
+
+        if (!dataIsTransient) {
+            updateFields(objectAdapter, data);
+            objectAdapter.getOid().setVersion(data.getOid().getVersion());
+        } else if (objectAdapter.isTransient() && dataIsTransient) {
+            updateFields(objectAdapter, data);
+
+        } else if (objectAdapter.isParentedCollection()) {
+            // this branch is kind-a wierd, I think it's to handle aggregated adapters.
+            updateFields(objectAdapter, data);
+
+        } else {
+            final ObjectData od = (ObjectData) data;
+            if (od.containsField()) {
+                throw new IsisException("Resolve state (for " + objectAdapter + ") inconsistent with fact that data exists for fields");
+            }
+        }
+    }
+    
+    private void updateFields(final ObjectAdapter object, final Data state) {
+        final ObjectData od = (ObjectData) state;
+        final List<ObjectAssociation> fields = object.getSpecification().getAssociations(Contributed.EXCLUDED);
+        for (final ObjectAssociation field : fields) {
+            if (field.isNotPersisted()) {
+                if (field.isOneToManyAssociation()) {
+                    continue;
+                }
+                if (field.containsFacet(PropertyOrCollectionAccessorFacet.class) && !field.containsFacet(PropertySetterFacet.class)) {
+                    LOG.debug("ignoring not-settable field {}", field.getName());
+                    continue;
+                }
+            }
+            updateField(object, od, field);
+        }
+    }
+
+    private void updateField(final ObjectAdapter objectAdapter, final ObjectData objectData, final ObjectAssociation objectAssoc) {
+        final Object fieldData = objectData.getEntry(objectAssoc.getId());
+
+        if (objectAssoc.isOneToManyAssociation()) {
+            updateOneToManyAssociation(objectAdapter, (OneToManyAssociation) objectAssoc, (CollectionData) fieldData);
+
+        } else if (objectAssoc.getSpecification().containsFacet(EncodableFacet.class)) {
+            final EncodableFacet facet = objectAssoc.getSpecification().getFacet(EncodableFacet.class);
+            final ObjectAdapter value = facet.fromEncodedString((String) fieldData);
+            ((OneToOneAssociation) objectAssoc).initAssociation(objectAdapter, value);
+
+        } else if (objectAssoc.isOneToOneAssociation()) {
+            updateOneToOneAssociation(objectAdapter, (OneToOneAssociation) objectAssoc, (Data) fieldData);
+        }
+    }
+
+    private void updateOneToManyAssociation(final ObjectAdapter objectAdapter, final OneToManyAssociation otma, final CollectionData collectionData) {
+        final ObjectAdapter collection = otma.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK);
+        final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collection);
+        final List<ObjectAdapter> original = _Lists.newArrayList();
+        for (final ObjectAdapter adapter : facet.iterable(collection)) {
+            original.add(adapter);
+        }
+
+        final Data[] elements = collectionData.getElements();
+        for (final Data data : elements) {
+            final ObjectAdapter elementAdapter = recreateReference(data);
+            if (!facet.contains(collection, elementAdapter)) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("  association {} changed, added {}", otma, elementAdapter.getOid());
+                }
+                otma.addElement(objectAdapter, elementAdapter, InteractionInitiatedBy.FRAMEWORK);
+            } else {
+                otma.removeElement(objectAdapter, elementAdapter, InteractionInitiatedBy.FRAMEWORK);
+            }
+        }
+
+        for (final ObjectAdapter element : original) {
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("  association {} changed, removed {}", otma, element.getOid());
+            }
+            otma.removeElement(objectAdapter, element, InteractionInitiatedBy.FRAMEWORK);
+        }
+    }
+
+    private void updateOneToOneAssociation(final ObjectAdapter objectAdapter, final OneToOneAssociation otoa, final Data assocData) {
+        if (assocData == null) {
+            otoa.initAssociation(objectAdapter, null);
+        } else {
+            final ObjectAdapter ref = recreateReference(assocData);
+            if (otoa.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK) != ref) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("  association {} changed to {}", otoa, ref.getOid());
+                }
+                otoa.initAssociation(objectAdapter, ref);
+            }
+        }
+    }
+   
+}
\ No newline at end of file
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java
index 2f01ffa..af9930f 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterLegacy.java
@@ -26,31 +26,12 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.ensure.Assert;
-import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacetUtils;
-import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
-import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
-import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySetterFacet;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.Contributed;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
-import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.runtime.memento.CollectionData;
-import org.apache.isis.core.runtime.memento.Data;
-import org.apache.isis.core.runtime.memento.ObjectData;
-import org.apache.isis.core.runtime.memento.StandaloneData;
 import org.apache.isis.core.runtime.system.context.IsisContext;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 import org.apache.isis.schema.common.v1.CollectionDto;
@@ -129,197 +110,4 @@ public class ObjectAdapterLegacy {
         
     }
     
-    // -- Memento --------------------------------------------------------
-
-    public static class __Memento {
-        
-        public static ObjectAdapter recreateObject(ObjectSpecification spec, Oid oid, Data data) {
-            ObjectAdapter adapter;
-            
-            if (spec.isParentedOrFreeCollection()) {
-
-                final Object recreatedPojo = getPersistenceSession().instantiateAndInjectServices(spec);
-                adapter = getPersistenceSession().addRecreatedPojoToCache(oid, recreatedPojo);
-                populateCollection(adapter, (CollectionData) data);
-
-            } else {
-                Assert.assertTrue("oid must be a RootOid representing an object because spec is not a collection and cannot be a value", oid instanceof RootOid);
-                RootOid typedOid = (RootOid) oid;
-
-                // remove adapter if already in the adapter manager maps, because
-                // otherwise would (as a side-effect) update the version to that of the current.
-                adapter = getPersistenceSession().lookupAdapterFor(typedOid);
-                if(adapter != null) {
-                    getPersistenceSession().removeAdapterFromCache(adapter);
-                }
-
-                // recreate an adapter for the original OID (with correct version)
-                adapter = getPersistenceSession().adapterFor(typedOid);
-
-                ObjectAdapterLegacy.__Memento.updateObject(adapter, data);
-            }
-
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("recreated object {}", adapter.getOid());
-            }
-            return adapter;
-        }
-
-        private static ObjectAdapter recreateReference(Data data) {
-         // handle values
-            if (data instanceof StandaloneData) {
-                final StandaloneData standaloneData = (StandaloneData) data;
-                return standaloneData.getAdapter();
-            }
-
-            // reference to entity
-
-            Oid oid = data.getOid();
-            Assert.assertTrue("can only create a reference to an entity", oid instanceof RootOid);
-
-            final RootOid rootOid = (RootOid) oid;
-            final ObjectAdapter referencedAdapter = getPersistenceSession().adapterFor(rootOid);
-
-            if (data instanceof ObjectData) {
-                if (rootOid.isTransient()) {
-                    updateObject(referencedAdapter, data);
-                }
-            }
-            return referencedAdapter;
-        }
-        
-        private static void updateObject(final ObjectAdapter adapter, final Data data) {
-            final Object oid = adapter.getOid();
-            if (oid != null && !oid.equals(data.getOid())) {
-                throw new IllegalArgumentException("This memento can only be used to update the ObjectAdapter with the Oid " + data.getOid() + " but is " + oid);
-            }
-            if (!(data instanceof ObjectData)) {
-                throw new IsisException("Expected an ObjectData but got " + data.getClass());
-            }
-
-            updateFieldsAndResolveState(adapter, data);
-
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("object updated {}", adapter.getOid());
-            }
-        }
-        
-        private static void populateCollection(final ObjectAdapter collectionAdapter, final CollectionData state) {
-            final ObjectAdapter[] initData = new ObjectAdapter[state.getElements().length];
-            int i = 0;
-            for (final Data elementData : state.getElements()) {
-                initData[i++] = recreateReference(elementData);
-            }
-            final CollectionFacet facet = collectionAdapter.getSpecification().getFacet(CollectionFacet.class);
-            facet.init(collectionAdapter, initData);
-        }
-        
-        private static void updateFieldsAndResolveState(final ObjectAdapter objectAdapter, final Data data) {
-
-            boolean dataIsTransient = data.getOid().isTransient();
-
-            if (!dataIsTransient) {
-                updateFields(objectAdapter, data);
-                objectAdapter.getOid().setVersion(data.getOid().getVersion());
-            } else if (objectAdapter.isTransient() && dataIsTransient) {
-                updateFields(objectAdapter, data);
-
-            } else if (objectAdapter.isParentedCollection()) {
-                // this branch is kind-a wierd, I think it's to handle aggregated adapters.
-                updateFields(objectAdapter, data);
-
-            } else {
-                final ObjectData od = (ObjectData) data;
-                if (od.containsField()) {
-                    throw new IsisException("Resolve state (for " + objectAdapter + ") inconsistent with fact that data exists for fields");
-                }
-            }
-        }
-        
-        private static void updateFields(final ObjectAdapter object, final Data state) {
-            final ObjectData od = (ObjectData) state;
-            final List<ObjectAssociation> fields = object.getSpecification().getAssociations(Contributed.EXCLUDED);
-            for (final ObjectAssociation field : fields) {
-                if (field.isNotPersisted()) {
-                    if (field.isOneToManyAssociation()) {
-                        continue;
-                    }
-                    if (field.containsFacet(PropertyOrCollectionAccessorFacet.class) && !field.containsFacet(PropertySetterFacet.class)) {
-                        LOG.debug("ignoring not-settable field {}", field.getName());
-                        continue;
-                    }
-                }
-                updateField(object, od, field);
-            }
-        }
-
-        private static void updateField(final ObjectAdapter objectAdapter, final ObjectData objectData, final ObjectAssociation objectAssoc) {
-            final Object fieldData = objectData.getEntry(objectAssoc.getId());
-
-            if (objectAssoc.isOneToManyAssociation()) {
-                updateOneToManyAssociation(objectAdapter, (OneToManyAssociation) objectAssoc, (CollectionData) fieldData);
-
-            } else if (objectAssoc.getSpecification().containsFacet(EncodableFacet.class)) {
-                final EncodableFacet facet = objectAssoc.getSpecification().getFacet(EncodableFacet.class);
-                final ObjectAdapter value = facet.fromEncodedString((String) fieldData);
-                ((OneToOneAssociation) objectAssoc).initAssociation(objectAdapter, value);
-
-            } else if (objectAssoc.isOneToOneAssociation()) {
-                updateOneToOneAssociation(objectAdapter, (OneToOneAssociation) objectAssoc, (Data) fieldData);
-            }
-        }
-
-        private static void updateOneToManyAssociation(final ObjectAdapter objectAdapter, final OneToManyAssociation otma, final CollectionData collectionData) {
-            final ObjectAdapter collection = otma.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK);
-            final CollectionFacet facet = CollectionFacetUtils.getCollectionFacetFromSpec(collection);
-            final List<ObjectAdapter> original = _Lists.newArrayList();
-            for (final ObjectAdapter adapter : facet.iterable(collection)) {
-                original.add(adapter);
-            }
-
-            final Data[] elements = collectionData.getElements();
-            for (final Data data : elements) {
-                final ObjectAdapter elementAdapter = recreateReference(data);
-                if (!facet.contains(collection, elementAdapter)) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("  association {} changed, added {}", otma, elementAdapter.getOid());
-                    }
-                    otma.addElement(objectAdapter, elementAdapter, InteractionInitiatedBy.FRAMEWORK);
-                } else {
-                    otma.removeElement(objectAdapter, elementAdapter, InteractionInitiatedBy.FRAMEWORK);
-                }
-            }
-
-            for (final ObjectAdapter element : original) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("  association {} changed, removed {}", otma, element.getOid());
-                }
-                otma.removeElement(objectAdapter, element, InteractionInitiatedBy.FRAMEWORK);
-            }
-        }
-
-        private static void updateOneToOneAssociation(final ObjectAdapter objectAdapter, final OneToOneAssociation otoa, final Data assocData) {
-            if (assocData == null) {
-                otoa.initAssociation(objectAdapter, null);
-            } else {
-                final ObjectAdapter ref = recreateReference(assocData);
-                if (otoa.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK) != ref) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("  association {} changed to {}", otoa, ref.getOid());
-                    }
-                    otoa.initAssociation(objectAdapter, ref);
-                }
-            }
-        }
-        
-        private static PersistenceSession getPersistenceSession() {
-            return IsisContext.getPersistenceSession().orElseThrow(_Exceptions::unexpectedCodeReach);
-        }
-
-
-        
-    }
-    
-    
-
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/RootAndCollectionAdapters.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/RootAndCollectionAdapters.java
index 5463820..f81a169 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/RootAndCollectionAdapters.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/RootAndCollectionAdapters.java
@@ -52,11 +52,11 @@ class RootAndCollectionAdapters implements Iterable<ObjectAdapter> {
 
     public RootAndCollectionAdapters(
             final ObjectAdapter parentAdapter,
-            final AdapterManager adapterManager) {
+            final ObjectAdapterContext_AdapterManager adapterManagerMixin) {
         Assert.assertNotNull(parentAdapter);
         this.rootAdapterOid = (RootOid) parentAdapter.getOid();
         this.parentAdapter = parentAdapter;
-        addCollectionAdapters(adapterManager);
+        addCollectionAdapters(adapterManagerMixin);
     }
 
     public ObjectAdapter getRootAdapter() {
@@ -96,10 +96,10 @@ class RootAndCollectionAdapters implements Iterable<ObjectAdapter> {
     // Helpers
     ////////////////////////////////////////////////////////////////////////
 
-    private void addCollectionAdapters(AdapterManager objectAdapterLookup) {
+    private void addCollectionAdapters(ObjectAdapterContext_AdapterManager adapterManagerMixin) {
         for (final OneToManyAssociation otma : parentAdapter.getSpecification().getCollections(Contributed.EXCLUDED)) {
             final ParentedCollectionOid collectionOid = new ParentedCollectionOid((RootOid) rootAdapterOid, otma);
-            final ObjectAdapter collectionAdapter = objectAdapterLookup.lookupAdapterFor(collectionOid);
+            final ObjectAdapter collectionAdapter = adapterManagerMixin.lookupAdapterFor(collectionOid);
             if (collectionAdapter != null) {
                 // collection adapters are lazily created and so there may not be one.
                 addCollectionAdapter(otma, collectionAdapter);
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java
index afd9e0f..a87b80d 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapter.java
@@ -23,6 +23,7 @@ import java.util.Locale;
 
 import org.apache.wicket.util.convert.IConverter;
 
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
@@ -44,8 +45,11 @@ public class ConverterForObjectAdapter implements IConverter<ObjectAdapter> {
      */
     @Override
     public ObjectAdapter convertToObject(final String value, final Locale locale) {
-        final Oid oid = RootOid.deStringEncoded(value);
-        return getPersistenceSession().lookupAdapterFor(oid);
+        final RootOid rootOid = RootOid.deStringEncoded(value);
+        
+        //FIXME[ISIS-1976]
+        //return getPersistenceSession().lookupAdapterFor(rootOid);
+        throw _Exceptions.notImplemented();
     }
 
     /**
diff --git a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java
index 48db82b..ff3ce43 100644
--- a/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java
+++ b/core/viewer-wicket-impl/src/main/java/org/apache/isis/viewer/wicket/viewer/integration/wicket/ConverterForObjectAdapterMemento.java
@@ -25,6 +25,7 @@ import com.google.common.base.Strings;
 
 import org.apache.wicket.util.convert.IConverter;
 
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
@@ -54,8 +55,11 @@ public class ConverterForObjectAdapterMemento implements IConverter<ObjectAdapte
             return null;
         }
         final Oid oid = RootOid.deStringEncoded(value);
-        final ObjectAdapter adapter = getPersistenceSession().lookupAdapterFor(oid);
-        return ObjectAdapterMemento.createOrNull(adapter);
+        
+        //FIXME[ISIS-1976]
+        //final ObjectAdapter adapter = getPersistenceSession().lookupAdapterFor(oid);
+        //return ObjectAdapterMemento.createOrNull(adapter);
+        throw _Exceptions.notImplemented();
     }
 
     /**