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 2019/02/11 14:08:12 UTC

[isis] branch 2033-IoC updated: ISIS-2033: adds new ContextManager to handle ViewModels

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

ahuber pushed a commit to branch 2033-IoC
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/2033-IoC by this push:
     new ba46bce  ISIS-2033: adds new ContextManager to handle ViewModels
ba46bce is described below

commit ba46bce12f2a8835bd7d83863211f80edb9af26c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Feb 11 15:08:02 2019 +0100

    ISIS-2033: adds new ContextManager to handle ViewModels
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-2033
---
 .../org/apache/isis/commons/internal/uri/_URI.java |   1 +
 .../context/managers/AuthorityDescriptor.java      |  38 ++++--
 .../system/context/managers/Converters.java        |   2 +-
 .../context/managers/UniversalContextManager.java  |   2 +-
 .../context/managers/cdi/CDIContextManager.java    |  20 ++-
 .../viewmodel/ViewModelContextManager.java         | 147 +++++++++++++++++++++
 .../ObjectAdapterContext_OidProviders.java         |   1 +
 7 files changed, 193 insertions(+), 18 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/uri/_URI.java b/core/commons/src/main/java/org/apache/isis/commons/internal/uri/_URI.java
index a52297c..b8ad5ff 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/uri/_URI.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/uri/_URI.java
@@ -90,6 +90,7 @@ public final class _URI {
 	}
 	
 	public static enum ContainerType {
+		isis,
 		jdo,
 		cdi,
 		spring,
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/AuthorityDescriptor.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/AuthorityDescriptor.java
index 54e358d..850706a 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/AuthorityDescriptor.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/AuthorityDescriptor.java
@@ -10,14 +10,15 @@ import org.apache.isis.commons.internal.uri._URI.ContextType;
 import org.apache.isis.commons.internal.uri._URI.UoidDto.UoidDtoBuilder;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
-import lombok.Value;
-import lombok.val;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
 
 /**
  * @since 2.0.0-M3
  */
-@Value(staticConstructor="of")
+@RequiredArgsConstructor(staticName="of") @ToString @EqualsAndHashCode
 public final class AuthorityDescriptor {
 	
 	@Getter private final ContainerType containerType;
@@ -34,16 +35,27 @@ public final class AuthorityDescriptor {
 	}
 
 	public boolean matches(URI uri) {
-		
-		val prefix = String.format("uoid://%s@%s%s/", 
-				containerType.name(),
-				contextType.name(),
-				isEmpty(contextId) 
-					? "" : 
-						":" + contextId
-				);
-		
-		return uri.toString().startsWith(prefix);
+		if(uri==null) {
+			return false;
+		}
+		return uri.toString().startsWith(matchingPrefix());
+	}
+	
+	// -- HELPER
+	
+	private String matchingPrefix;
+	
+	private String matchingPrefix() {
+		if(matchingPrefix==null) {
+			matchingPrefix = String.format("uoid://%s@%s%s/", 
+					contextType.name(),
+					containerType.name(),
+					isEmpty(contextId) 
+						? "" : 
+							":" + contextId
+					);	
+		}
+		return matchingPrefix;
 	}
 	
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/Converters.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/Converters.java
index b5a2fdd..476fcb2 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/Converters.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/Converters.java
@@ -32,7 +32,7 @@ public final class Converters {
 	
 	public static interface FromUriConverter {
 		String encodeToString(@Nullable URI objectUri);
-		String encodeToBase64(URI objectUri);
+		String encodeToBase64(@Nullable URI objectUri);
 		RootOid toRootOid(@Nullable URI objectUri);
 	}
 	
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/UniversalContextManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/UniversalContextManager.java
index e76359c..4276907 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/UniversalContextManager.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/UniversalContextManager.java
@@ -50,7 +50,7 @@ public class UniversalContextManager implements ContextManager {
 		.map(handler->handler.resolve(specId, identifier))
 		.orElseThrow(()->{
 			val msg = String.format(
-					"Could not find a ContextHandler that recognizes identifier URI %s.", identifier);
+					"Could not find a ContextHandler that recognizes object URI '%s'.", identifier);
 			return _Exceptions.unrecoverable(msg);
 		}); 
 		
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/cdi/CDIContextManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/cdi/CDIContextManager.java
index 8ca111d..1f3de27 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/cdi/CDIContextManager.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/cdi/CDIContextManager.java
@@ -63,11 +63,25 @@ public class CDIContextManager implements ContextHandler {
 		//TODO [2033] future extension ... to refine, convert id to array of Annotations
 		val qualifiers = _Constants.emptyAnnotations;
 		
-		val bean = serviceRegistry.getManagedBean(spec.getCorrespondingClass(), qualifiers);
+		val beanOptional = serviceRegistry.getManagedBean(spec.getCorrespondingClass(), qualifiers);
 		
-		val managedObject = SimpleManagedObject.of(spec, bean);
+		probe.println("resolve spec='%s' -> '%s'", 
+        		spec.getSpecId().asString(),
+        		beanOptional);
+		
+		if(beanOptional.isPresent()) {
+		
+			val beanPojo = beanOptional.get();
+			val managedObject = SimpleManagedObject.of(spec, beanPojo);
+			
+			return _CDI.InstanceFactory.singleton(managedObject);
+			
+		}
+		
+		// empty result
+		
+		return _CDI.InstanceFactory.empty();
 		
-		return _CDI.InstanceFactory.singleton(managedObject);
 	}
 
 	@Override
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/viewmodel/ViewModelContextManager.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/viewmodel/ViewModelContextManager.java
new file mode 100644
index 0000000..098c416
--- /dev/null
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/managers/viewmodel/ViewModelContextManager.java
@@ -0,0 +1,147 @@
+package org.apache.isis.core.runtime.system.context.managers.viewmodel;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Modifier;
+import java.net.URI;
+import java.util.Optional;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.inject.Instance;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.internal.cdi._CDI;
+import org.apache.isis.commons.internal.debug._Probe;
+import org.apache.isis.commons.internal.uri._URI.ContainerType;
+import org.apache.isis.commons.internal.uri._URI.ContextType;
+import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ManagedObject.SimpleManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtime.system.context.managers.AuthorityDescriptor;
+import org.apache.isis.core.runtime.system.context.managers.ContextHandler;
+
+import lombok.val;
+
+/**
+ * @since 2.0.0-M3
+ */
+@Singleton
+public class ViewModelContextManager implements ContextHandler {
+
+	private final static _Probe probe = _Probe.unlimited().label("ViewModelContextManager");
+
+	@Inject SpecificationLoader specLoader;
+	@Inject ServiceInjector serviceInjector;
+
+	@PostConstruct
+	public void init() {
+		//
+	}
+
+	@Override
+	public URI uriOf(ManagedObject managedObject) {
+
+		val pojo = managedObject.getPojo();
+		val spec = managedObject.getSpecification();
+
+		val viewModelFacet = spec.getFacet(ViewModelFacet.class);
+		val serialized = viewModelFacet.memento(pojo);
+
+		probe.println("uriOf spec='%s', serialized='%s'", 
+				spec.getSpecId().asString(),
+				serialized);
+
+		return DEFAULT_AUTHORITY.toUoidDtoBuilder(spec.getSpecId())
+				.query(serialized)
+				.build()
+				.toURI();
+	}
+
+	@Override
+	public Instance<ManagedObject> resolve(ObjectSpecId specId, URI objectUri) {
+
+		val serialized = objectUri.getQuery();
+		val spec = specLoader.lookupBySpecId(specId);
+
+		probe.println("resolve spec='%s', serialized='%s'", 
+				spec.getSpecId().asString(),
+				serialized);
+
+		val viewModelPojo = deserializeViewModel(spec, serialized);
+
+		val managedObject = SimpleManagedObject.of(spec, viewModelPojo);
+
+		return _CDI.InstanceFactory.singleton(managedObject);
+	}
+
+	@Override
+	public boolean recognizes(ObjectSpecification spec) {
+		return spec.isViewModel();
+	}
+
+	@Override
+	public boolean recognizes(URI uri) {
+		return DEFAULT_AUTHORITY.matches(uri);
+	}
+
+	@Override
+	public Optional<AuthorityDescriptor> authorityFor(ObjectSpecification spec) {
+		if(!recognizes(spec)) {
+			return Optional.empty();
+		}
+		return Optional.of(DEFAULT_AUTHORITY);
+	}
+
+	// -- HELPER
+
+	private final static AuthorityDescriptor DEFAULT_AUTHORITY =
+			AuthorityDescriptor.of(ContainerType.isis, ContextType.beans, null);
+
+	private Object deserializeViewModel(final ObjectSpecification spec, final String serialized) {
+		final ViewModelFacet facet = spec.getFacet(ViewModelFacet.class);
+		if(facet == null) {
+			throw new IllegalArgumentException("spec does not have ViewModelFacet; spec is " 
+					+ spec.getFullIdentifier());
+		}
+
+		final Object viewModelPojo;
+		if(facet.getRecreationMechanism().isInitializes()) {
+			viewModelPojo = instantiateAndInjectServices(spec);
+			facet.initialize(viewModelPojo, serialized);
+		} else {
+			viewModelPojo = facet.instantiate(spec.getCorrespondingClass(), serialized);
+		}
+		return viewModelPojo;
+	}
+	
+	private Object instantiateAndInjectServices(final ObjectSpecification objectSpec) {
+
+        final Class<?> correspondingClass = objectSpec.getCorrespondingClass();
+        if (correspondingClass.isArray()) {
+            return Array.newInstance(correspondingClass.getComponentType(), 0);
+        }
+
+        final Class<?> cls = correspondingClass;
+        if (Modifier.isAbstract(cls.getModifiers())) {
+            throw new IsisException("Cannot create an instance of an abstract class: " + cls);
+        }
+
+        final Object newInstance;
+        try {
+            newInstance = cls.newInstance();
+        } catch (final IllegalAccessException | InstantiationException e) {
+            throw new IsisException("Failed to create instance of type " + objectSpec.getFullIdentifier(), e);
+        }
+
+        serviceInjector.injectServicesInto(newInstance);
+        return newInstance;
+
+    }
+	
+}
+
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_OidProviders.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_OidProviders.java
index 96f59fe..f12672c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_OidProviders.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_OidProviders.java
@@ -158,6 +158,7 @@ class ObjectAdapterContext_OidProviders {
 
     }
     
+    //TODO [2033] should no longer be required
     static class OidForViewModels implements OidProvider {
 
         @Override