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/05 18:49:16 UTC
[isis] 03/03: ISIS-1976: improve the ObjectAdapterProvider
interface (API)
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 5a8b180a8337a1d9072f94623af1afa7888ce085
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Sep 5 20:41:07 2018 +0200
ISIS-1976: improve the ObjectAdapterProvider interface (API)
also prepare for removal of the OA by pojo lookup map
Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
.../metamodel/adapter/ObjectAdapterProvider.java | 28 ++++++++--
...ObjectFacetDeclarativeInitializingAbstract.java | 3 +-
.../adaptermanager/ObjectAdapterContext.java | 64 ++++++++++++++--------
.../ObjectAdapterContext_AdapterManager.java | 30 ++++++++++
...ObjectAdapterContext_ObjectAdapterProvider.java | 11 +++-
5 files changed, 103 insertions(+), 33 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java
index e799f5d..fef5bf7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapterProvider.java
@@ -25,6 +25,7 @@ import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.core.metamodel.adapter.oid.Oid;
import org.apache.isis.core.metamodel.adapter.oid.RootOid;
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;
/**
@@ -56,12 +57,19 @@ public interface ObjectAdapterProvider {
OneToManyAssociation collection);
/**
- * @param viewModelPojo
- * @return an ObjectAdapter 'bypassing mapping', that holds the ObjectSpecification
- * FIXME[ISIS-1976] Note: whether or not 'bypassing mapping' should not be exposed by the API.
- * So this further needs refactoring.
+ * Returns an ObjectAdapter that holds the ObjectSpecification used for
+ * interrogating the domain object's metadata.
+ * <p>
+ * Does _not_ perform dependency injection on the domain object. Also bypasses
+ * caching (if any), that is each call to this method creates a new unique instance.
+ * </p>
+ *
+ * @param viewModelPojo domain object
+ * @return
*/
- ObjectAdapter specificationForViewModel(final Object viewModelPojo);
+ ObjectAdapter disposableAdapterForViewModel(Object viewModelPojo);
+
+ ObjectSpecification specificationForViewModel(Object viewModelPojo);
ObjectAdapter adapterForViewModel(
final Object viewModelPojo,
@@ -97,7 +105,12 @@ public interface ObjectAdapterProvider {
}
@Programmatic
- default ObjectAdapter specificationForViewModel(final Object viewModelPojo) {
+ default ObjectAdapter disposableAdapterForViewModel(final Object viewModelPojo) {
+ return getObjectAdapterProvider().disposableAdapterForViewModel(viewModelPojo);
+ }
+
+ @Programmatic
+ default ObjectSpecification specificationForViewModel(Object viewModelPojo) {
return getObjectAdapterProvider().specificationForViewModel(viewModelPojo);
}
@@ -116,6 +129,9 @@ public interface ObjectAdapterProvider {
}
+
+
+
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
index 2b47acd..97cc65e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/recreatable/RecreatableObjectFacetDeclarativeInitializingAbstract.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.facets.object.recreatable;
import java.util.List;
import java.util.Set;
+import java.util.UUID;
import org.apache.isis.applib.services.urlencoding.UrlEncodingService;
import org.apache.isis.commons.internal.memento._Mementos;
@@ -97,7 +98,7 @@ extends RecreatableObjectFacetAbstract {
final _Mementos.Memento memento = _Mementos.create(codec, serializer);
- final ObjectAdapter ownerAdapter = adapterProvider.specificationForViewModel(viewModelPojo);
+ final ObjectAdapter ownerAdapter = adapterProvider.disposableAdapterForViewModel(viewModelPojo);
final ObjectSpecification spec = ownerAdapter.getSpecification();
final List<OneToOneAssociation> properties = spec.getProperties(Contributed.EXCLUDED);
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 a9535a6..5ebfe1f 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
@@ -19,13 +19,16 @@
package org.apache.isis.core.runtime.system.persistence.adaptermanager;
import java.util.List;
+import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.isis.commons.internal.functions._Predicates;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.ensure.Ensure;
import org.apache.isis.core.commons.ensure.IsisAssertException;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
@@ -66,6 +69,7 @@ public class ObjectAdapterContext {
private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
+ private final OidAdapterHashMap oidAdapterMap2 = new OidAdapterHashMap();
private final PersistenceSession persistenceSession;
private final ServicesInjector servicesInjector;
private final SpecificationLoader specificationLoader;
@@ -100,6 +104,7 @@ public class ObjectAdapterContext {
public void open() {
oidAdapterMap.open();
pojoAdapterMap.open();
+ oidAdapterMap2.open();
initServices();
}
@@ -107,6 +112,7 @@ public class ObjectAdapterContext {
try {
oidAdapterMap.close();
+ oidAdapterMap2.close();
} catch(final Throwable ex) {
// ignore
LOG.error("close: oidAdapterMap#close() failed; continuing to avoid memory leakage");
@@ -120,22 +126,45 @@ public class ObjectAdapterContext {
}
}
- // -- CACHING
+ // -- CACHING DEPR.
@Deprecated // don't expose caching
protected ObjectAdapter lookupAdapterByPojo(Object pojo) {
- return pojoAdapterMap.getAdapter(pojo);
+ final ObjectAdapter adapter = pojoAdapterMap.getAdapter(pojo);
+ if(adapter!=null) {
+ Oid y = adapter.getOid();
+ Objects.requireNonNull(y);
+
+ Oid x = objectAdapterProviderMixin.oidFor(pojo);
+ Objects.requireNonNull(x);
+
+ //FIXME[ISIS-1976] oids must match
+ //Ensure.ensureThatArg(x, _Predicates.equalTo(y), ()->String.format("x: %s\ny: %s", ""+x, ""+y));
+ }
+ return adapter;
}
private void putPojo(Object pojo, ObjectAdapter adapter) {
+
+ Oid x = objectAdapterProviderMixin.oidFor(pojo);
+ Oid y = adapter.getOid();
+ Objects.requireNonNull(y);
+
+ //FIXME[ISIS-1976] oids must match
+ //Ensure.ensureThatArg(x, _Predicates.equalTo(y), ()->String.format("x: %s\ny: %s", ""+x, ""+y));
+
+ oidAdapterMap2.add(adapter.getOid(), adapter);
pojoAdapterMap.add(adapter.getObject(), adapter);
}
private void removePojo(ObjectAdapter adapter) {
+ Oid y = adapter.getOid();
+ Objects.requireNonNull(y);
+ oidAdapterMap2.remove(y);
pojoAdapterMap.remove(adapter);
}
- // --
+ // -- CACHING
@Deprecated // don't expose caching
public boolean containsAdapterForPojo(Object pojo) {
@@ -315,28 +344,15 @@ public class ObjectAdapterContext {
oidAdapterMap.add(adapter.getOid(), adapter);
}
- public ObjectAdapter specificationForViewModel(Object viewModelPojo) {
- //FIXME[ISIS-1976]
- // this is horrible, but there's a catch-22 here...
- // we need an adapter in order to query the state of the object via the metamodel, on the other hand
- // we can't create an adapter without the identifier, which is what we're trying to derive
- // so... we create a temporary transient adapter, use it to wrap this adapter and interrogate this pojo,
- // then throw away that adapter (remove from the adapter map)
- final boolean[] createdTemporaryAdapter = {false};
- final ObjectAdapter viewModelAdapter = adapterForViewModel(
- viewModelPojo,
- (ObjectSpecId objectSpecId)->{
- createdTemporaryAdapter[0] = true;
- return RootOid.create(objectSpecId, UUID.randomUUID().toString()); });
-
- //final ObjectSpecification spec = viewModelAdapter.getSpecification();
-
- if(createdTemporaryAdapter[0]) {
- adapterManagerMixin.removeAdapterFromCache(viewModelAdapter);
- }
- return viewModelAdapter;
+ public ObjectAdapter disposableAdapterForViewModel(Object viewModelPojo) {
+ final ObjectSpecification objectSpecification =
+ specificationLoader.loadSpecification(viewModelPojo.getClass());
+ final ObjectSpecId objectSpecId = objectSpecification.getSpecId();
+ final RootOid newRootOid = RootOid.create(objectSpecId, UUID.randomUUID().toString());
+ final ObjectAdapter createdAdapter = adapterManagerMixin.createRootOrAggregatedAdapter(newRootOid, viewModelPojo);
+ return createdAdapter;
}
-
+
public ObjectAdapter adapterForViewModel(Object viewModelPojo, Function<ObjectSpecId, RootOid> rootOidFactory) {
ObjectAdapter viewModelAdapter = adapterManagerMixin.lookupAdapterFor(viewModelPojo);
if(viewModelAdapter == null) {
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
index f88f5f8..e60d247 100644
--- 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
@@ -178,6 +178,36 @@ class ObjectAdapterContext_AdapterManager {
return adapter;
}
+ ObjectAdapter injectServices(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();
+
+ 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;
+ }
+
+ // 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) {
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java
index ba820e3..77545ab 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_ObjectAdapterProvider.java
@@ -116,8 +116,15 @@ class ObjectAdapterContext_ObjectAdapterProvider implements ObjectAdapterProvide
}
@Override
- public ObjectAdapter specificationForViewModel(Object viewModelPojo) {
- return objectAdapterContext.specificationForViewModel(viewModelPojo);
+ public ObjectSpecification specificationForViewModel(Object viewModelPojo) {
+ final ObjectSpecification objectSpecification =
+ specificationLoader.loadSpecification(viewModelPojo.getClass());
+ return objectSpecification;
+ }
+
+ @Override
+ public ObjectAdapter disposableAdapterForViewModel(Object viewModelPojo) {
+ return objectAdapterContext.disposableAdapterForViewModel(viewModelPojo);
}
@Override