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/11/15 13:44:48 UTC

[isis] branch master updated: ISIS-2893: moves the command vs member matching logic to CommandUtil

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 d483f6e  ISIS-2893: moves the command vs member matching logic to CommandUtil
d483f6e is described below

commit d483f6e5a37f78569e2a98048ea650f835481ada
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Nov 15 14:44:39 2021 +0100

    ISIS-2893: moves the command vs member matching logic to CommandUtil
    
    - thats where the identifier to String conversion happens at first place
---
 .../java/org/apache/isis/applib/Identifier.java    |  6 ---
 .../isis/applib/services/command/Command.java      |  2 -
 .../org/apache/isis/applib/IdentifierTests.java    | 28 +++++-----
 .../actions/action/invocation/CommandUtil.java     | 61 ++++++++++++++++------
 .../publish/command/CommandPublishingFacet.java    |  3 +-
 .../testdomain/interact/ActionInteractionTest.java | 38 ++++++++++----
 .../interaction/DomainObjectTesterFactory.java     | 20 +++++++
 7 files changed, 110 insertions(+), 48 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/Identifier.java b/api/applib/src/main/java/org/apache/isis/applib/Identifier.java
index 5a90ff8..a269ef2 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/Identifier.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/Identifier.java
@@ -25,7 +25,6 @@ import java.util.stream.Collectors;
 
 import org.apache.isis.applib.id.HasLogicalType;
 import org.apache.isis.applib.id.LogicalType;
-import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.i18n.HasTranslationContext;
 import org.apache.isis.applib.services.i18n.TranslationContext;
 import org.apache.isis.applib.services.i18n.TranslationService;
@@ -195,11 +194,6 @@ implements
                 + memberNameAndParameterClassNamesIdentityString;
     }
 
-    public boolean matchesCommand(final @NonNull Command command) {
-        return (getLogicalTypeName() + "#" + memberLogicalName)
-                .equals(command.getLogicalMemberIdentifier());
-    }
-
     // -- NATURAL NAMES
 
     public String getClassNaturalName() {
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/command/Command.java b/api/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
index 591f10b..db6becc 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/command/Command.java
@@ -363,6 +363,4 @@ public class Command implements HasInteractionId, HasUsername, HasCommandDto {
         return UPDATER;
     }
 
-
-
 }
diff --git a/api/applib/src/test/java/org/apache/isis/applib/IdentifierTests.java b/api/applib/src/test/java/org/apache/isis/applib/IdentifierTests.java
index 8194be8..c8a966f 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/IdentifierTests.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/IdentifierTests.java
@@ -20,8 +20,7 @@ package org.apache.isis.applib;
 
 import java.math.BigDecimal;
 
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
@@ -31,42 +30,41 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.commons.collections.Can;
 
