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/06 16:12:56 UTC
[isis] 09/18: ISIS-1976: add layer of abstraction
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 392687a4ac27f3bebf3ac08116901b154becfda6
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Sep 6 06:04:41 2018 +0200
ISIS-1976: add layer of abstraction
Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
.../core/metamodel/services/ServicesInjector.java | 39 +++--
.../adaptermanager/ObjectAdapterContext.java | 194 +++++++++++----------
.../ObjectAdapterContext_AdapterManager.java | 3 +-
...ObjectAdapterContext_ObjectAdapterProvider.java | 12 +-
4 files changed, 140 insertions(+), 108 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
index f80535b..d293abc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
@@ -23,11 +23,16 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.services.exceprecog.ExceptionRecognizer;
+import org.apache.isis.commons.internal.base._Lazy;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.collections._Collections;
import org.apache.isis.commons.internal.collections._Lists;
@@ -48,8 +53,6 @@ import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.runtime.authentication.AuthenticationManager;
import org.apache.isis.core.runtime.authorization.AuthorizationManager;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* The repository of services, also able to inject into any object.
@@ -78,7 +81,7 @@ public class ServicesInjector implements ApplicationScopedComponent {
* services that are assignable to the type. It's possible that this is an empty list.
*/
private final Map<Class<?>, List<Object>> servicesAssignableToType = _Maps.newHashMap();
- private final Map<Class<?>, Object> serviceByConcreteType = _Maps.newHashMap();
+ private final _Lazy<Map<Class<?>, Object>> serviceByConcreteType = _Lazy.of(this::initServiceByConcreteType);
private final Map<Class<?>, Method[]> methodsByClassCache = _Maps.newHashMap();
private final Map<Class<?>, Field[]> fieldsByClassCache = _Maps.newHashMap();
@@ -143,18 +146,30 @@ public class ServicesInjector implements ApplicationScopedComponent {
serviceByConcreteType.clear();
autowire();
}
+
+ private Map<Class<?>, Object> initServiceByConcreteType(){
+ final Map<Class<?>, Object> map = _Maps.newHashMap();
+ for (Object service : services) {
+ final Class<?> concreteType = service.getClass();
+ map.put(concreteType, service);
+ }
+ return map;
+ }
public boolean isRegisteredService(final Class<?> cls) {
- // lazily construct cache
- if(serviceByConcreteType.isEmpty()) {
- for (Object service : services) {
- final Class<?> concreteType = service.getClass();
- serviceByConcreteType.put(concreteType, service);
- }
- }
- return serviceByConcreteType.containsKey(cls);
+ return serviceByConcreteType.get().containsKey(cls);
}
+ public boolean isRegisteredServiceInstance(final Object pojo) {
+ if(pojo==null) {
+ return false;
+ }
+ final Class<?> key = pojo.getClass();
+ final Object serviceInstance = serviceByConcreteType.get().get(key);
+ return Objects.equals(pojo, serviceInstance);
+ }
+
+
public <T> void addFallbackIfRequired(final Class<T> serviceClass, final T serviceInstance) {
if(!contains(services, serviceClass)) {
// add to beginning;
@@ -206,7 +221,7 @@ public class ServicesInjector implements ApplicationScopedComponent {
public List<Object> getRegisteredServices() {
return Collections.unmodifiableList(services);
}
-
+
// -- INJECT SERVICES INTO
/**
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 5ebfe1f..06642b2 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
@@ -22,10 +22,14 @@ import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
+import java.util.function.Supplier;
+
+import com.google.common.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.commons.internal.functions._Predicates;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.commons.ensure.Ensure;
@@ -44,7 +48,9 @@ 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.persistence.adapter.PojoAdapter;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
+import org.apache.isis.core.runtime.threadpool.ThreadPoolSupport;
/**
* Encapsulate ObjectAdpater life-cycling.
@@ -67,9 +73,76 @@ public class ObjectAdapterContext {
return objectAdapterContext;
}
- private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
- private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
- private final OidAdapterHashMap oidAdapterMap2 = new OidAdapterHashMap();
+ private final static class Cache {
+ private final PojoAdapterHashMap pojoAdapterMap = new PojoAdapterHashMap();
+ private final OidAdapterHashMap oidAdapterMap = new OidAdapterHashMap();
+
+ public void open() {
+ oidAdapterMap.open();
+ pojoAdapterMap.open();
+ }
+
+ public void close() {
+
+ try {
+ oidAdapterMap.close();
+ } catch(final Throwable ex) {
+ // ignore
+ LOG.error("close: oidAdapterMap#close() failed; continuing to avoid memory leakage");
+ }
+
+ try {
+ pojoAdapterMap.close();
+ } catch(final Throwable ex) {
+ // ignore
+ LOG.error("close: pojoAdapterMap#close() failed; continuing to avoid memory leakage");
+ }
+ }
+
+ private ObjectAdapter lookupAdapterByPojo(Object pojo) {
+ final ObjectAdapter adapter = pojoAdapterMap.getAdapter(pojo);
+ return adapter;
+ }
+
+ private void putPojo(Object pojo, ObjectAdapter adapter) {
+ pojoAdapterMap.add(adapter.getObject(), adapter);
+ }
+
+ private void removePojo(ObjectAdapter adapter) {
+ pojoAdapterMap.remove(adapter);
+ }
+
+ private ObjectAdapter lookupAdapterById(Oid oid) {
+ return oidAdapterMap.getAdapter(oid);
+ }
+
+ private void addAdapter(ObjectAdapter adapter) {
+ if(adapter==null) {
+ return; // nothing to do
+ }
+ final Oid oid = adapter.getOid();
+ if (oid != null) { // eg. value objects don't have an Oid
+ oidAdapterMap.add(oid, adapter);
+ }
+ putPojo(adapter.getObject(), adapter);
+ }
+
+ private void removeAdapter(ObjectAdapter adapter) {
+ LOG.debug("removing adapter: {}", adapter);
+ if(adapter==null) {
+ return; // nothing to do
+ }
+ final Oid oid = adapter.getOid();
+ if (oid != null) { // eg. value objects don't have an Oid
+ oidAdapterMap.remove(oid);
+ }
+ removePojo(adapter);
+ }
+
+ }
+
+ private final Cache cache = new Cache();
+
private final PersistenceSession persistenceSession;
private final ServicesInjector servicesInjector;
private final SpecificationLoader specificationLoader;
@@ -102,103 +175,47 @@ public class ObjectAdapterContext {
// -- LIFE-CYCLING
public void open() {
- oidAdapterMap.open();
- pojoAdapterMap.open();
- oidAdapterMap2.open();
+ cache.open();
initServices();
}
public void close() {
-
- try {
- oidAdapterMap.close();
- oidAdapterMap2.close();
- } catch(final Throwable ex) {
- // ignore
- LOG.error("close: oidAdapterMap#close() failed; continuing to avoid memory leakage");
- }
-
- try {
- pojoAdapterMap.close();
- } catch(final Throwable ex) {
- // ignore
- LOG.error("close: pojoAdapterMap#close() failed; continuing to avoid memory leakage");
- }
+ cache.close();
}
- // -- CACHING DEPR.
+ // -- CACHING POJO
@Deprecated // don't expose caching
protected ObjectAdapter lookupAdapterByPojo(Object 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);
+ return cache.lookupAdapterByPojo(pojo);
}
- 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) {
return lookupAdapterByPojo(pojo)!=null;
}
+ // -- CACHING OID
+
@Deprecated // don't expose caching
protected ObjectAdapter lookupAdapterById(Oid oid) {
- return oidAdapterMap.getAdapter(oid);
+ return cache.lookupAdapterById(oid);
}
+
+ private OidAdapterHashMap oidAdapterMap() {
+ return cache.oidAdapterMap;
+ }
+
+ // -- CACHING BOTH
@Deprecated // don't expose caching
public void addAdapter(ObjectAdapter adapter) {
- if(adapter==null) {
- return; // nothing to do
- }
- final Oid oid = adapter.getOid();
- if (oid != null) { // eg. value objects don't have an Oid
- oidAdapterMap.add(oid, adapter);
- }
- putPojo(adapter.getObject(), adapter);
+ cache.addAdapter(adapter);
}
@Deprecated // don't expose caching
public void removeAdapter(ObjectAdapter adapter) {
- LOG.debug("removing adapter: {}", adapter);
- if(adapter==null) {
- return; // nothing to do
- }
- final Oid oid = adapter.getOid();
- if (oid != null) { // eg. value objects don't have an Oid
- oidAdapterMap.remove(oid);
- }
- removePojo(adapter);
+ cache.removeAdapter(adapter);
}
// -- CACHE CONSISTENCY
@@ -327,7 +344,8 @@ public class ObjectAdapterContext {
// remap as Persistent if required
if (serviceAdapter.getOid().isTransient()) {
- remapAsPersistent(serviceAdapter, null, persistenceSession);
+ _Exceptions.unexpectedCodeReach();
+ //remapAsPersistent(serviceAdapter, null, persistenceSession);
}
}
}
@@ -337,11 +355,11 @@ public class ObjectAdapterContext {
// add all aggregated collections
final ObjectSpecification objSpec = adapter.getSpecification();
if (!adapter.isParentedCollection() || adapter.isParentedCollection() && !objSpec.isImmutable()) {
- putPojo(pojo, adapter);
+ cache.putPojo(pojo, adapter);
}
// order is important - add to pojo map first, then identity map
- oidAdapterMap.add(adapter.getOid(), adapter);
+ oidAdapterMap().add(adapter.getOid(), adapter);
}
public ObjectAdapter disposableAdapterForViewModel(Object viewModelPojo) {
@@ -367,9 +385,6 @@ public class ObjectAdapterContext {
}
/**
- * was in PersisenceSessionX, temporarily moved here to successfully compile
- *
- * <p>
* Note that there is no management of {@link Version}s here. That is
* because the {@link PersistenceSession} is expected to manage this.
*
@@ -434,7 +449,7 @@ public class ObjectAdapterContext {
for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
final ParentedCollectionOid previousCollectionOid = (ParentedCollectionOid) collectionAdapter.getOid();
final ParentedCollectionOid persistedCollectionOid = previousCollectionOid.asPersistent(persistedRootOid);
- oidAdapterMap.add(persistedCollectionOid, collectionAdapter);
+ oidAdapterMap().add(persistedCollectionOid, collectionAdapter);
}
// some object store implementations may replace collection instances (eg ORM may replace with a cglib-enhanced
@@ -449,9 +464,9 @@ public class ObjectAdapterContext {
final Object collectionPojoActuallyOnPojo = getCollectionPojo(otma, adapterReplacement);
if (collectionPojoActuallyOnPojo != collectionPojoWrappedByAdapter) {
- removePojo(collectionAdapter);
+ cache.removePojo(collectionAdapter);
final ObjectAdapter newCollectionAdapter = collectionAdapter.withPojo(collectionPojoActuallyOnPojo);
- putPojo(collectionPojoActuallyOnPojo, newCollectionAdapter);
+ cache.putPojo(collectionPojoActuallyOnPojo, newCollectionAdapter);
}
}
@@ -460,10 +475,10 @@ public class ObjectAdapterContext {
private void removeFromCache(
final RootAndCollectionAdapters rootAndCollectionAdapters,
final RootOid transientRootOid) {
- LOG.debug("remapAsPersistent: {}", transientRootOid);
+
LOG.debug("removing root adapter from oid map");
- boolean removed = oidAdapterMap.remove(transientRootOid);
+ boolean removed = oidAdapterMap().remove(transientRootOid);
if (!removed) {
LOG.warn("could not remove oid: {}", transientRootOid);
// should we fail here with a more serious error?
@@ -474,7 +489,7 @@ public class ObjectAdapterContext {
}
for (final ObjectAdapter collectionAdapter : rootAndCollectionAdapters) {
final Oid collectionOid = collectionAdapter.getOid();
- removed = oidAdapterMap.remove(collectionOid);
+ removed = oidAdapterMap().remove(collectionOid);
if (!removed) {
ObjectAdapterLegacy.LOG.warn("could not remove collectionOid: {}", collectionOid);
// should we fail here with a more serious error?
@@ -493,11 +508,8 @@ public class ObjectAdapterContext {
@Deprecated
public ObjectAdapter remapRecreatedPojo(ObjectAdapter adapter, final Object pojo) {
final ObjectAdapter newAdapter = adapter.withPojo(pojo);
- removePojo(adapter);
- removePojo(newAdapter);
-
- oidAdapterMap.remove(adapter.getOid());
- oidAdapterMap.remove(newAdapter.getOid());
+ cache.removeAdapter(adapter);
+ cache.removeAdapter(newAdapter);
//FIXME[ISIS-1976] can't remove yet, does have strange side-effects
if(true){
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 e60d247..7936a9d 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
@@ -23,7 +23,9 @@ import java.util.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.isis.commons.internal.functions._Predicates;
import org.apache.isis.core.commons.ensure.Assert;
+import org.apache.isis.core.commons.ensure.Ensure;
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;
@@ -149,7 +151,6 @@ class ObjectAdapterContext_AdapterManager {
// 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));
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 77545ab..593ad6c 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
@@ -72,8 +72,9 @@ class ObjectAdapterContext_ObjectAdapterProvider implements ObjectAdapterProvide
if(persistentOrValueOid != null) {
return persistentOrValueOid;
}
- // Creates a new transient root for the supplied domain object
- final RootOid rootOid = persistenceSession.createTransientOrViewModelOid(pojo);
+ final RootOid rootOid = servicesInjector.isRegisteredServiceInstance(pojo)
+ ? persistenceSession.createPersistentOrViewModelOid(pojo)
+ : persistenceSession.createTransientOrViewModelOid(pojo);
return rootOid;
}
@@ -88,8 +89,11 @@ class ObjectAdapterContext_ObjectAdapterProvider implements ObjectAdapterProvide
return existingOrValueAdapter;
}
- // Creates a new transient root {@link ObjectAdapter adapter} for the supplied domain
- final RootOid rootOid = persistenceSession.createTransientOrViewModelOid(pojo);
+ final RootOid rootOid = servicesInjector.isRegisteredServiceInstance(pojo)
+ ? persistenceSession.createPersistentOrViewModelOid(pojo)
+ : persistenceSession.createTransientOrViewModelOid(pojo);
+
+// final RootOid rootOid = persistenceSession.createTransientOrViewModelOid(pojo);
final ObjectAdapter newAdapter = objectAdapterContext.getFactories().createRootAdapter(pojo, rootOid);
return objectAdapterContext.mapAndInjectServices(newAdapter);