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
The following commit(s) were added to refs/heads/ISIS-1976-rethink-object-adapters by this push: new 866b09c ISIS-1976: experimental refactoring 866b09c is described below commit 866b09c47d66c5577ef57bc69819471249e60def Author: a.hu...@corax.at <a.hu...@corax.at@luna> AuthorDate: Sun Sep 2 10:57:14 2018 +0200 ISIS-1976: experimental refactoring adapterFor(RootOid) --- .../system/persistence/PersistenceSession5.java | 13 + .../isis/core/runtime/memento/CollectionData.java | 9 + .../apache/isis/core/runtime/memento/Memento.java | 198 +-------------- .../background/CommandExecutorServiceDefault.java | 40 +-- .../AbstractIsisSessionTemplate.java | 93 +++---- .../adaptermanager/ObjectAdapterLegacy.java | 276 +++++++++++++++++++++ 6 files changed, 347 insertions(+), 282 deletions(-) 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 1f78654..6d5baa6 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 @@ -1236,6 +1236,9 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement { } + /** + * foreign refs: 1 + */ @Override public ObjectAdapter adapterForAny(RootOid rootOid) { @@ -1272,6 +1275,9 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement { } } + /** + * foreign refs: 1 + */ @Override public Map<RootOid, ObjectAdapter> adaptersFor(final List<RootOid> rootOids) { return adaptersFor(rootOids, ConcurrencyChecking.NO_CHECK); @@ -1336,6 +1342,8 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement { * This method will <i>always</i> return an object, possibly indicating it is persistent; so make sure that you * know that the oid does indeed represent an object you know exists. * </p> + * + * foreign refs: 4 */ @Override public ObjectAdapter adapterFor(final RootOid rootOid) { @@ -1369,6 +1377,9 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement { * value. This allows the client to retry if they wish. * * @throws {@link org.apache.isis.core.runtime.persistence.ObjectNotFoundException} if the object does not exist. + * + * foreign refs: 0 + * */ @Override public ObjectAdapter adapterFor( @@ -1465,6 +1476,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement { /** * {@inheritDoc} + * foreign refs: ~90 */ @Override public ObjectAdapter adapterFor(final Object pojo) { @@ -1484,6 +1496,7 @@ implements IsisLifecycleListener2.PersistenceSessionLifecycleManagement { /** * {@inheritDoc} + * foreign refs: 2 */ @Override public ObjectAdapter adapterFor(final Object pojo, final ObjectAdapter parentAdapter, final OneToManyAssociation collection) { diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/CollectionData.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/CollectionData.java index e28cc9e..1f2803f 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/CollectionData.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/CollectionData.java @@ -55,5 +55,14 @@ public class CollectionData extends Data { str.append(")"); return str.toString(); } + + /** + * TODO[ISIS-1976] only introduced for refactoring. + */ + @Deprecated + public Data[] getElements() { + return elements; + } + } 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 78f9f7c..9e1eedc 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 @@ -22,14 +22,14 @@ package org.apache.isis.core.runtime.memento; import java.io.Serializable; 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.commons.exceptions.UnknownTypeException; 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.OidMarshaller; -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; @@ -39,14 +39,11 @@ import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySe 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.system.context.IsisContext; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; +import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy; import org.apache.isis.core.runtime.system.session.IsisSessionFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Holds the state for the specified object in serializable form. @@ -195,196 +192,13 @@ public class Memento implements Serializable { } final ObjectSpecification spec = getSpecificationLoader().loadSpecification(data.getClassName()); - - ObjectAdapter adapter; - + final Oid oid = getOid(); - if (spec.isParentedOrFreeCollection()) { - - final Object recreatedPojo = getPersistenceSession().instantiateAndInjectServices(spec); - adapter = getPersistenceSession().mapRecreatedPojo(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().getAdapterFor(typedOid); - if(adapter != null) { - getPersistenceSession().removeAdapter(adapter); - } - // recreate an adapter for the original OID (with correct version) - adapter = getPersistenceSession().adapterFor(typedOid); - - updateObject(adapter, data); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("recreated object {}", adapter.getOid()); - } - return adapter; + return ObjectAdapterLegacy.__Memento.recreateObject(spec, oid, data); } - - private void populateCollection(final ObjectAdapter collectionAdapter, final CollectionData state) { - final ObjectAdapter[] initData = new ObjectAdapter[state.elements.length]; - int i = 0; - for (final Data elementData : state.elements) { - initData[i++] = recreateReference(elementData); - } - final CollectionFacet facet = collectionAdapter.getSpecification().getFacet(CollectionFacet.class); - facet.init(collectionAdapter, initData); - } - - private ObjectAdapter recreateReference(final 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; - } - - - //////////////////////////////////////////////// - // helpers - //////////////////////////////////////////////// - - 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 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.elements; - 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); - } - } - } - - - // /////////////////////////////////////////////////////////////// // toString, debug // /////////////////////////////////////////////////////////////// diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java index 9d4deb0..ef6910a 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java @@ -55,6 +55,7 @@ import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; import org.apache.isis.core.metamodel.specloader.SpecificationLoader; import org.apache.isis.core.runtime.system.context.IsisContext; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; +import org.apache.isis.core.runtime.system.persistence.adaptermanager.ObjectAdapterLegacy; import org.apache.isis.core.runtime.system.session.IsisSessionFactory; import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager; import org.apache.isis.schema.cmd.v1.ActionDto; @@ -348,44 +349,7 @@ public class CommandExecutorServiceDefault implements CommandExecutorService { } private ObjectAdapter adapterFor(final Object targetObject) { - if(targetObject instanceof OidDto) { - final OidDto oidDto = (OidDto) targetObject; - return adapterFor(oidDto); - } - if(targetObject instanceof CollectionDto) { - final CollectionDto collectionDto = (CollectionDto) targetObject; - final List<ValueDto> valueDtoList = collectionDto.getValue(); - final List<Object> pojoList = Lists.newArrayList(); - for (final ValueDto valueDto : valueDtoList) { - ValueType valueType = collectionDto.getType(); - final Object valueOrOidDto = CommonDtoUtils.getValue(valueDto, valueType); - // converting from adapter and back means we handle both - // collections of references and of values - final ObjectAdapter objectAdapter = adapterFor(valueOrOidDto); - Object pojo = objectAdapter != null ? objectAdapter.getObject() : null; - pojoList.add(pojo); - } - return adapterFor(pojoList); - } - if(targetObject instanceof Bookmark) { - final Bookmark bookmark = (Bookmark) targetObject; - return adapterFor(bookmark); - } - return getPersistenceSession().adapterFor(targetObject); - } - - private ObjectAdapter adapterFor(final OidDto oidDto) { - final Bookmark bookmark = Bookmark.from(oidDto); - return adapterFor(bookmark); - } - - private ObjectAdapter adapterFor(final Bookmark bookmark) { - final RootOid rootOid = RootOid.create(bookmark); - return adapterFor(rootOid); - } - - private ObjectAdapter adapterFor(final RootOid rootOid) { - return getPersistenceSession().adapterFor(rootOid); + return ObjectAdapterLegacy.__CommandExecutorServiceDefault.adapterFor(targetObject); } // ////////////////////////////////////// diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java index 318177c..fc01c0f 100644 --- a/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java +++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/sessiontemplate/AbstractIsisSessionTemplate.java @@ -16,14 +16,7 @@ */ package org.apache.isis.core.runtime.sessiontemplate; -import java.util.List; - -import com.google.common.collect.Lists; - -import org.apache.isis.applib.services.bookmark.Bookmark; import org.apache.isis.core.commons.authentication.AuthenticationSession; -import org.apache.isis.core.metamodel.adapter.ObjectAdapter; -import org.apache.isis.core.metamodel.adapter.oid.RootOid; import org.apache.isis.core.metamodel.specloader.SpecificationLoader; import org.apache.isis.core.runtime.system.context.IsisContext; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; @@ -31,11 +24,6 @@ import org.apache.isis.core.runtime.system.session.IsisSession; import org.apache.isis.core.runtime.system.session.IsisSessionFactory; import org.apache.isis.core.runtime.system.transaction.IsisTransactionManager; import org.apache.isis.core.runtime.system.transaction.TransactionalClosure; -import org.apache.isis.schema.common.v1.CollectionDto; -import org.apache.isis.schema.common.v1.OidDto; -import org.apache.isis.schema.common.v1.ValueDto; -import org.apache.isis.schema.common.v1.ValueType; -import org.apache.isis.schema.utils.CommonDtoUtils; public abstract class AbstractIsisSessionTemplate { @@ -90,46 +78,47 @@ public abstract class AbstractIsisSessionTemplate { // ////////////////////////////////////// - protected final ObjectAdapter adapterFor(final Object targetObject) { - if(targetObject instanceof OidDto) { - final OidDto oidDto = (OidDto) targetObject; - return adapterFor(oidDto); - } - if(targetObject instanceof CollectionDto) { - final CollectionDto collectionDto = (CollectionDto) targetObject; - final List<ValueDto> valueDtoList = collectionDto.getValue(); - final List<Object> pojoList = Lists.newArrayList(); - for (final ValueDto valueDto : valueDtoList) { - ValueType valueType = collectionDto.getType(); - final Object valueOrOidDto = CommonDtoUtils.getValue(valueDto, valueType); - // converting from adapter and back means we handle both - // collections of references and of values - final ObjectAdapter objectAdapter = adapterFor(valueOrOidDto); - Object pojo = objectAdapter != null ? objectAdapter.getObject() : null; - pojoList.add(pojo); - } - return adapterFor(pojoList); - } - if(targetObject instanceof Bookmark) { - final Bookmark bookmark = (Bookmark) targetObject; - return adapterFor(bookmark); - } - return getPersistenceSession().adapterFor(targetObject); - } - - protected final ObjectAdapter adapterFor(final OidDto oidDto) { - final Bookmark bookmark = Bookmark.from(oidDto); - return adapterFor(bookmark); - } - - protected final ObjectAdapter adapterFor(final Bookmark bookmark) { - final RootOid rootOid = RootOid.create(bookmark); - return adapterFor(rootOid); - } - - protected final ObjectAdapter adapterFor(final RootOid rootOid) { - return getPersistenceSession().adapterFor(rootOid); - } +//TODO[ISIS-1976] not used !? +// protected final ObjectAdapter adapterFor(final Object targetObject) { +// if(targetObject instanceof OidDto) { +// final OidDto oidDto = (OidDto) targetObject; +// return adapterFor(oidDto); +// } +// if(targetObject instanceof CollectionDto) { +// final CollectionDto collectionDto = (CollectionDto) targetObject; +// final List<ValueDto> valueDtoList = collectionDto.getValue(); +// final List<Object> pojoList = Lists.newArrayList(); +// for (final ValueDto valueDto : valueDtoList) { +// ValueType valueType = collectionDto.getType(); +// final Object valueOrOidDto = CommonDtoUtils.getValue(valueDto, valueType); +// // converting from adapter and back means we handle both +// // collections of references and of values +// final ObjectAdapter objectAdapter = adapterFor(valueOrOidDto); +// Object pojo = objectAdapter != null ? objectAdapter.getObject() : null; +// pojoList.add(pojo); +// } +// return adapterFor(pojoList); +// } +// if(targetObject instanceof Bookmark) { +// final Bookmark bookmark = (Bookmark) targetObject; +// return adapterFor(bookmark); +// } +// return getPersistenceSession().adapterFor(targetObject); +// } +// +// protected final ObjectAdapter adapterFor(final OidDto oidDto) { +// final Bookmark bookmark = Bookmark.from(oidDto); +// return adapterFor(bookmark); +// } +// +// protected final ObjectAdapter adapterFor(final Bookmark bookmark) { +// final RootOid rootOid = RootOid.create(bookmark); +// return adapterFor(rootOid); +// } +// +// protected final ObjectAdapter adapterFor(final RootOid rootOid) { +// return getPersistenceSession().adapterFor(rootOid); +// } // ////////////////////////////////////// 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 d89524f..77e21a8 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 @@ -18,23 +18,53 @@ */ package org.apache.isis.core.runtime.system.persistence.adaptermanager; +import java.util.List; +import java.util.function.Supplier; + +import com.google.common.collect.Lists; + 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.ensure.Assert; import org.apache.isis.core.commons.ensure.IsisAssertException; +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.ParentedCollectionOid; import org.apache.isis.core.metamodel.adapter.oid.RootOid; import org.apache.isis.core.metamodel.adapter.version.Version; 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.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.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.context.IsisContext; import org.apache.isis.core.runtime.system.persistence.PersistenceSession; +import org.apache.isis.schema.common.v1.CollectionDto; +import org.apache.isis.schema.common.v1.OidDto; +import org.apache.isis.schema.common.v1.ValueDto; +import org.apache.isis.schema.common.v1.ValueType; +import org.apache.isis.schema.utils.CommonDtoUtils; +/** + * Interim class, expected to be removed with https://issues.apache.org/jira/browse/ISIS-1976 + */ public class ObjectAdapterLegacy { private static final Logger LOG = LoggerFactory.getLogger(ObjectAdapterLegacy.class); @@ -45,6 +75,10 @@ public class ObjectAdapterLegacy { return objectAdapterContext; } + public static interface ObjectAdapterProvider extends Supplier<ObjectAdapter> { + + } + public static class ObjectAdapterContext /*implements AdapterManager*/ { private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap(); private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap(); @@ -229,6 +263,248 @@ public class ObjectAdapterLegacy { } + // -- CommandExecutorServiceDefault -------------------------------------------------------- + + public static class __CommandExecutorServiceDefault { + + public static ObjectAdapter adapterFor(Object targetObject) { + if(targetObject instanceof OidDto) { + final OidDto oidDto = (OidDto) targetObject; + return adapterFor(oidDto); + } + if(targetObject instanceof CollectionDto) { + final CollectionDto collectionDto = (CollectionDto) targetObject; + final List<ValueDto> valueDtoList = collectionDto.getValue(); + final List<Object> pojoList = Lists.newArrayList(); + for (final ValueDto valueDto : valueDtoList) { + ValueType valueType = collectionDto.getType(); + final Object valueOrOidDto = CommonDtoUtils.getValue(valueDto, valueType); + // converting from adapter and back means we handle both + // collections of references and of values + final ObjectAdapter objectAdapter = adapterFor(valueOrOidDto); + Object pojo = objectAdapter != null ? objectAdapter.getObject() : null; + pojoList.add(pojo); + } + return adapterFor(pojoList); + } + if(targetObject instanceof Bookmark) { + final Bookmark bookmark = (Bookmark) targetObject; + return adapterFor(bookmark); + } + return getPersistenceSession().adapterFor(targetObject); + } + + private static ObjectAdapter adapterFor(final OidDto oidDto) { + final Bookmark bookmark = Bookmark.from(oidDto); + return adapterFor(bookmark); + } + + private static ObjectAdapter adapterFor(final Bookmark bookmark) { + final RootOid rootOid = RootOid.create(bookmark); + return adapterFor(rootOid); + } + + private static ObjectAdapter adapterFor(final RootOid rootOid) { + return getPersistenceSession().adapterFor(rootOid); + } + + private static PersistenceSession getPersistenceSession() { + return IsisContext.getPersistenceSession().orElseThrow(_Exceptions::unexpectedCodeReach); + } + + } + + // -- 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().mapRecreatedPojo(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().getAdapterFor(typedOid); + if(adapter != null) { + getPersistenceSession().removeAdapter(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); + } + + + + } + + }