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 2020/05/07 16:56:04 UTC

[isis] 02/02: ISIS-2340: move more ActionModel logic to common

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

commit 366f6f4c95c5259c136a1ce3fe47281fdaf66ecc
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu May 7 18:55:24 2020 +0200

    ISIS-2340: move more ActionModel logic to common
---
 .../isis/core/metamodel/spec/ManagedObjects.java   | 14 ++++
 .../common/model/action/form/FormUiModel.java      | 81 ++++++++++++++++++-
 .../viewer/wicket/model/models/ActionModel.java    | 90 +++-------------------
 .../ui/components/actioninfo/ActionInfoPanel.java  |  2 +-
 .../actionprompt/ActionPromptHeaderPanel.java      |  2 +-
 .../actions/ActionFormExecutorStrategy.java        |  4 +-
 .../widgets/linkandlabel/ActionLink.java           | 15 +---
 .../linkandlabel/LinkAndLabelFactoryAbstract.java  |  6 +-
 8 files changed, 116 insertions(+), 98 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
index 18cc336..cc9aee7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObjects.java
@@ -106,6 +106,20 @@ public final class ManagedObjects {
         return adapter;
         
     }
+    
+    // -- TITLE UTILITIES
+    
+    public static String abbreviatedTitleOf(ManagedObject adapter, int maxLength, String suffix) {
+        return abbreviated(titleOf(adapter), maxLength, suffix);
+    }
+    
+    private static String titleOf(ManagedObject adapter) {
+        return adapter!=null?adapter.titleString(null):"";
+    }
+
+    private static String abbreviated(final String str, final int maxLength, String suffix) {
+        return str.length() < maxLength ? str : str.substring(0, maxLength - 3) + suffix;
+    }
 
 
 }
diff --git a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/form/FormUiModel.java b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/form/FormUiModel.java
index fa03cd2..b05a2ca 100644
--- a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/form/FormUiModel.java
+++ b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/action/form/FormUiModel.java
@@ -20,12 +20,91 @@ package org.apache.isis.viewer.common.model.action.form;
 
 import java.util.stream.Stream;
 
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.collections.Can;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.specloader.specimpl.PendingParameterModelHead;
+import org.apache.isis.viewer.common.model.HasTitle;
+import org.apache.isis.viewer.common.model.feature.ParameterUiModel;
 
