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/causeway.git


The following commit(s) were added to refs/heads/master by this push:
     new 22aad05080 CAUSEWAY-3686: improved veto reduction algorithm
22aad05080 is described below

commit 22aad05080a5f7bd9cd2175526b076a1f92d0543
Author: Andi Huber <[email protected]>
AuthorDate: Thu Feb 8 09:15:53 2024 +0100

    CAUSEWAY-3686: improved veto reduction algorithm
    
    - merge veto text based on priority
---
 .../commons/internal/primitives/_Ints.java         | 14 +++++++++
 .../causeway/core/metamodel/consent/Consent.java   | 35 ++++++++++++++++++----
 .../core/metamodel/consent/InteractionResult.java  |  2 +-
 .../scalars/ScalarPanelAdditionalButton.java       | 30 +++++++++++--------
 4 files changed, 63 insertions(+), 18 deletions(-)

diff --git 
a/commons/src/main/java/org/apache/causeway/commons/internal/primitives/_Ints.java
 
b/commons/src/main/java/org/apache/causeway/commons/internal/primitives/_Ints.java
index cc706a49ce..6b3361cbf5 100644
--- 
a/commons/src/main/java/org/apache/causeway/commons/internal/primitives/_Ints.java
+++ 
b/commons/src/main/java/org/apache/causeway/commons/internal/primitives/_Ints.java
@@ -395,4 +395,18 @@ public class _Ints {
         return sb.toString();
     }
 
+    /**
+     * Compares two {@code int} values numerically.
+     * @param  x the first {@code int} to compare
+     * @param  y the second {@code int} to compare
+     * @return the value {@code 0} if {@code x == y};
+     *         {@code -1} if {@code x < y}; and
+     *         {@code 1} if {@code x > y}
+     * @apiNote copy of {@link Integer#compress(int, int)}
+     *      because their java-doc states that return values -1, +1 are not 
guaranteed.
+     */
+    public static int compare(final int x, final int y) {
+        return (x < y) ? -1 : ((x == y) ? 0 : 1);
+    }
+
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
index a92685258d..cefaee11fa 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
@@ -19,10 +19,14 @@
 package org.apache.causeway.core.metamodel.consent;
 
 import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._Strings;
+import org.apache.causeway.commons.internal.primitives._Ints;
 import 
org.apache.causeway.core.metamodel.facets.object.immutable.ImmutableFacet;
 
 import lombok.NonNull;
