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 2021/01/23 10:10:54 UTC

[isis] branch master updated: ISIS-2492: first naive implementation in support of action inheritance

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0ff62cd  ISIS-2492: first naive implementation in support of action inheritance
0ff62cd is described below

commit 0ff62cd24ea5b82bdd4714559f9f2e1dd491a7d3
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Jan 23 11:10:37 2021 +0100

    ISIS-2492: first naive implementation in support of action inheritance
    
    not considering the corner case, that the action's type (prototyping or
    not) can be overriden when inherited
---
 .../core/metamodel/spec/ObjectSpecification.java   |  4 ++-
 .../spec/feature/ObjectActionContainer.java        | 29 +++++++++++++++++++---
 .../specimpl/dflt/ObjectSpecificationDefault.java  | 26 ++++++++++++++++++-
 .../testspec/ObjectSpecificationStub.java          |  6 +++++
 .../DomainModelTest_usingGoodDomain.java           | 10 ++++----
 5 files changed, 65 insertions(+), 10 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
index 97dfded..6ec068e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
@@ -540,7 +540,9 @@ public interface ObjectSpecification extends Specification, ObjectActionContaine
                 || Externalizable.class.isAssignableFrom(getCorrespondingClass());
     }
 
-    
+    default boolean isTypeHierarchyRoot() {
+        return getCorrespondingClass().getSuperclass()==null;
+    }
     
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
index 20fb116..d9fec83 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
@@ -31,7 +31,31 @@ import org.apache.isis.core.metamodel.spec.ActionType;
 
 public interface ObjectActionContainer {
 
-    // -- ACTION LOOKUP
+    // -- ACTION LOOKUP (INHERITENCE CONSIDERED)
+    
+    /**
+     * Same as {@link #getObjectAction(String, ActionType)}, but also considering any inherited object members. 
+     * @param id
+     * @param type
+     * 
+     * @implSpec If not found on the current 'type' search for the 'nearest' match in super-types, 
+     * and if nothing found there, search the interfaces. Special care needs to be taken, as the
+     * {@link ActionType} might be redeclared when inheriting from a super-type or interface.  
+     */
+    Optional<ObjectAction> findObjectAction(String id, @Nullable ActionType type);
+    
+    default ObjectAction findObjectActionElseFail(String id, @Nullable ActionType type) {
+        return findObjectAction(id, type)
+                .orElseThrow(()->_Exceptions.noSuchElement("id=%s type=%s", 
+                        id, 
+                        type==null ? "any" : type.name()));
+    }
+
+     default ObjectAction findObjectActionElseFail(String id) {
+        return findObjectActionElseFail(id, null);
+    }
+    
+    // -- ACTION LOOKUP, DECLARED ACTIONS (NO INHERITENCE CONSIDERED)
     
     /**
      * Get the action object represented by the specified identity string.
@@ -60,8 +84,7 @@ public interface ObjectActionContainer {
     }
     
     default ObjectAction getObjectActionElseFail(String id) {
-        return getObjectAction(id)
-                .orElseThrow(()->_Exceptions.noSuchElement("id=%s", id));  
+        return getObjectActionElseFail(id, null);
     }
 
     // -- ACTION STREAM
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 107a28d..5aed2d6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -71,7 +71,9 @@ import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
 @Log4j2 
-public class ObjectSpecificationDefault extends ObjectSpecificationAbstract implements FacetHolder {
+public class ObjectSpecificationDefault 
+extends ObjectSpecificationAbstract 
+implements FacetHolder {
 
     private static String determineShortName(final Class<?> introspectedClass) {
         final String name = introspectedClass.getName();
@@ -266,6 +268,28 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
         return nameIfIsManagedBean;
     }
     
+    // -- findObjectAction
+    
+    @Override
+    public Optional<ObjectAction> findObjectAction(String id, ActionType type) {
+
+        if(isTypeHierarchyRoot()) {
+            return Optional.empty();
+        }
+        
+        val declaredAction = getObjectAction(id, type); // no inheritance considered
+                
+        if(declaredAction.isPresent()) {
+            return declaredAction; 
+        }
+        
+        return superclass().findObjectAction(id, type);
+        
+        //XXX future extensions should also search the interfaces, 
+        // but avoid doing redundant work when walking the type-hierarchy;
+        // (this elegant recursive solution will then need some tweaks to be efficient)
+    }
+    
     // -- getObjectAction
 
     @Override
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
index f4d8cce..809578f 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
@@ -352,4 +352,10 @@ public class ObjectSpecificationStub extends FacetHolderImpl implements ObjectSp
         return Optional.empty();
     }
 
+    @Override
+    public Optional<ObjectAction> findObjectAction(String id, ActionType type) {
+        // poorly implemented, inheritance not supported
+        return getObjectAction(id, type);
+    }
+
 }
diff --git a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
index 1a487e8..5c5d8a8 100644
--- a/regressiontests/stable/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
+++ b/regressiontests/stable/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
@@ -180,25 +180,25 @@ class DomainModelTest_usingGoodDomain {
     @Test
     void metamodelContributingMembers_shouldBeInheritable() {
         
-        val holderSpec1 = specificationLoader.loadSpecification(ProperMemberInheritance.class, 
+        val holderSpec = specificationLoader.loadSpecification(ProperMemberInheritance.class, 
                         IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
         
         //TODO we need to synthesize any inherited members on the subclass instead 
-        val holderSpec = holderSpec1.superclass();
+        val holderSpec_super = holderSpec.superclass();
         
-        val super_action = holderSpec.getObjectActionElseFail("sampleAction");
+        val super_action = holderSpec.findObjectActionElseFail("sampleAction");
         assertNotNull(super_action);
         assertEquals("sampleAction", super_action.getId());
         assertEquals("foo", super_action.getName());
         assertEquals("bar", super_action.getDescription());
         
-        val super_property = holderSpec.getAssociationElseFail("sampleProperty");
+        val super_property = holderSpec_super.getAssociationElseFail("sampleProperty");
         assertNotNull(super_property);
         assertEquals("sampleProperty", super_property.getId());
         assertEquals("foo", super_property.getName());
         assertEquals("bar", super_property.getDescription());
         
-        val super_collection = holderSpec.getAssociationElseFail("sampleCollection");
+        val super_collection = holderSpec_super.getAssociationElseFail("sampleCollection");
         assertNotNull(super_collection);
         assertEquals("sampleCollection", super_collection.getId());
         assertEquals("foo", super_collection.getName());