-public interface FormUiModel {
+import lombok.val;
+
+public interface FormUiModel extends HasTitle {
 
     ObjectAction getMetaModel();
     
+    /** action's owner
+     * @apiNote for mixins this is not the target to use on mixin actions
+     * instead the logic of resolving the target for action invocation is 
+     * encapsulated within the {@link PendingParameterModelHead}
+     */
+    ManagedObject getOwner();
+    
     Stream<FormPendingParamUiModel> streamPendingParamUiModels();
 
+    // -- USABILITY
+    
+    default Consent getUsabilityConsent() {
+        return getMetaModel().isUsable(
+                getOwner(),
+                InteractionInitiatedBy.USER,
+                Where.OBJECT_FORMS);
+    }
+
+    // -- VISABILITY
+    
+    default Consent getVisibilityConsent() {
+        return getMetaModel().isVisible(
+                getOwner(),
+                InteractionInitiatedBy.USER,
+                Where.OBJECT_FORMS);
+    }
+
+    // -- VALIDITY
+    
+    default Consent getValidityConsent() {
+        
+        val proposedArguments = streamPendingParamUiModels()
+                .map(FormPendingParamUiModel::getParamModel)
+                .map(ParameterUiModel::getValue)
+                .collect(Can.toCan());
+                
+        return getMetaModel().isProposedArgumentSetValid(
+                getOwner(), 
+                proposedArguments, 
+                InteractionInitiatedBy.USER);
+        
+    }
+    
+    // -- HAS TITLE
+    
+    default String getTitle() {
+        val target = getOwner();
+        val objectAction = getMetaModel();
+
+        val buf = new StringBuilder();
+        
+        streamPendingParamUiModels()
+        .filter(argAndConsent->argAndConsent.getVisibilityConsent().isAllowed())
+        .map(FormPendingParamUiModel::getParamModel)
+        .map(ParameterUiModel::getValue)
+        .forEach(paramValue->{
+            if(buf.length() > 0) {
+                buf.append(",");
+            }
+            buf.append(ManagedObjects.abbreviatedTitleOf(paramValue, 8, "..."));
+        });
+        return target.titleString(null) + "." + objectAction.getName() + (buf.length()>0?"(" + buf.toString() + ")":"");
+    }
+    
+    // -- SHORTCUTS
+    
+    default boolean hasParameters() {
+        return getMetaModel().getParameterCount() > 0;
+    }
+    
 }
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index 9041cfb..f752d64 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -45,7 +45,6 @@ import org.apache.isis.applib.value.LocalResourcePath;
 import org.apache.isis.applib.value.NamedWithMimeType;
 import org.apache.isis.core.commons.collections.Can;
 import org.apache.isis.core.commons.internal.base._NullSafe;
-import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -96,7 +95,7 @@ implements FormUiModel, FormExecutorContext {
 
     @Override
     public PageParameters getPageParametersWithoutUiHints() {
-        val adapter = getTargetAdapter();
+        val adapter = getOwner();
         val objectAction = getMetaModel();
         return PageParameterUtil.createPageParameters(adapter, objectAction, argCache().snapshot());
     }
@@ -107,21 +106,14 @@ implements FormUiModel, FormExecutorContext {
     }
 
     // --
-
+    
+    private transient ObjectAction objectAction;
     @Override
-    public String getTitle() {
-        val target = getTargetAdapter();
-        val objectAction = getMetaModel();
-
-        val buf = new StringBuilder();
-        for(val argumentAdapter: argCache().snapshot()) {
-            if(buf.length() > 0) {
-                buf.append(",");
-            }
-            buf.append(abbreviated(titleOf(argumentAdapter), 8));
+    public ObjectAction getMetaModel() {
+        if(objectAction==null) {
+            objectAction = actionMemento.getAction(getSpecificationLoader()); 
         }
-
-        return target.titleString(null) + "." + objectAction.getName() + (buf.length()>0?"(" + buf.toString() + ")":"");
+        return objectAction;
     }
 
     @Override
@@ -136,14 +128,6 @@ implements FormUiModel, FormExecutorContext {
 
     // -- HELPERS
 
-    private static String titleOf(ManagedObject argumentAdapter) {
-        return argumentAdapter!=null?argumentAdapter.titleString(null):"";
-    }
-
-    private static String abbreviated(final String str, final int maxLength) {
-        return str.length() < maxLength ? str : str.substring(0, maxLength - 3) + "...";
-    }
-
     private final EntityModel entityModel;
     private final ActionMemento actionMemento;
 
@@ -177,20 +161,8 @@ implements FormUiModel, FormExecutorContext {
         this.argCache = actionModel.argCache().copy(); 
     }
 
-    private transient ObjectAction objectAction;
     @Override
-    public ObjectAction getMetaModel() {
-        if(objectAction==null) {
-            objectAction = actionMemento.getAction(getSpecificationLoader()); 
-        }
-        return objectAction;
-    }
-
-    public boolean hasParameters() {
-        return getMetaModel().getParameterCount() > 0;
-    }
-
-    public ManagedObject getTargetAdapter() {
+    public ManagedObject getOwner() {
         return entityModel.load();
     }
 
@@ -215,7 +187,7 @@ implements FormUiModel, FormExecutorContext {
 
     private ManagedObject executeAction() {
 
-        val targetAdapter = getTargetAdapter();
+        val targetAdapter = getOwner();
         final Can<ManagedObject> arguments = argCache().snapshot();
         final ObjectAction action = getMetaModel();
 
@@ -242,51 +214,13 @@ implements FormUiModel, FormExecutorContext {
 
     }
 
-    public String getReasonDisabledIfAny() {
-
-        val targetAdapter = getTargetAdapter();
-        final ObjectAction objectAction = getMetaModel();
-
-        final Consent usability =
-                objectAction.isUsable(
-                        targetAdapter,
-                        InteractionInitiatedBy.USER,
-                        Where.OBJECT_FORMS);
-        final String disabledReasonIfAny = usability.getReason();
-        return disabledReasonIfAny;
-    }
-
-
-    public boolean isVisible() {
-
-        val targetAdapter = getTargetAdapter();
-        val objectAction = getMetaModel();
-
-        final Consent visibility =
-                objectAction.isVisible(
-                        targetAdapter,
-                        InteractionInitiatedBy.USER,
-                        Where.OBJECT_FORMS);
-        return visibility.isAllowed();
-    }
-
-
-    public String getReasonInvalidIfAny() {
-        val targetAdapter = getTargetAdapter();
-        final Can<ManagedObject> proposedArguments = argCache().snapshot();
-        final ObjectAction objectAction = getMetaModel();
-        final Consent validity = objectAction
-                .isProposedArgumentSetValid(targetAdapter, proposedArguments, InteractionInitiatedBy.USER);
-        return validity.isAllowed() ? null : validity.getReason();
-    }
-
     @Override
     public void setObject(final ManagedObject object) {
         throw new UnsupportedOperationException("target adapter for ActionModel cannot be changed");
     }
 
     public PendingParameterModel getArgumentsAsParamModel() {
-        return getMetaModel().newPendingParameterModelHead(getTargetAdapter())
+        return getMetaModel().newPendingParameterModelHead(getOwner())
                 .model(argCache().snapshot());
     }
 
@@ -297,7 +231,7 @@ implements FormUiModel, FormExecutorContext {
     public void clearArguments() {
 
         val defaultsFixedPoint = getMetaModel()
-                .newPendingParameterModelHead(getTargetAdapter())
+                .newPendingParameterModelHead(getOwner())
                 .defaults()
                 .getParamValues();
 
@@ -461,7 +395,7 @@ implements FormUiModel, FormExecutorContext {
     @Override
     public Stream<FormPendingParamUiModel> streamPendingParamUiModels() {
 
-        val targetAdapter = this.getTargetAdapter();
+        val targetAdapter = this.getOwner();
         val realTargetAdapter = this.getMetaModel().realTargetAdapter(targetAdapter);
         val pendingArgs = getArgumentsAsParamModel();
 
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actioninfo/ActionInfoPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actioninfo/ActionInfoPanel.java
index 3d34f26..c5e928e 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actioninfo/ActionInfoPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actioninfo/ActionInfoPanel.java
@@ -39,7 +39,7 @@ public class ActionInfoPanel extends PanelAbstract<ActionModel> {
     public ActionInfoPanel(final String id, final ActionModel actionModel) {
         super(id, actionModel);
 
-        val targetAdapter = getModel().getTargetAdapter();
+        val targetAdapter = getModel().getOwner();
         val objectAction = getModel().getMetaModel();
 
         // TODO: render instead as links (providing isn't a service; provide a
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptHeaderPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptHeaderPanel.java
index 26061b4..eead4cc 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptHeaderPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptHeaderPanel.java
@@ -39,7 +39,7 @@ public class ActionPromptHeaderPanel extends PanelAbstract<ActionModel> {
     public ActionPromptHeaderPanel(String id, final ActionModel model) {
         super(id, model);
 
-        _Blackhole.consume(model.getTargetAdapter()); // side-effect: loads the model
+        _Blackhole.consume(model.getOwner()); // side-effect: loads the model
 
         getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.ENTITY_ICON_AND_TITLE, model.getParentUiModel());
 
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionFormExecutorStrategy.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionFormExecutorStrategy.java
index 9f805b2..b976200 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionFormExecutorStrategy.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionFormExecutorStrategy.java
@@ -42,12 +42,12 @@ public class ActionFormExecutorStrategy implements FormExecutorStrategy<ActionMo
 
     @Override
     public ManagedObject obtainTargetAdapter() {
-        return model.getTargetAdapter();
+        return model.getOwner();
     }
 
     @Override
     public String getReasonInvalidIfAny() {
-        return model.getReasonInvalidIfAny();
+        return model.getValidityConsent().getReason();
     }
 
     @Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java
index 48bbcd2..646328f 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLink.java
@@ -128,7 +128,7 @@ public abstract class ActionLink extends AjaxLink<ManagedObject> implements IAja
 
     public String getReasonDisabledIfAny() {
         // no point evaluating if not visible
-        return isVisible() ? getActionModel().getReasonDisabledIfAny() : null;
+        return isVisible() ? getActionModel().getUsabilityConsent().getReason() : null;
     }
 
     @Override
@@ -155,22 +155,13 @@ public abstract class ActionLink extends AjaxLink<ManagedObject> implements IAja
 
     @Override
     public boolean isVisible() {
-        return determineIfVisible();
-    }
-
-    private boolean determineIfVisible() {
-        return getActionModel().isVisible();
+        return getActionModel().getVisibilityConsent().isAllowed();
     }
 
     @Override
     @Programmatic
     public boolean isEnabled() {
-        return determineIfEnabled();
-    }
-
-    private boolean determineIfEnabled() {
-        val reasonDisabledIfAny = getReasonDisabledIfAny();
-        return reasonDisabledIfAny == null;
+        return getActionModel().getUsabilityConsent().isAllowed();
     }
 
     @Override
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/LinkAndLabelFactoryAbstract.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/LinkAndLabelFactoryAbstract.java
index e8e0e9f..999510d 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/LinkAndLabelFactoryAbstract.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/LinkAndLabelFactoryAbstract.java
@@ -160,7 +160,7 @@ implements Serializable {
 
         if(inlinePromptContext == null || promptStyle.isDialog()) {
             final ActionPromptProvider promptProvider = ActionPromptProvider.getFrom(actionLink.getPage());
-            val spec = actionModel.getTargetAdapter().getSpecification();
+            val spec = actionModel.getOwner().getSpecification();
 
             final ActionPrompt prompt = promptProvider.getActionPrompt(promptStyle, spec.getBeanSort());
 
@@ -203,7 +203,7 @@ implements Serializable {
                         if(mixinSpec.isViewModel()) {
 
                             val commonContext = getCommonContext();
-                            final ManagedObject targetAdapterForMixin = action.realTargetAdapter(actionModel.getTargetAdapter());
+                            final ManagedObject targetAdapterForMixin = action.realTargetAdapter(actionModel.getOwner());
                             final EntityModel entityModelForMixin = 
                                     EntityModel.ofAdapter(commonContext, targetAdapterForMixin);
 
@@ -263,7 +263,7 @@ implements Serializable {
                     // (One way this can occur is if an event subscriber has a defect and throws an exception; in which case
                     // the EventBus' exception handler will automatically veto.  This results in a growl message rather than
                     // an error page, but is probably 'good enough').
-                    val targetAdapter = actionModel.getTargetAdapter();
+                    val targetAdapter = actionModel.getOwner();
 
                     final EntityPage entityPage = new EntityPage(getCommonContext(), targetAdapter);