@@ -38,21 +42,42 @@ public interface Consent {
          * Introduced to help decide whether or not to display a 'ban' icon
          * in the UI, with a tooltip showing the disabled reason.
          */
-        private final boolean showInUi;
+        public enum UiHint {
+            /**
+             * When prototyping, icon rendering can be suppressed via config 
option.
+             */
+            NO_ICON_UNLESS_PROTOTYPING,
+            SHOW_BAN_ICON;
+            public boolean isNoIconUnlessPrototying() { return 
this==NO_ICON_UNLESS_PROTOTYPING; }
+            public boolean isShowBanIcon() { return this==SHOW_BAN_ICON; }
+            /** reduce to max ordinal */
+            static UiHint reduceToMaxOrdinal(final UiHint a, final UiHint b) {
+                return b.ordinal()>a.ordinal() ? b : a;
+            }
+        }
+        private final UiHint uiHint;
         private final @NonNull String string;
         public static VetoReason explicit(final String reason) {
             _Assert.assertTrue(_Strings.isNotEmpty(reason));
-            return new VetoReason(true, reason);
+            return new VetoReason(UiHint.SHOW_BAN_ICON, reason);
         }
         private static VetoReason inferred(final String reason) {
             _Assert.assertTrue(_Strings.isNotEmpty(reason));
-            return new VetoReason(false, reason);
+            return new VetoReason(UiHint.NO_ICON_UNLESS_PROTOTYPING, reason);
         }
         public Optional<VetoReason> toOptional() {
             return Optional.of(this);
         }
-        public VetoReason concatenate(final VetoReason other) {
-            return new VetoReason(this.showInUi || other.showInUi, this.string 
+ "; " + other.string);
+        public VetoReason reduce(final VetoReason other) {
+            final List<String> mergedText = new ArrayList<>(2);
+            switch(_Ints.compare(this.uiHint.ordinal(), 
other.uiHint.ordinal())) {
+            case -1: mergedText.add(other.string); break;
+            case 0:  mergedText.add(this.string); 
mergedText.add(other.string); break;
+            case 1:  mergedText.add(this.string); break;
+            }
+            return new VetoReason(
+                    UiHint.reduceToMaxOrdinal(this.uiHint, other.uiHint),
+                    mergedText.stream().collect(Collectors.joining("; ")));
         }
         // -- PREDEFINED REASONS
         public static VetoReason editingObjectDisabledReasonNotGiven() {
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionResult.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionResult.java
index 926f139762..caa453b377 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionResult.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/InteractionResult.java
@@ -131,7 +131,7 @@ public class InteractionResult {
      * If {@link #isNotVetoing()}, then returns <tt>Optional.empty()</tt>.
      */
     public Optional<Consent.VetoReason> getReason() {
-        return reasonBuf.stream().reduce(Consent.VetoReason::concatenate);
+        return reasonBuf.stream().reduce(Consent.VetoReason::reduce);
     }
 
     @Override
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAdditionalButton.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAdditionalButton.java
index fab9c356fb..8d751ccf2d 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAdditionalButton.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/scalars/ScalarPanelAdditionalButton.java
@@ -37,12 +37,14 @@ enum ScalarPanelAdditionalButton {
                 final ScalarModel scalarModel,
                 final RenderScenario renderScenario,
                 final FieldFragment fieldFragment) {
-            return renderScenario!=RenderScenario.CAN_EDIT_INLINE_VIA_ACTION
+            var precondition = 
renderScenario!=RenderScenario.CAN_EDIT_INLINE_VIA_ACTION;
+            return precondition
                     && scalarModel.disabledReason()
-                    .map(InteractionVeto::getVetoConsent)
-                    .flatMap(Consent::getReason)
-                    .map(VetoReason::showInUi)
-                    .orElse(false);
+                        .map(InteractionVeto::getVetoConsent)
+                        .flatMap(Consent::getReason)
+                        .map(VetoReason::uiHint)
+                        .map(VetoReason.UiHint::isShowBanIcon)
+                        .orElse(false);
         }
     },
     DISABLED_REASON_PROTOTYPING {
@@ -51,14 +53,18 @@ enum ScalarPanelAdditionalButton {
                 final ScalarModel scalarModel,
                 final RenderScenario renderScenario,
                 final FieldFragment fieldFragment) {
-            return scalarModel.getSystemEnvironment().isPrototyping()
-                    && 
scalarModel.getConfiguration().getViewer().getWicket().isDisableReasonExplanationInPrototypingModeEnabled()
-                    && 
renderScenario!=RenderScenario.CAN_EDIT_INLINE_VIA_ACTION
+            var precondition = 
renderScenario!=RenderScenario.CAN_EDIT_INLINE_VIA_ACTION
+                    && scalarModel.getSystemEnvironment().isPrototyping()
+                    && 
scalarModel.getConfiguration().getViewer().getWicket().isDisableReasonExplanationInPrototypingModeEnabled();
+            return precondition
                     && scalarModel.disabledReason()
-                    .map(InteractionVeto::getVetoConsent)
-                    .flatMap(Consent::getReason)
-                    .map(vetoReason->!vetoReason.showInUi())
-                    .orElse(false);
+                        .map(InteractionVeto::getVetoConsent)
+                        .flatMap(Consent::getReason)
+                        .map(VetoReason::uiHint)
+                        // opposite of logic in DISABLED_REASON above,
+                        // because DISABLED_REASON_PROTOTYPING should only 
ever activate when DISABLED_REASON is not active
+                        .map(VetoReason.UiHint::isNoIconUnlessPrototying)
+                        .orElse(false);
         }
     },
     CLEAR_FIELD {

Reply via email to