-public class IdentifierTests {
+import lombok.val;
 
-    private Identifier identifier;
+class IdentifierTests {
 
-    @Before
-    public void setUp() {
-    }
+    private Identifier identifier;
 
     @Test
-    public void canInstantiateClassIdentifier() {
+    void canInstantiateClassIdentifier() {
         identifier = Identifier.classIdentifier(LogicalType.fqcn(SomeDomainClass.class));
         assertThat(identifier, is(not(nullValue())));
     }
 
     @Test
-    public void classIdentifierClassNameIsSet() {
-        final Class<?> domainClass = SomeDomainClass.class;
+    void classIdentifierClassNameIsSet() {
+        val domainClass = SomeDomainClass.class;
         final String domainClassFullyQualifiedName = domainClass.getCanonicalName();
         identifier = Identifier.classIdentifier(LogicalType.fqcn(domainClass));
         assertThat(identifier.getClassName(), is(domainClassFullyQualifiedName));
     }
 
     @Test
-    public void memberParameterNames() {
-        final Class<?> domainClass = SomeDomainClass.class;
+    void memberParameterNames() {
+        val domainClass = SomeDomainClass.class;
         identifier = Identifier.actionIdentifier(LogicalType.fqcn(domainClass), "placeOrder", int.class, String.class);
         assertThat(identifier.getMemberParameterClassNames(), is(Can.of("int", "java.lang.String")));
     }
 
     @Test
-    public void paramsIdentityString() {
-        final Class<?> domainClass = SomeDomainClass.class;
+    void paramsIdentityString() {
+        val domainClass = SomeDomainClass.class;
         identifier = Identifier.actionIdentifier(LogicalType.fqcn(domainClass), "placeOrder", int.class, String.class, BigDecimal.class);
         assertThat(
-                identifier.getFullIdentityString(), 
+                identifier.getFullIdentityString(),
                 is("org.apache.isis.applib.SomeDomainClass#placeOrder(int,java.lang.String,java.math.BigDecimal)"));
     }
 
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/CommandUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/CommandUtil.java
index a5b13e6..4c199ed 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/CommandUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/CommandUtil.java
@@ -20,7 +20,10 @@ package org.apache.isis.core.metamodel.facets.actions.action.invocation;
 
 import java.util.List;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
@@ -35,28 +38,28 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 
 import lombok.val;
+import lombok.experimental.UtilityClass;
 
 /**
  * Factoring out the commonality between <tt>ActionInvocationFacetViaMethod</tt>
  * and <tt>BackgroundServiceDefault</tt>.
  */
+@UtilityClass
 public class CommandUtil {
 
-    private CommandUtil(){}
-
-    public static String targetClassNameFor(final ManagedObject targetAdapter) {
+    public String targetClassNameFor(final ManagedObject targetAdapter) {
         return targetClassNameFor(targetAdapter.getSpecification());
     }
 
-    public static String targetClassNameFor(final ObjectSpecification spec) {
+    public String targetClassNameFor(final ObjectSpecification spec) {
         return StringExtensions.asNaturalName2(spec.getSingularName());
     }
 
-    public static String memberIdentifierFor(final ObjectMember objectMember) {
+    public String memberIdentifierFor(final ObjectMember objectMember) {
         return objectMember.getFeatureIdentifier().getFullIdentityString();
     }
 
-    public static String logicalMemberIdentifierFor(final ObjectMember objectMember) {
+    public String logicalMemberIdentifierFor(final ObjectMember objectMember) {
         if(objectMember instanceof ObjectAction) {
             return logicalMemberIdentifierFor((ObjectAction)objectMember);
         }
@@ -66,22 +69,50 @@ public class CommandUtil {
         throw new IllegalArgumentException(objectMember.getClass() + " is not supported");
     }
 
-    public static String logicalMemberIdentifierFor(final ObjectAction objectAction) {
+    public String logicalMemberIdentifierFor(final ObjectAction objectAction) {
         return logicalMemberIdentifierFor(objectAction.getDeclaringType(), objectAction);
     }
 
-    public static String logicalMemberIdentifierFor(final OneToOneAssociation otoa) {
+    public String logicalMemberIdentifierFor(final OneToOneAssociation otoa) {
         return logicalMemberIdentifierFor(otoa.getDeclaringType(), otoa);
     }
 
-    private static String logicalMemberIdentifierFor(
+    /**
+     * Whether given command corresponds to given objectMember.
+     * <p>
+     * Is related to {@link #logicalMemberIdentifierFor(ObjectMember)}.
+     */
+    public boolean matches(
+            final @Nullable Command command,
+            final @Nullable ObjectMember objectMember) {
+        if(command==null
+                || objectMember==null) {
+            return false;
+        }
+        if(!objectMember.isMixedIn()) {
+            val featureIdentifier = objectMember.getFeatureIdentifier();
+            return (featureIdentifier.getLogicalTypeName() + "#" + featureIdentifier.getMemberLogicalName())
+                    .equals(command.getLogicalMemberIdentifier());
+        }
+
+        return logicalMemberIdentifierFor(objectMember)
+                .equals(command.getLogicalMemberIdentifier());
+
+        //FIXME[ISIS-2893] eg. when the Command's memberId is "Employment#bookLeave",
+        // and the objectMember.getFeatureIdentifier() is "Employment_bookLeave#act"
+
+    }
+
+    // -- HELPER
+
+    private String logicalMemberIdentifierFor(
             final ObjectSpecification onType, final ObjectMember objectMember) {
         final String logicalTypeName = onType.getLogicalTypeName();
         final String localId = objectMember.getFeatureIdentifier().getMemberLogicalName();
         return logicalTypeName + "#" + localId;
     }
 
-    public static String argDescriptionFor(final ManagedObject valueAdapter) {
+    public String argDescriptionFor(final ManagedObject valueAdapter) {
         final StringBuilder buf = new StringBuilder();
         if(valueAdapter != null) {
             appendArg(buf, "new value", valueAdapter);
@@ -91,7 +122,7 @@ public class CommandUtil {
         return buf.toString();
     }
 
-    public static String argDescriptionFor(
+    public String argDescriptionFor(
             final ObjectAction owningAction,
             final List<ManagedObject> arguments) {
 
@@ -107,12 +138,12 @@ public class CommandUtil {
         return argsBuf.toString();
     }
 
-    public static Bookmark bookmarkFor(final ManagedObject adapter) {
+    public Bookmark bookmarkFor(final ManagedObject adapter) {
         return ManagedObjects.bookmark(adapter)
                 .orElse(null);
     }
 
-    static void appendParamArg(
+    void appendParamArg(
             final StringBuilder buf,
             final ObjectActionParameter param,
             final ManagedObject objectAdapter) {
@@ -122,7 +153,7 @@ public class CommandUtil {
         appendArg(buf, name, objectAdapter);
     }
 
-    private static void appendArg(
+    private void appendArg(
             final StringBuilder buf,
             final String name,
             final ManagedObject objectAdapter) {
@@ -131,7 +162,7 @@ public class CommandUtil {
         buf.append(name).append(": ").append(titleOf).append("\n");
     }
 
-    public static ManagedObject[] adaptersFor(
+    public ManagedObject[] adaptersFor(
             final Object[] args,
             final ObjectManager objectManager) {
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/publish/command/CommandPublishingFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/publish/command/CommandPublishingFacet.java
index 7305431..150870a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/publish/command/CommandPublishingFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/members/publish/command/CommandPublishingFacet.java
@@ -24,6 +24,7 @@ import org.apache.isis.applib.services.commanddto.processor.CommandDtoProcessor;
 import org.apache.isis.applib.services.publishing.spi.CommandSubscriber;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
 import org.apache.isis.core.metamodel.services.publishing.CommandPublisher;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
 
@@ -58,7 +59,7 @@ public interface CommandPublishingFacet extends Facet {
             final @NonNull ObjectMember objectMember,
             final @NonNull FacetHolder facetHolder) {
 
-        if(objectMember.getFeatureIdentifier().matchesCommand(command)
+        if(CommandUtil.matches(command, objectMember)
                 && isPublishingEnabled(facetHolder)) {
             command.updater().setPublishingPhase(CommandPublishingPhase.READY);
         }
diff --git a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java
index ccbe728..a3a7874 100644
--- a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java
+++ b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/ActionInteractionTest.java
@@ -25,10 +25,16 @@ import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.TestPropertySource;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.config.presets.IsisPresets;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
 import org.apache.isis.testdomain.conf.Configuration_headless;
 import org.apache.isis.testdomain.model.interaction.Configuration_usingInteractionDomain;
 import org.apache.isis.testdomain.model.interaction.DemoEnum;
@@ -39,11 +45,6 @@ import org.apache.isis.testdomain.model.interaction.InteractionDemo_multiEnum;
 import org.apache.isis.testdomain.model.interaction.InteractionDemo_multiInt;
 import org.apache.isis.testdomain.util.interaction.InteractionTestAbstract;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
 import lombok.val;
 
 @SpringBootTest(
@@ -101,7 +102,7 @@ class ActionInteractionTest extends InteractionTestAbstract {
     }
 
     @Test
-    void mixinwhenDisabled_shouldProvideActionMetadata() {
+    void mixinWhenDisabled_shouldProvideActionMetadata() {
 
         val actionInteraction = startActionInteractionOn(InteractionDemo.class, "biArgDisabled", Where.OBJECT_FORMS)
                 .checkVisibility()
@@ -123,6 +124,17 @@ class ActionInteractionTest extends InteractionTestAbstract {
         tester.assertVisibilityIsNotVetoed();
         tester.assertUsabilityIsNotVetoed();
         tester.assertInvocationResult(99, UnaryOperator.identity());
+
+
+        val capturedCommands = tester.getCapturedCommands();
+        assertEquals(1, capturedCommands.size());
+        val command = capturedCommands.getElseFail(1);
+        assertEquals("regressiontests.InteractionDemo#noArgEnabled",
+                command.getLogicalMemberIdentifier());
+
+        // test feature-identifier to command matching ...
+        val act = tester.getActionMetaModelElseFail();
+        assertTrue(CommandUtil.matches(command, act));
     }
 
     @Test
@@ -151,7 +163,7 @@ class ActionInteractionTest extends InteractionTestAbstract {
     }
 
     @Test
-    void withParams_shouldProduceCorrectResult() throws Throwable {
+    void mixinWithParams_shouldProduceCorrectResult() throws Throwable {
 
         val tester =
                 testerFactory.actionTester(InteractionDemo.class, "biArgEnabled", Where.OBJECT_FORMS);
@@ -159,6 +171,16 @@ class ActionInteractionTest extends InteractionTestAbstract {
         tester.assertVisibilityIsNotVetoed();
         tester.assertUsabilityIsNotVetoed();
         tester.assertInvocationResult(46, arg0->12, arg1->34);
+
+        val capturedCommands = tester.getCapturedCommands();
+        assertEquals(1, capturedCommands.size());
+        val command = capturedCommands.getElseFail(1);
+        assertEquals("regressiontests.InteractionDemo#biArgEnabled",
+                command.getLogicalMemberIdentifier());
+
+        // test feature-identifier to command matching ...
+        val act = tester.getActionMetaModelElseFail();
+        assertTrue(CommandUtil.matches(command, act));
     }
 
     @Test
@@ -431,8 +453,6 @@ class ActionInteractionTest extends InteractionTestAbstract {
   //TODO also deal with non-scalar parameter values
   //TODO test whether actions do emit their domain events
   //TODO test whether actions can be vetoed via domain event interception
-  //TODO test command reification
   //TODO test whether interactions spawn their own transactions, commands, interactions(applib)
 
-
 }
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java
index 31e2f36..2323958 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java
@@ -18,6 +18,7 @@
  */
 package org.apache.isis.testdomain.util.interaction;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -41,6 +42,7 @@ import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.exceptions.unrecoverable.DomainModelException;
 import org.apache.isis.applib.id.LogicalType;
+import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.factory.FactoryService;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
 import org.apache.isis.applib.services.inject.ServiceInjector;
@@ -227,6 +229,7 @@ public class DomainObjectTesterFactory {
         }
 
         private final @NonNull ThrowingSupplier<ParameterNegotiationModel> parameterNegotiationStarter;
+        private List<Command> capturedCommands = new ArrayList<>();
 
         private ActionTester(
                 final @NonNull Class<T> domainObjectType,
@@ -315,10 +318,13 @@ public class DomainObjectTesterFactory {
                 val actionResultAsPojo = resultOrVeto.leftIfAny().getPojo();
                 assertEquals(expectedResult, actionResultAsPojo);
 
+                captureCommand();
             });
 
         }
 
+
+
         public Object invokeWithPojos(final List<Object> pojoArgList) {
 
             assertExists(true);
@@ -341,6 +347,8 @@ public class DomainObjectTesterFactory {
                 val resultOrVeto = actionInteraction.invokeWith(pendingArgs);
                 assertTrue(resultOrVeto.isLeft()); // assert action did not throw
 
+                captureCommand();
+
                 return resultOrVeto.leftIfAny().getPojo();
             });
         }
@@ -402,10 +410,17 @@ public class DomainObjectTesterFactory {
                                     ));
                 });
 
+                captureCommand();
+
             });
 
         }
 
+        public Can<Command> getCapturedCommands() {
+            return Can.ofCollection(capturedCommands);
+        }
+
+
         /**
          * Use on non scalar results.
          */
@@ -474,6 +489,11 @@ public class DomainObjectTesterFactory {
         }
 
 
+        private void captureCommand() {
+            capturedCommands.add(
+                    interactionService.currentInteraction().get().getCommand());
+        }
+
     }
 
     // -- PROPERTY TESTER