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

ahuber pushed a commit to branch 3824-action.ellipsis
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 394bb05872fcbd8a858cb752ba950ca8e0457b49
Author: Andi Huber <[email protected]>
AuthorDate: Sat Oct 26 11:18:18 2024 +0200

    CAUSEWAY-3824: refactoring: consolidates menu action decoration
---
 .../model/action/decorator/UiActionDecorator.java  |  46 -------
 .../commons/model/decorators/ConfirmDecorator.java |  39 +++---
 .../model/decorators/DisablingDecorator.java       |  11 +-
 .../model/decorators/FormLabelDecorator.java       |  26 +---
 .../model/decorators/MenuActionDecorator.java      |  72 +++++++++++
 .../model/decorators/PrototypingDecorator.java     |  12 +-
 .../commons/model/decorators/TooltipDecorator.java |   8 +-
 .../viewer/wicket/model/links/LinkAndLabel.java    |  12 ++
 .../actionmenu/serviceactions/CssMenuItem.java     |   2 +-
 .../actionmenu/serviceactions/MenuActionPanel.java |   5 +-
 .../serviceactions/ServiceActionUtil.java          |  33 ++----
 .../components/actions/ActionParametersForm.java   |  30 +++--
 .../viewer/wicket/ui/util/WktDecorators.java       | 132 ++++++++-------------
 .../causeway/viewer/wicket/ui/util/WktLinks.java   |  20 ++--
 .../viewer/wicket/ui/util/WktTooltips.java         |   6 +-
 15 files changed, 210 insertions(+), 244 deletions(-)

diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/decorator/UiActionDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/decorator/UiActionDecorator.java
deleted file mode 100644
index 42cc87d8e6..0000000000
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/action/decorator/UiActionDecorator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.causeway.viewer.commons.model.action.decorator;
-
-import org.apache.causeway.viewer.commons.model.decorators.ConfirmDecorator;
-import org.apache.causeway.viewer.commons.model.decorators.DisablingDecorator;
-import org.apache.causeway.viewer.commons.model.decorators.IconDecorator;
-import 
org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator;
-import org.apache.causeway.viewer.commons.model.decorators.TooltipDecorator;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-/**
- * Decorates a click-able UI component of various type {@code <T>} based 
UiModels.
- *
- * @since 2.0.0
- * @param <T> - link component type, native to the viewer
- */
-@Getter
-@RequiredArgsConstructor
-public class UiActionDecorator<T> {
-
-    private final TooltipDecorator<T> tooltipDecorator;
-    private final DisablingDecorator<T> disableDecorator;
-    private final ConfirmDecorator<T> confirmDecorator;
-    private final PrototypingDecorator<T, T> prototypingDecorator;
-    private final IconDecorator<T, T> iconDecorator;
-
-}
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java
index 7ba2a5a792..69d31f1445 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/ConfirmDecorator.java
@@ -22,15 +22,14 @@ import java.io.Serializable;
 import java.util.Optional;
 
 import org.apache.causeway.applib.services.i18n.TranslationContext;
-import org.apache.causeway.applib.services.i18n.TranslationService;
 import org.apache.causeway.core.config.messages.MessageRegistry;
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
 import org.apache.causeway.viewer.commons.model.layout.UiPlacementDirection;
 
