Repository: isis
Updated Branches:
  refs/heads/master 5522f4bd5 -> ffd9f08c9


ISIS-1425: making the wrapper factory intelligent enough to handle 
(dereference) programmatically instantiated mixins


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/ffd9f08c
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/ffd9f08c
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/ffd9f08c

Branch: refs/heads/master
Commit: ffd9f08c9487d1c785d8ebd10fb99c0da3aa47fe
Parents: 5522f4b
Author: Dan Haywood <d...@haywood-associates.co.uk>
Authored: Fri Jun 3 18:48:29 2016 +0100
Committer: Dan Haywood <d...@haywood-associates.co.uk>
Committed: Fri Jun 3 18:48:29 2016 +0100

----------------------------------------------------------------------
 .../facets/object/mixin/MixinFacet.java         |  6 +++
 .../facets/object/mixin/MixinFacetAbstract.java | 32 +++++++++++++
 .../handlers/DomainObjectInvocationHandler.java | 47 +++++++++++++++++---
 3 files changed, 78 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/ffd9f08c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
index b3d4e40..8aed8ad 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacet.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.facets.object.mixin;
 
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.Nature;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
@@ -35,6 +36,11 @@ public interface MixinFacet extends Facet {
     boolean isMixinFor(Class<?> candidateDomainType);
 
     /**
+     * Returns the (adapter of the) domain object that a mixin adapter 
contains.
+     */
+    ObjectAdapter mixedIn(ObjectAdapter mixinAdapter);
+
+    /**
      * Returns the mixin around the provided domain object
      */
     Object instantiate(Object domainPojo);

http://git-wip-us.apache.org/repos/asf/isis/blob/ffd9f08c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
index f5cb292..cabb093 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/mixin/MixinFacetAbstract.java
@@ -20,8 +20,12 @@
 package org.apache.isis.core.metamodel.facets.object.mixin;
 
 import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 
+import org.apache.isis.applib.services.title.TitleService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
@@ -85,4 +89,32 @@ public abstract class MixinFacetAbstract extends 
MarkerFacetAbstract implements
         }
     }
 
+    @Override
+    public ObjectAdapter mixedIn(ObjectAdapter mixinAdapter) {
+
+        final Object mixin = mixinAdapter.getObject();
+
+        final Field[] declaredFields = mixinType.getDeclaredFields();
+        for (final Field declaredField : declaredFields) {
+            if(declaredField.getType().isAssignableFrom(constructorType)) {
+                declaredField.setAccessible(true);
+                try {
+                    Object o = declaredField.get(mixin);
+                    return getAdapterManager().adapterFor(o);
+                } catch (IllegalAccessException e) {
+                    throw new RuntimeException("Unable to access " + 
declaredField + " for " + getTitleService().titleOf(mixin));
+                }
+            }
+        }
+        throw new RuntimeException("Could not find the \"mixed-in\" domain 
object within " + getTitleService().titleOf(mixin) + " (tried to guess by 
looking at all private fields and matching one against the constructor 
parameter)");
+    }
+
+    private AdapterManager getAdapterManager() {
+        return servicesInjector.getPersistenceSessionServiceInternal();
+    }
+
+    private TitleService getTitleService() {
+        return servicesInjector.lookupService(TitleService.class);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/ffd9f08c/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
----------------------------------------------------------------------
diff --git 
a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
 
b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
index 16f1819..fafe407 100644
--- 
a/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
+++ 
b/core/wrapper/src/main/java/org/apache/isis/core/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -32,6 +32,8 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
+import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet;
+import org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionMixedIn;
 import org.datanucleus.enhancement.Persistable;
 
 import org.apache.isis.applib.annotation.Where;
@@ -253,13 +255,43 @@ public class DomainObjectInvocationHandler<T> extends 
DelegatingInvocationHandle
                 throw new UnsupportedOperationException(String.format("Cannot 
invoke supporting method '%s'; use only the 'invoke' method", memberName));
             }
 
-            final ObjectAction noa = (ObjectAction) objectMember;
-            return handleActionMethod(targetAdapter, args, noa, 
contributeeMember);
+            final ObjectAction objectAction = (ObjectAction) objectMember;
+
+            final ObjectAction actualObjectAction;
+            final ObjectAdapter actualTargetAdapter;
+
+            final MixinFacet mixinFacet = 
targetAdapter.getSpecification().getFacet(MixinFacet.class);
+            if(mixinFacet != null) {
+
+                // rather than invoke on a (transient) mixin, instead figure 
out the corresponding ObjectActoinMixedIn
+                actualTargetAdapter = mixinFacet.mixedIn(targetAdapter);
+                actualObjectAction = determineMixinAction(objectAction, 
actualTargetAdapter);
+
+            } else {
+                actualTargetAdapter = targetAdapter;
+                actualObjectAction = objectAction;
+            }
+
+            return handleActionMethod(actualTargetAdapter, args, 
actualObjectAction, contributeeMember);
         }
 
         throw new UnsupportedOperationException(String.format("Unknown member 
type '%s'", objectMember));
     }
 
+    private ObjectAction determineMixinAction(final ObjectAction objectAction, 
final ObjectAdapter actualTargetAdapter) {
+        final ObjectSpecification specification = 
actualTargetAdapter.getSpecification();
+        final List<ObjectAction> objectActions = 
specification.getObjectActions(Contributed.INCLUDED);
+        for (final ObjectAction action : objectActions) {
+            if(action instanceof ObjectActionMixedIn) {
+                ObjectActionMixedIn mixedInAction = (ObjectActionMixedIn) 
action;
+                if(mixedInAction.hasMixinAction(objectAction)) {
+                    return mixedInAction;
+                }
+            }
+        }
+        throw new RuntimeException("Unable to find the mixed-in action 
corresponding to " + objectAction.getIdentifier().toFullIdentityString());
+    }
+
     public InteractionInitiatedBy getInteractionInitiatedBy() {
         return getExecutionMode().shouldEnforceRules()? 
InteractionInitiatedBy.USER: InteractionInitiatedBy.FRAMEWORK;
     }
@@ -618,11 +650,12 @@ public class DomainObjectInvocationHandler<T> extends 
DelegatingInvocationHandle
 
         if (getExecutionMode().shouldExecute()) {
             final InteractionInitiatedBy interactionInitiatedBy = 
getInteractionInitiatedBy();
-            final ObjectAdapter mixedInAdapter = null; // mixin action will 
automatically fill in.
-            final ObjectAdapter returnedAdapter =
-                    objectAction.execute(
-                            targetAdapter, mixedInAdapter, argAdapters,
-                            interactionInitiatedBy);
+
+            final ObjectAdapter mixedInAdapter = null; // if a mixin action, 
then it will automatically fill in.
+
+            final ObjectAdapter returnedAdapter = objectAction.execute(
+                    targetAdapter, mixedInAdapter, argAdapters,
+                    interactionInitiatedBy);
 
             return ObjectAdapter.Util.unwrap(returnedAdapter);
         }

Reply via email to