-import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
-import lombok.val;
+import lombok.experimental.Accessors;
 
 @FunctionalInterface
 public interface ConfirmDecorator<T> {
@@ -39,8 +38,8 @@ public interface ConfirmDecorator<T> {
 
     // -- DECORATION MODEL
 
-    @Getter
-    @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE)
+    @Getter @Accessors(fluent=true) //RECORD (java 16)
+    @AllArgsConstructor
     public static class ConfirmDecorationModel implements Serializable {
 
         private static final long serialVersionUID = 1L;
@@ -51,28 +50,18 @@ public interface ConfirmDecorator<T> {
         final @NonNull String cancelLabel;
         final @NonNull UiPlacementDirection placement;
 
-        public static ConfirmDecorationModel areYouSure(
-                final TranslationService translationService,
-                final UiPlacementDirection placement) {
+        public static ConfirmDecorationModel areYouSure(final 
UiPlacementDirection placement) {
 
-            val context = 
TranslationContext.forClassName(MessageRegistry.class);
+            var translationService = 
MetaModelContext.translationServiceOrFallback();
+            var context = 
TranslationContext.forClassName(MessageRegistry.class);
+            
+            var areYouSure = translationService.translate(context, 
MessageRegistry.MSG_ARE_YOU_SURE);
+            var confirm = translationService.translate(context, 
MessageRegistry.MSG_CONFIRM);
+            var cancel = translationService.translate(context, 
MessageRegistry.MSG_CANCEL);
 
-            val areYouSure = translate(translationService, context, 
MessageRegistry.MSG_ARE_YOU_SURE);
-            val confirm = translate(translationService, context, 
MessageRegistry.MSG_CONFIRM);
-            val cancel = translate(translationService, context, 
MessageRegistry.MSG_CANCEL);
+            var message = Optional.<String>empty(); // not used yet
 
-            val message = Optional.<String>empty(); // not used yet
-
-            return of(areYouSure, message, confirm, cancel, placement);
-        }
-
-        // -- HELPER
-
-        private static String translate(final TranslationService 
translationService, final TranslationContext context, final String msg) {
-            if(translationService!=null) {
-                return translationService.translate(context, msg);
-            }
-            return msg;
+            return new ConfirmDecorationModel(areYouSure, message, confirm, 
cancel, placement);
         }
 
     }
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java
index be9cb16a93..bb3d6cb06d 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/DisablingDecorator.java
@@ -24,10 +24,10 @@ import java.util.Optional;
 import org.apache.causeway.core.metamodel.interactions.managed.InteractionVeto;
 import 
org.apache.causeway.core.metamodel.interactions.managed.MemberInteraction;
 
-import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
+import lombok.experimental.Accessors;
 
 @FunctionalInterface
 public interface DisablingDecorator<T> {
@@ -36,8 +36,8 @@ public interface DisablingDecorator<T> {
 
     // -- DECORATION MODEL
 
-    @Getter
-    @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE)
+    @Getter @Accessors(fluent=true) //RECORD (java 16)
+    @AllArgsConstructor
     public static class DisablingDecorationModel implements Serializable {
 
         private static final long serialVersionUID = 1L;
@@ -46,14 +46,13 @@ public interface DisablingDecorator<T> {
 
         public static Optional<DisablingDecorationModel> of(@NonNull final 
Optional<InteractionVeto> usabilityVeto) {
             return usabilityVeto
-                    .map(veto->of(veto.getReasonAsString().orElse(null)));
+                    .map(veto->new 
DisablingDecorationModel(veto.getReasonAsString().orElse(null)));
         }
 
         public static Optional<DisablingDecorationModel> of(@NonNull final 
MemberInteraction<?, ?> memberInteraction) {
             return of(memberInteraction.getInteractionVeto());
         }
 
-
     }
 
 }
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java
index 6da048546c..fc4a9f4386 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/FormLabelDecorator.java
@@ -20,11 +20,9 @@ package org.apache.causeway.viewer.commons.model.decorators;
 
 import java.io.Serializable;
 
-import org.springframework.lang.Nullable;
-
-import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.experimental.Accessors;
 
 @FunctionalInterface
 public interface FormLabelDecorator<T> {
@@ -33,29 +31,17 @@ public interface FormLabelDecorator<T> {
 
     // -- DECORATION MODEL
 
-    @Getter
-    @RequiredArgsConstructor(staticName = "of", access = AccessLevel.PRIVATE)
+    @Getter @Accessors(fluent=true) //RECORD (java 16)
+    @AllArgsConstructor
     public static class FormLabelDecorationModel implements Serializable {
 
         private static final long serialVersionUID = 1L;
 
         public static FormLabelDecorationModel mandatory(final boolean 
mandatory) {
-            /* used to be suffixed with ':' till 2.0.0-RC1;
-             * however, the question arises what to do in the label RIGHT 
position case;
-             * and so we concluded, that perhaps its better to remove the 
suffix colon
-             * all together */
-            return of(mandatory, "");
+            return new FormLabelDecorationModel(mandatory);
         }
 
-        /* not used
-        public static FormLabelDecorationModel mandatorySuffixed2(
-                final boolean mandatory,
-                final @Nullable String suffix) {
-            return of(mandatory, suffix);
-        } */
-
-        final boolean mandatoryMarker;
-        final @Nullable String suffix;
+        final boolean isMandatoryIndicatorShown;
 
     }
 
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/MenuActionDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/MenuActionDecorator.java
new file mode 100644
index 0000000000..9974822564
--- /dev/null
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/MenuActionDecorator.java
@@ -0,0 +1,72 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.causeway.viewer.commons.model.decorators;
+
+import java.util.Optional;
+
+import org.apache.causeway.applib.Identifier;
+import org.apache.causeway.applib.fa.FontAwesomeLayers;
+import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction;
+import 
org.apache.causeway.viewer.commons.model.decorators.DisablingDecorator.DisablingDecorationModel;
+import 
org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator.PrototypingDecorationModel;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.val;
+import lombok.experimental.Accessors;
+
+/**
+ * Decorates Actions that appear in drop-down menus.
+ * 
+ * @param <T> primary UI component type to decorate
+ * @param <U> secondary UI component type to decorate
+ * @param <V> tertiary UI component type to decorate
+ */
+@FunctionalInterface
+public interface MenuActionDecorator<T, U, V> {
+
+    void decorate(T uiComponent1, U uiComponent2, V uiComponent3, 
MenuActionDecorationModel decorationModel);
+
+    // -- DECORATION MODEL
+
+    @Builder(builderMethodName = "builderInternal")
+    @Getter @Accessors(fluent=true) //RECORD (java 16)
+    @AllArgsConstructor
+    public static class MenuActionDecorationModel {
+        private final boolean isImmediateConfirmationRequired;
+        private final Identifier featureIdentifier;
+        private final Optional<DisablingDecorationModel> disabling;
+        private final Optional<PrototypingDecorationModel> prototyping;
+        private final Optional<FontAwesomeLayers> fontAwesomeLayers;
+        private final Optional<String> describedAs;
+        private final Optional<String> additionalCssClass;
+        
+        public static MenuActionDecorationModelBuilder builder(final 
ManagedAction managedAction) {
+            val action = managedAction.getAction();
+            return builderInternal()
+                    .prototyping(managedAction.getAction().isPrototype() 
+                            ? 
Optional.of(PrototypingDecorationModel.of(managedAction))
+                            : Optional.empty())
+                    
.isImmediateConfirmationRequired(action.isImmediateConfirmationRequired());
+        }
+        
+    }
+
+}
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java
index f83c8fac85..882a147141 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/PrototypingDecorator.java
@@ -25,9 +25,9 @@ import org.apache.causeway.core.metamodel.facetapi.Facet;
 import org.apache.causeway.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.causeway.core.metamodel.interactions.managed.ManagedMember;
 
-import lombok.AccessLevel;
+import lombok.AllArgsConstructor;
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.experimental.Accessors;
 
 /**
  *
@@ -43,8 +43,8 @@ public interface PrototypingDecorator<T, R> {
 
     // -- DECORATION MODEL
 
-    @Getter
-    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
+    @Getter @Accessors(fluent=true) //RECORD (java 16)
+    @AllArgsConstructor
     public static class PrototypingDecorationModel {
 
         private final Class<?> featureType;
@@ -58,7 +58,6 @@ public interface PrototypingDecorator<T, R> {
             String featureFullLabel = String.format("%s: %s",
                     managedAction.getMemberType(),
                     managedAction.getId());
-
             return new PrototypingDecorationModel(featureType, 
featureShortLabel, featureFullLabel,
                     managedAction.getAction()::streamFacets);
         }
@@ -69,7 +68,6 @@ public interface PrototypingDecorator<T, R> {
             String featureFullLabel = String.format("%s: %s",
                     managedMember.getMemberType(),
                     managedMember.getId());
-
             return new PrototypingDecorationModel(featureType, 
featureShortLabel, featureFullLabel,
                     managedMember.getElementType()::streamFacets);
         }
@@ -78,8 +76,6 @@ public interface PrototypingDecorator<T, R> {
             return facetStreamProvider.get();
         }
 
-
-
     }
 
 }
diff --git 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java
 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java
index e8a4e7581d..6bd884dbd9 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/causeway/viewer/commons/model/decorators/TooltipDecorator.java
@@ -27,7 +27,7 @@ import org.apache.causeway.commons.internal.base._Strings;
 import org.apache.causeway.viewer.commons.model.layout.UiPlacementDirection;
 
 import lombok.NonNull;
-import lombok.Value;
+import lombok.experimental.Accessors;
 
 @FunctionalInterface
 public interface TooltipDecorator<T> {
@@ -36,7 +36,7 @@ public interface TooltipDecorator<T> {
 
     // -- DECORATION MODEL
 
-    @Value(staticConstructor = "of")
+    @lombok.Value @Accessors(fluent=true) //RECORD (java 16)
     public static class TooltipDecorationModel implements Serializable {
 
         private static final long serialVersionUID = 1L;
@@ -48,14 +48,14 @@ public interface TooltipDecorator<T> {
         public static TooltipDecorationModel ofBody(
                 final @NonNull UiPlacementDirection uiPlacementDirection,
                 final @Nullable String body) {
-            return of(uiPlacementDirection, Optional.empty(), 
_Strings.nonEmpty(body).orElse(""));
+            return new TooltipDecorationModel(uiPlacementDirection, 
Optional.empty(), _Strings.nonEmpty(body).orElse(""));
         }
 
         public static TooltipDecorationModel ofTitleAndBody(
                 final @NonNull UiPlacementDirection uiPlacementDirection,
                 final @Nullable String title,
                 final @Nullable String body) {
-            return of(uiPlacementDirection, _Strings.nonEmpty(title), 
_Strings.nonEmpty(body).orElse(""));
+            return new TooltipDecorationModel(uiPlacementDirection, 
_Strings.nonEmpty(title), _Strings.nonEmpty(body).orElse(""));
         }
 
         public static TooltipDecorationModel empty() {
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java
index 96197317c0..b11cf7d16b 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/links/LinkAndLabel.java
@@ -30,6 +30,7 @@ import 
org.apache.causeway.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.spec.feature.ObjectAction;
 import org.apache.causeway.viewer.commons.model.action.HasManagedAction;
+import 
org.apache.causeway.viewer.commons.model.decorators.MenuActionDecorator.MenuActionDecorationModel;
 import org.apache.causeway.viewer.commons.model.mixin.HasUiComponent;
 import org.apache.causeway.viewer.wicket.model.models.ActionModel;
 
@@ -93,6 +94,17 @@ implements
         return actionModel.getUsabilityConsent().isAllowed();
     }
 
+    public MenuActionDecorationModel getMenuActionDecorationModel() {
+        return MenuActionDecorationModel
+                .builder(getManagedAction())
+                .featureIdentifier(getFeatureIdentifier())
+                .describedAs(getDescription())
+                .disabling(getDisableUiModel())
+                .additionalCssClass(getAdditionalCssClass())
+                .fontAwesomeLayers(lookupFontAwesomeLayers(true))
+                .build();
+    }
+    
     // -- UTILITY
 
     public static Predicate<LinkAndLabel> isPositionedAt(final Position panel) 
{
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
index ff593f232b..535576b3fb 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
@@ -151,7 +151,7 @@ implements Menuable {
             // ... and show label, along with disabled reason
 
             linkAndLabel.getDisableUiModel().ifPresent(disableUiModel->{
-                WktTooltips.addTooltip(label, disableUiModel.getReason());
+                WktTooltips.addTooltip(label, disableUiModel.reason());
             });
 
             label.add(new AttributeModifier("class", Model.of("disabled")));
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java
index 34502c0b06..1323bed5e9 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/MenuActionPanel.java
@@ -74,13 +74,12 @@ public abstract class MenuActionPanel extends PanelBase {
 
     private void addFolderItem(final CssMenuItem menuItem, final 
ListItem<CssMenuItem> listItem) {
         final MarkupContainer parent = this;
-        ServiceActionUtil.addFolderItem(super.getMetaModelContext(), menuItem, 
listItem, parent);
+        ServiceActionUtil.addFolderItem(menuItem, listItem, parent);
     }
 
     private void addLeafItem(final CssMenuItem menuItem, final 
ListItem<CssMenuItem> listItem) {
         final MarkupContainer parent = this;
-        ServiceActionUtil.addLeafItem(
-                super.getMetaModelContext(), menuItem, listItem, parent);
+        ServiceActionUtil.addLeafItem(menuItem, listItem, parent);
     }
 
     private void addSpacer(final CssMenuItem menuItem, final 
ListItem<CssMenuItem> listItem) {
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
index 213d6132af..3cca611468 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionUtil.java
@@ -41,36 +41,27 @@ import lombok.val;
 import lombok.experimental.UtilityClass;
 
 @UtilityClass
-//@Log4j2
-public final class ServiceActionUtil {
+class ServiceActionUtil {
 
-    static void addLeafItem(
-            final MetaModelContext commonContext,
+    void addLeafItem(
             final CssMenuItem menuItem,
             final ListItem<CssMenuItem> listItem,
             final MarkupContainer parent) {
 
-        val actionUiModel = menuItem.getLinkAndLabel();
-        val menuItemActionLink = actionUiModel.getUiComponent();
-        val menuItemLabel = Wkt.labelAdd(menuItemActionLink, "menuLinkLabel", 
menuItem.getName());
-
-        WktDecorators.getActionLink().decorateMenuItem(
-                listItem,
-                actionUiModel,
-                commonContext.getTranslationService());
+        var linkAndLabel = menuItem.getLinkAndLabel();
+        var menuItemActionLink = linkAndLabel.getUiComponent();
+        var menuItemLabel = Wkt.labelAdd(menuItemActionLink, "menuLinkLabel", 
menuItem.getName());
 
-        val faLayers = actionUiModel.lookupFontAwesomeLayers(true);
-        WktDecorators.getIcon().decorate(menuItemLabel, faLayers);
-        WktDecorators.getMissingIcon().decorate(menuItemActionLink, faLayers);
+        WktDecorators.getActionLink()
+            .decorate(listItem, menuItemActionLink, menuItemLabel, 
linkAndLabel.getMenuActionDecorationModel());
 
-        val leafItem = new Fragment("content", "leafItem", parent);
+        var leafItem = new Fragment("content", "leafItem", parent);
         leafItem.add(menuItemActionLink);
 
         listItem.add(leafItem);
     }
 
-    static void addFolderItem(
-            final MetaModelContext commonContext,
+    void addFolderItem(
             final CssMenuItem subMenuItem,
             final ListItem<CssMenuItem> listItem,
             final MarkupContainer parent) {
@@ -87,9 +78,9 @@ public final class ServiceActionUtil {
             CssMenuItem menuItem = listItem.getModelObject();
 
             if (menuItem.hasSubMenuItems()) {
-                addFolderItem(commonContext, menuItem, item, parent);
+                addFolderItem(menuItem, item, parent);
             } else {
-                addLeafItem(commonContext, menuItem, item, parent);
+                addLeafItem(menuItem, item, parent);
             }
         });
 
@@ -137,7 +128,7 @@ public final class ServiceActionUtil {
         }
     }
 
-    public static void buildMenu(
+    void buildMenu(
             final MetaModelContext commonContext,
             final MenuUiModel menuUiModel,
             final Consumer<CssMenuItem> onNewMenuItem) {
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java
index a85db8ff9a..00bb3a11c0 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/components/actions/ActionParametersForm.java
@@ -44,8 +44,6 @@ import 
org.apache.causeway.viewer.wicket.ui.panels.PromptFormAbstract;
 import org.apache.causeway.viewer.wicket.ui.util.Wkt;
 import org.apache.causeway.viewer.wicket.ui.util.WktDecorators;
 
-import lombok.val;
-
 import 
de.agilecoders.wicket.extensions.markup.html.bootstrap.confirmation.ConfirmationBehavior;
 
 class ActionParametersForm
@@ -66,9 +64,9 @@ extends PromptFormAbstract<ActionModel> {
 
     @Override
     protected void addParameters() {
-        val actionModel = actionModel();
+        var actionModel = actionModel();
 
-        val repeatingView =
+        var repeatingView =
                 Wkt.add(this, new 
RepeatingView(ActionParametersFormPanel.ID_ACTION_PARAMETERS));
 
         paramPanels.clear();
@@ -77,7 +75,7 @@ extends PromptFormAbstract<ActionModel> {
         .map(UiParameterWkt.class::cast)
         .forEach(paramModel->{
 
-            val container = Wkt.containerAdd(repeatingView, 
repeatingView.newChildId());
+            var container = Wkt.containerAdd(repeatingView, 
repeatingView.newChildId());
 
             newParamPanel(container, paramModel, paramPanels::add);
 
@@ -91,10 +89,10 @@ extends PromptFormAbstract<ActionModel> {
             final UiParameterWkt paramModel,
             final Consumer<ScalarPanelAbstract> onNewScalarPanel) {
 
-        val scalarParamModel = ScalarParameterModel.wrap(paramModel);
+        var scalarParamModel = ScalarParameterModel.wrap(paramModel);
 
         // returned ScalarPanelAbstract should already have added any 
associated LinkAndLabel(s)
-        val component = getComponentFactoryRegistry()
+        var component = getComponentFactoryRegistry()
                 .addOrReplaceComponent(container, 
ActionParametersFormPanel.ID_SCALAR_NAME_AND_VALUE,
                         UiComponentType.SCALAR_NAME_AND_VALUE, 
scalarParamModel);
 
@@ -118,11 +116,11 @@ extends PromptFormAbstract<ActionModel> {
      * @param button The button which action should be confirmed
      */
     private void applyAreYouSure(final AjaxButton button) {
-        val actionModel = actionModel();
-        val action = actionModel.getAction();
+        var actionModel = actionModel();
+        var action = actionModel.getAction();
 
         if (action.getSemantics().isAreYouSure()) {
-            val confirmUiModel = 
ConfirmDecorationModel.areYouSure(getTranslationService(), 
UiPlacementDirection.BOTTOM);
+            var confirmUiModel = 
ConfirmDecorationModel.areYouSure(UiPlacementDirection.BOTTOM);
             WktDecorators.getConfirm().decorate(button, confirmUiModel);
         }
     }
@@ -130,10 +128,10 @@ extends PromptFormAbstract<ActionModel> {
     @Override
     public void onUpdate(final AjaxRequestTarget target, final 
ScalarPanelAbstract scalarPanelUpdated) {
 
-        val actionModel = actionModel();
-        val updatedParamModel = (UiParameter)scalarPanelUpdated.getModel();
-        val paramNegotiationModel = 
updatedParamModel.getParameterNegotiationModel();
-        val pendingParamModels = 
actionModel.streamPendingParamUiModels().collect(Can.toCan());
+        var actionModel = actionModel();
+        var updatedParamModel = (UiParameter)scalarPanelUpdated.getModel();
+        var paramNegotiationModel = 
updatedParamModel.getParameterNegotiationModel();
+        var pendingParamModels = 
actionModel.streamPendingParamUiModels().collect(Can.toCan());
 
         final int paramIndexOfUpdated = updatedParamModel.getParameterIndex();
         _Xray.beforeParamFormUpdate(paramIndexOfUpdated, 
paramNegotiationModel);
@@ -148,8 +146,8 @@ extends PromptFormAbstract<ActionModel> {
                     Repaint.required(wasValueChanged);
             _Xray.reassessedDefault(paramIndexForReassessment, 
paramNegotiationModel);
 
-            val paramPanel = paramPanels.get(paramIndexForReassessment);
-            val paramModel = 
pendingParamModels.getElseFail(paramIndexForReassessment);
+            var paramPanel = paramPanels.get(paramIndexForReassessment);
+            var paramModel = 
pendingParamModels.getElseFail(paramIndexForReassessment);
             /* repaint is required, either because of a changed value during 
reassessment above
              * or because visibility or usability have changed */
             paramRepaint = paramRepaint.max(
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java
index d24c86f77c..6020a52080 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktDecorators.java
@@ -21,27 +21,25 @@ package org.apache.causeway.viewer.wicket.ui.util;
 import java.util.Optional;
 
 import org.apache.wicket.Component;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.form.Button;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
+import org.apache.wicket.markup.html.list.ListItem;
 
 import org.apache.causeway.applib.fa.FontAwesomeLayers;
-import org.apache.causeway.applib.services.i18n.TranslationService;
-import org.apache.causeway.commons.internal.base._Casts;
-import org.apache.causeway.commons.internal.base._Strings;
-import 
org.apache.causeway.viewer.commons.model.action.decorator.UiActionDecorator;
+import org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.viewer.commons.model.decorators.ConfirmDecorator;
 import 
org.apache.causeway.viewer.commons.model.decorators.ConfirmDecorator.ConfirmDecorationModel;
 import org.apache.causeway.viewer.commons.model.decorators.DangerDecorator;
 import org.apache.causeway.viewer.commons.model.decorators.DisablingDecorator;
 import org.apache.causeway.viewer.commons.model.decorators.FormLabelDecorator;
 import org.apache.causeway.viewer.commons.model.decorators.IconDecorator;
+import org.apache.causeway.viewer.commons.model.decorators.MenuActionDecorator;
 import 
org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator;
-import 
org.apache.causeway.viewer.commons.model.decorators.PrototypingDecorator.PrototypingDecorationModel;
 import org.apache.causeway.viewer.commons.model.decorators.TooltipDecorator;
 import 
org.apache.causeway.viewer.commons.model.decorators.TooltipDecorator.TooltipDecorationModel;
 import org.apache.causeway.viewer.commons.model.layout.UiPlacementDirection;
-import org.apache.causeway.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.causeway.viewer.wicket.model.links.Menuable;
 import 
org.apache.causeway.viewer.wicket.ui.components.actionmenu.FontAwesomeBehavior;
 import 
org.apache.causeway.viewer.wicket.ui.util.BootstrapConstants.ButtonSemantics;
 
@@ -52,9 +50,6 @@ import lombok.experimental.UtilityClass;
 import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig.Placement;
 import 
de.agilecoders.wicket.extensions.markup.html.bootstrap.confirmation.ConfirmationConfig;
 
-/**
- *
- */
 @UtilityClass
 public class WktDecorators {
 
@@ -77,13 +72,9 @@ public class WktDecorators {
     public final static class FormLabel implements 
FormLabelDecorator<Component> {
         @Override
         public void decorate(final Component uiComponent, final 
FormLabelDecorationModel decorationModel) {
-            if(decorationModel.isMandatoryMarker()) {
+            if(decorationModel.isMandatoryIndicatorShown()) {
                 Wkt.cssAppend(uiComponent, "mandatory");
             }
-            if(_Strings.isNotEmpty(decorationModel.getSuffix())) {
-                final IModel<String> labelModel = 
_Casts.uncheckedCast(uiComponent.getDefaultModel());
-                uiComponent.setDefaultModel(Model.of(labelModel.getObject() + 
decorationModel.getSuffix()));
-            }
             uiComponent.setEscapeModelStrings(true);
         }
     }
@@ -99,7 +90,7 @@ public class WktDecorators {
         @Override
         public void decorate(final Component uiComponent, final 
DisablingDecorationModel decorationModel) {
             val tooltipDecorationModel = TooltipDecorationModel
-                    .ofBody(UiPlacementDirection.BOTTOM, 
decorationModel.getReason());
+                    .ofBody(UiPlacementDirection.BOTTOM, 
decorationModel.reason());
             getTooltip().decorate(uiComponent, tooltipDecorationModel);
 
             Wkt.cssAppend(uiComponent, "disabled");
@@ -120,12 +111,12 @@ public class WktDecorators {
         public void decorate(final Component uiComponent, final 
ConfirmDecorationModel decorationModel) {
 
             val confirmationConfig = new ConfirmationConfig()
-                    .withTitle(decorationModel.getTitle())
-                    .withBtnOkLabel(decorationModel.getOkLabel())
-                    .withBtnCancelLabel(decorationModel.getCancelLabel())
+                    .withTitle(decorationModel.title())
+                    .withBtnOkLabel(decorationModel.okLabel())
+                    .withBtnCancelLabel(decorationModel.cancelLabel())
                     .withBtnOkClass(ButtonSemantics.DANGER.fullButtonCss())
                     
.withBtnCancelClass(ButtonSemantics.SECONDARY.fullButtonCss())
-                    
.withPlacement(Placement.valueOf(decorationModel.getPlacement().name().toLowerCase()));
+                    
.withPlacement(Placement.valueOf(decorationModel.placement().name().toLowerCase()));
 
             Wkt.behaviorAddConfirm(uiComponent, confirmationConfig);
 
@@ -167,67 +158,48 @@ public class WktDecorators {
 
     // -- ADVANCED DECORATOR CLASSES
 
-    public final static class ActionLink extends UiActionDecorator<Component> {
+    public final static class ActionLink 
+    implements MenuActionDecorator<ListItem<? extends Menuable>, 
AjaxLink<ManagedObject>, Label> {
 
-        public ActionLink() {
-            super(getTooltip(), getDisable(), getConfirm(), getPrototyping(), 
getIcon());
-        }
-
-        //TODO this is yet the result of refactoring the logic originating 
from the wicket viewer
-        //I'm not happy with this yet: this code decorates 2 UI components at 
once which is confusing
-        //also is not generic enough, because wicket still needs to override 
this in order to decorate
-        //even another UI component
-        private <T extends Component> void commonDecorateMenuItem(
-                final T uiComponent, // UI component #1
-                final LinkAndLabel linkAndLabel,
-                final TranslationService translationService) {
-
-            val actionLinkUiComponent = linkAndLabel.getUiComponent(); // UI 
component #2
-            val actionMeta = linkAndLabel.getManagedAction().getAction();
-
-            linkAndLabel.getDisableUiModel().ifPresent(disableUiModel->{
-                getDisableDecorator().decorate(uiComponent, disableUiModel);
-                getTooltipDecorator().decorate(uiComponent,
-                        
TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, 
disableUiModel.getReason()));
+        @Override
+        public void decorate(
+                ListItem<? extends Menuable> listItem, 
+                AjaxLink<ManagedObject> actionLink,
+                Label menuItemLabel,
+                MenuActionDecorationModel decorationModel) {
+            Wkt.cssAppend(listItem, decorationModel.featureIdentifier());
+            
+            decorationModel.disabling()
+                .ifPresentOrElse(disableUiModel->{
+                    getDisable().decorate(listItem, disableUiModel);
+                    getTooltip().decorate(listItem,
+                            
TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, 
disableUiModel.reason()));
+                }, ()->{
+                    decorationModel
+                        .describedAs()
+                        .ifPresent(describedAs->
+                            getTooltip()
+                                .decorate(listItem,
+                                        
TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, describedAs)));
+                    
+                    //{CAUSEWAY-1626] confirmation dialog for no-parameter 
menu actions
+                    if (decorationModel.isImmediateConfirmationRequired()) {
+                        var confirmUiModel = 
ConfirmDecorationModel.areYouSure(UiPlacementDirection.BOTTOM);
+                        getConfirm().decorate(actionLink, confirmUiModel);
+                    }
+                    
+                });
+            
+            decorationModel.prototyping().ifPresent(protoDecModel->{
+                getPrototyping().decorate(actionLink, protoDecModel);
             });
-
-            if (!linkAndLabel.getDisableUiModel().isPresent()) {
-
-                linkAndLabel
-                .getDescription()
-                .ifPresent(describedAs->
-                    getTooltipDecorator()
-                    .decorate(uiComponent,
-                            
TooltipDecorationModel.ofBody(UiPlacementDirection.BOTTOM, describedAs)));
-
-                //XXX CAUSEWAY-1626, confirmation dialog for no-parameter menu 
actions
-                if (actionMeta.isImmediateConfirmationRequired()) {
-
-                    val confirmUiModel = 
ConfirmDecorationModel.areYouSure(translationService, 
UiPlacementDirection.BOTTOM);
-                    getConfirmDecorator().decorate(actionLinkUiComponent, 
confirmUiModel);
-
-                }
-
-            }
-
-            if (actionMeta.isPrototype()) {
-                getPrototypingDecorator()
-                .decorate(actionLinkUiComponent, 
PrototypingDecorationModel.of(linkAndLabel.getManagedAction()));
-            }
-
-        }
-
-        public void decorateMenuItem(
-                final Component uiComponent,
-                final LinkAndLabel linkAndLabel,
-                final TranslationService translationService) {
-
-            Wkt.cssAppend(uiComponent, linkAndLabel.getFeatureIdentifier());
-
-            commonDecorateMenuItem(uiComponent, linkAndLabel, 
translationService);
-
-            linkAndLabel.getAdditionalCssClass()
-                
.ifPresent(cssClass->Wkt.cssAppend(linkAndLabel.getUiComponent(), cssClass));
+            
+            decorationModel.additionalCssClass()
+                .ifPresent(cssClass->Wkt.cssAppend(actionLink, cssClass));
+            
+            var faLayers = decorationModel.fontAwesomeLayers();
+            getIcon().decorate(menuItemLabel, faLayers);
+            getMissingIcon().decorate(actionLink, faLayers);
         }
 
     }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java
index ba211b4190..aea04b86ed 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktLinks.java
@@ -44,7 +44,6 @@ import 
org.apache.causeway.viewer.wicket.ui.components.widgets.linkandlabel.Acti
 import 
org.apache.causeway.viewer.wicket.ui.util.BootstrapConstants.ButtonSemantics;
 
 import lombok.NonNull;
-import lombok.val;
 import lombok.experimental.UtilityClass;
 
 @UtilityClass
@@ -64,10 +63,11 @@ public final class WktLinks {
             final LinkAndLabel linkAndLabel,
             final boolean isForceAlignmentWithBlankIcon) {
 
-        val link = linkAndLabel.getUiComponent();
-        val action = linkAndLabel.getManagedAction().getAction();
+        var link = linkAndLabel.getUiComponent();
+        var action = linkAndLabel.getManagedAction().getAction();
 
-        val hasDisabledReason = link instanceof ActionLink && 
_Strings.isNotEmpty(((ActionLink) link).getReasonDisabledIfAny());
+        var hasDisabledReason = link instanceof ActionLink 
+                && _Strings.isNotEmpty(((ActionLink) 
link).getReasonDisabledIfAny());
 
         WktTooltips.addTooltip(tooltipReceiver, hasDisabledReason
                 ? ((ActionLink) link).getReasonDisabledIfAny()
@@ -84,10 +84,8 @@ public final class WktLinks {
         if (action.getSemantics().isAreYouSure()) {
             if(action.getParameterCount()==0) {
                 if (!hasDisabledReason) {
-                    val translationService = 
linkAndLabel.getAction().getMetaModelContext()
-                            .getTranslationService();
-                    val confirmUiModel = ConfirmDecorationModel
-                            .areYouSure(translationService, 
UiPlacementDirection.BOTTOM);
+                    var confirmUiModel = ConfirmDecorationModel
+                            .areYouSure(UiPlacementDirection.BOTTOM);
                     WktDecorators.getConfirm().decorate(link, confirmUiModel);
                 }
             }
@@ -105,10 +103,10 @@ public final class WktLinks {
         .getAdditionalCssClass()
         .ifPresent(cssClass->Wkt.cssAppend(link, cssClass));
 
-        val viewTitleLabel = Wkt.labelAdd(link, titleId,
+        var viewTitleLabel = Wkt.labelAdd(link, titleId,
                 linkAndLabel::getFriendlyName);
 
-        val faLayers = 
linkAndLabel.lookupFontAwesomeLayers(isForceAlignmentWithBlankIcon);
+        var faLayers = 
linkAndLabel.lookupFontAwesomeLayers(isForceAlignmentWithBlankIcon);
 
         WktDecorators.getIcon().decorate(viewTitleLabel, faLayers);
         WktDecorators.getMissingIcon().decorate(viewTitleLabel, faLayers);
@@ -122,7 +120,7 @@ public final class WktLinks {
             final @NonNull String iconId, final @Nullable Function<T, 
IModel<String>> iconProvider,
             final @Nullable BiFunction<T, Label, IModel<String>> cssFactory) {
 
-        val t = item.getModelObject();
+        var t = item.getModelObject();
 
         // add title and icon to the link
 
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java
 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java
index 5cd30e9935..5d84648e9b 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/causeway/viewer/wicket/ui/util/WktTooltips.java
@@ -73,12 +73,12 @@ public class WktTooltips {
             }
         }
 
-        val placementDirection = 
tooltipDecorationModel.getPlacementDirection();
+        val placementDirection = tooltipDecorationModel.placementDirection();
 
-        final IModel<String> bodyModel = 
Model.of(tooltipDecorationModel.getBody());
+        final IModel<String> bodyModel = 
Model.of(tooltipDecorationModel.body());
 
         val tooltipBehavior = tooltipDecorationModel
-                .getTitle()
+                .title()
                 .map(title->Model.of(title))
                 .map(titleModel->createTooltipBehavior(placementDirection, 
titleModel, bodyModel))
                 .orElseGet(()->createTooltipBehavior(placementDirection, 
bodyModel));


Reply via email to