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 d0ebbe844a ISIS-3124: introduces PlaceholderRenderingService
d0ebbe844a is described below

commit d0ebbe844a478ed35c7ca2ccd078c9ad28d6f086
Author: andi-huber <[email protected]>
AuthorDate: Thu Aug 18 14:05:06 2022 +0200

    ISIS-3124: introduces PlaceholderRenderingService
---
 .../placeholder/PlaceholderRenderService.java      | 52 +++++++++++++++++
 .../org/apache/isis/applib/value/Password.java     |  5 +-
 .../value/semantics/ValueSemanticsAbstract.java    | 36 +++++-------
 .../apache/isis/applib/value/Password_Test.java    |  6 +-
 .../memento/ObjectMementoForEmpty.java             |  5 +-
 .../valuesemantics/PasswordValueSemantics.java     |  7 ++-
 .../value/BooleanValueSemanticsProviderTest.java   |  9 ++-
 .../ValueSemanticsProviderAbstractTestCase.java    | 15 +++--
 .../IsisModuleCoreRuntimeServices.java             |  2 +
 .../PlaceholderRenderServiceDefault.java           | 65 ++++++++++++++++++++++
 .../isis/testdomain/value/ValueSemanticsTest.java  | 13 ++---
 .../components/scalars/ScalarPanelAbstract2.java   |  9 +--
 .../blobclob/IsisBlobOrClobPanelAbstract.java      |  8 ++-
 .../scalars/reference/ReferencePanel.java          |  4 +-
 .../entitysimplelink/EntityLinkSimplePanel.java    | 20 ++++++-
 .../ObjectAdapterMementoProviderAbstract.java      |  9 ++-
 .../isis/viewer/wicket/ui/panels/PanelBase.java    | 10 ++++
 17 files changed, 207 insertions(+), 68 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/services/placeholder/PlaceholderRenderService.java
 
b/api/applib/src/main/java/org/apache/isis/applib/services/placeholder/PlaceholderRenderService.java
new file mode 100644
index 0000000000..aa48dfc652
--- /dev/null
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/services/placeholder/PlaceholderRenderService.java
@@ -0,0 +1,52 @@
+/*
+ *  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.isis.applib.services.placeholder;
+
+import lombok.Getter;
+import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Service that renders various {@link PlaceholderLiteral}s, as presented with 
the UI.
+ *
+ * @since 2.0 {@index}
+ */
+public interface PlaceholderRenderService {
+
+    @Getter
+    @RequiredArgsConstructor
+    public static enum PlaceholderLiteral {
+        NULL_REPRESENTATION("none"),
+        SUPPRESSED("suppressed");
+        private final String literal;
+    }
+
+    String asText(@NonNull PlaceholderLiteral placeholderLiteral);
+    String asHtml(@NonNull PlaceholderLiteral placeholderLiteral);
+
+    static PlaceholderRenderService fallback() {
+        return new PlaceholderRenderService() {
+            @Override public String asText(@NonNull final PlaceholderLiteral 
placeholderLiteral) {
+                return "(" + placeholderLiteral.getLiteral() + ")"; }
+            @Override public String asHtml(@NonNull final PlaceholderLiteral 
placeholderLiteral) {
+                return asText(placeholderLiteral); }
+        };
+    }
+
+}
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/value/Password.java 
b/api/applib/src/main/java/org/apache/isis/applib/value/Password.java
index c5ab75635a..972d8e229c 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/Password.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/Password.java
@@ -27,7 +27,8 @@ import javax.xml.bind.annotation.XmlAccessorType;
 
 import org.apache.isis.applib.IsisModuleApplib;
 import org.apache.isis.applib.annotation.Value;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 
 /**
  * Represents a password that will not displayed to the UI but can be 
persisted.
@@ -65,7 +66,7 @@ public class Password implements Serializable {
 
     @Override
     public String toString() {
-        return PlaceholderLiteral.SUPPRESSED.getLiteral();
+        return 
PlaceholderRenderService.fallback().asText(PlaceholderLiteral.SUPPRESSED);
     }
 
     public static class JaxbToStringAdapter
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
 
b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
index e3b1c1172d..5346b132fc 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
@@ -31,7 +31,6 @@ import java.util.Locale;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.function.Supplier;
-import java.util.function.UnaryOperator;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.lang.Nullable;
@@ -43,6 +42,8 @@ import org.apache.isis.applib.services.bookmark.IdStringifier;
 import org.apache.isis.applib.services.i18n.TranslationContext;
 import org.apache.isis.applib.services.i18n.TranslationService;
 import org.apache.isis.applib.services.iactnlayer.InteractionContext;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.applib.util.schema.CommonDtoUtils;
 import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics.EditingFormatDirection;
 import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalEditingPattern;
@@ -54,9 +55,7 @@ import 
org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.schema.common.v2.ValueType;
 import org.apache.isis.schema.common.v2.ValueWithTypeDto;
 
-import lombok.Getter;
 import lombok.NonNull;
-import lombok.RequiredArgsConstructor;
 import lombok.val;
 
 /**
@@ -66,23 +65,6 @@ public abstract class ValueSemanticsAbstract<T>
 implements
     ValueSemanticsProvider<T> {
 
-    @Getter
-    @RequiredArgsConstructor
-    public static enum PlaceholderLiteral {
-        NULL_REPRESENTATION("(none)",       "badge bg-light 
placeholder-literal-null"),
-        SUPPRESSED(         "(suppressed)", "badge bg-light 
placeholder-literal-suppressed");
-        private final String literal;
-        private final String cssClass;
-        public String asText(final UnaryOperator<String> translator) {
-            return translator.apply(literal);
-        }
-        public String asHtml(final UnaryOperator<String> translator) {
-            return String.format("<span class=\"%s\">%s</span>",
-                    getCssClass(),
-                    asText(translator));
-        }
-    }
-
     @SuppressWarnings("unchecked")
     @Override
     public OrderRelation<T, ?> getOrderRelation() {
@@ -138,13 +120,13 @@ implements
     protected String renderTitle(final T value, final Function<T, String> 
toString) {
         return Optional.ofNullable(value)
                 .map(toString)
-                
.orElse(PlaceholderLiteral.NULL_REPRESENTATION.asText(this::translate));
+                
.orElseGet(()->getPlaceholderRenderService().asText(PlaceholderLiteral.NULL_REPRESENTATION));
     }
 
     protected String renderHtml(final T value, final Function<T, String> 
toString) {
         return Optional.ofNullable(value)
                 .map(toString)
-                
.orElse(PlaceholderLiteral.NULL_REPRESENTATION.asHtml(this::translate));
+                
.orElseGet(()->getPlaceholderRenderService().asHtml(PlaceholderLiteral.NULL_REPRESENTATION));
     }
 
 
@@ -364,7 +346,7 @@ implements
         }
     }
 
-    // TRANSLATION SUPPORT
+    // -- TRANSLATION SUPPORT
 
     @Autowired(required = false) // nullable (JUnit support)
     protected TranslationService translationService;
@@ -374,5 +356,13 @@ implements
                 : text;
     }
 
+    // -- PLACEHOLDER RENDERING
+
+    @Autowired(required = false) // nullable (JUnit support)
+    private Optional<PlaceholderRenderService> placeholderRenderService = 
Optional.empty();
+    protected PlaceholderRenderService getPlaceholderRenderService() {
+        return 
placeholderRenderService.orElseGet(PlaceholderRenderService::fallback);
+    }
+
 
 }
diff --git 
a/api/applib/src/test/java/org/apache/isis/applib/value/Password_Test.java 
b/api/applib/src/test/java/org/apache/isis/applib/value/Password_Test.java
index 2d56173b98..76866d8b92 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/value/Password_Test.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/value/Password_Test.java
@@ -25,8 +25,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
-
 import lombok.val;
 
 class Password_Test {
@@ -75,10 +73,10 @@ class Password_Test {
         @Test
         void obscures_password() {
             Password password = new Password("secret");
-            assertEquals(PlaceholderLiteral.SUPPRESSED.getLiteral(), 
password.toString());
+            assertEquals("(suppressed)", password.toString());
 
             password = new Password("a very very very long password");
-            assertEquals(PlaceholderLiteral.SUPPRESSED.getLiteral(), 
password.toString());
+            assertEquals("(suppressed)", password.toString());
         }
     }
 
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoForEmpty.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoForEmpty.java
index fc20ad9696..a439d21a65 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoForEmpty.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/memento/ObjectMementoForEmpty.java
@@ -20,7 +20,8 @@ package org.apache.isis.core.metamodel.objectmanager.memento;
 
 import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 
 import lombok.Getter;
 import lombok.NonNull;
@@ -36,7 +37,7 @@ public class ObjectMementoForEmpty implements ObjectMemento {
 
     @Override
     public String getTitle() {
-        return 
ValueSemanticsAbstract.PlaceholderLiteral.NULL_REPRESENTATION.getLiteral();
+        return 
PlaceholderRenderService.fallback().asText(PlaceholderLiteral.NULL_REPRESENTATION);
     }
 
     @Override
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
index 6bf34ac020..3cb501314c 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
@@ -24,6 +24,7 @@ import javax.inject.Named;
 import org.springframework.stereotype.Component;
 
 import org.apache.isis.applib.annotation.PriorityPrecedence;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.applib.value.Password;
 import org.apache.isis.applib.value.semantics.Parser;
 import org.apache.isis.applib.value.semantics.Renderer;
@@ -70,19 +71,19 @@ implements
 
     @Override
     public String titlePresentation(final Context context, final Password 
value) {
-        return renderTitle(value, 
v->PlaceholderLiteral.SUPPRESSED.asText(this::translate));
+        return renderTitle(value, 
v->getPlaceholderRenderService().asText(PlaceholderLiteral.SUPPRESSED));
     }
 
     @Override
     public String htmlPresentation(final Context context, final Password 
value) {
-        return renderHtml(value, 
v->PlaceholderLiteral.SUPPRESSED.asHtml(this::translate));
+        return renderHtml(value, 
v->getPlaceholderRenderService().asHtml(PlaceholderLiteral.SUPPRESSED));
     }
 
     // -- PARSER
 
     @Override
     public String parseableTextRepresentation(final Context context, final 
Password value) {
-        return renderTitle(value, 
v->PlaceholderLiteral.SUPPRESSED.asText(this::translate));
+        return renderTitle(value, 
v->getPlaceholderRenderService().asText(PlaceholderLiteral.SUPPRESSED));
     }
 
     @Override
diff --git 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
index 4e9aebaa58..21d097449c 100644
--- 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
+++ 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/BooleanValueSemanticsProviderTest.java
@@ -21,13 +21,12 @@ package org.apache.isis.core.metamodel.facets.value;
 import org.junit.Before;
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
 import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
 import org.apache.isis.core.metamodel.valuesemantics.BooleanValueSemantics;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
 public class BooleanValueSemanticsProviderTest
 extends ValueSemanticsProviderAbstractTestCase<Boolean> {
 
@@ -81,7 +80,7 @@ extends ValueSemanticsProviderAbstractTestCase<Boolean> {
 
     @Test
     public void testTitleWhenNotSet() throws Exception {
-        assertEquals(PlaceholderLiteral.NULL_REPRESENTATION.getLiteral(),
+        assertEquals("(none)",
                 value.titlePresentation(null, null));
     }
 
diff --git 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
index a2c41772cd..71eb5d60c3 100644
--- 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
+++ 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
@@ -28,17 +28,10 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.not;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
 import org.apache.isis.applib.services.iactn.InteractionProvider;
 import org.apache.isis.applib.value.semantics.Parser;
 import org.apache.isis.applib.value.semantics.Renderer;
 import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
 import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2;
 import 
org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2.Mode;
@@ -50,6 +43,12 @@ import 
org.apache.isis.core.metamodel.facets.object.value.ValueSerializerDefault
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.valuesemantics.StringValueSemantics;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
 import lombok.Getter;
 
 public abstract class ValueSemanticsProviderAbstractTestCase<T> {
@@ -160,7 +159,7 @@ public abstract class 
ValueSemanticsProviderAbstractTestCase<T> {
             assertEquals("",
                     semantics.getRenderer().titlePresentation(null, null));
         } else {
-            assertEquals(PlaceholderLiteral.NULL_REPRESENTATION.getLiteral(),
+            assertEquals("(none)",
                     semantics.getRenderer().titlePresentation(null, null));
         }
 
diff --git 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
index 2552cec424..a5bf42d8fa 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
@@ -48,6 +48,7 @@ import 
org.apache.isis.core.runtimeservices.memento.ObjectMementoServiceDefault;
 import 
org.apache.isis.core.runtimeservices.menubars.MenuBarsLoaderServiceDefault;
 import 
org.apache.isis.core.runtimeservices.menubars.bootstrap.MenuBarsServiceBS;
 import org.apache.isis.core.runtimeservices.message.MessageServiceDefault;
+import 
org.apache.isis.core.runtimeservices.placeholder.PlaceholderRenderServiceDefault;
 import org.apache.isis.core.runtimeservices.publish.CommandPublisherDefault;
 import 
org.apache.isis.core.runtimeservices.publish.EntityChangesPublisherDefault;
 import 
org.apache.isis.core.runtimeservices.publish.EntityPropertyChangePublisherDefault;
@@ -109,6 +110,7 @@ import 
org.apache.isis.core.runtimeservices.xmlsnapshot.XmlSnapshotServiceDefaul
         ObjectIconServiceDefault.class,
         ObjectLifecyclePublisherDefault.class,
         ObjectMementoServiceDefault.class,
+        PlaceholderRenderServiceDefault.class,
         LifecycleCallbackNotifier.class,
         SchemaValueMarshallerDefault.class,
         ScratchpadDefault.class,
diff --git 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/placeholder/PlaceholderRenderServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/placeholder/PlaceholderRenderServiceDefault.java
new file mode 100644
index 0000000000..8b02590ab9
--- /dev/null
+++ 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/placeholder/PlaceholderRenderServiceDefault.java
@@ -0,0 +1,65 @@
+/*
+ *  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.isis.core.runtimeservices.placeholder;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.services.i18n.TranslationContext;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
+import org.apache.isis.core.runtimeservices.IsisModuleCoreRuntimeServices;
+
+import lombok.NonNull;
+import lombok.val;
+
+/**
+*
+* @since 2.0
+*
+*/
+@Service
+@Named(IsisModuleCoreRuntimeServices.NAMESPACE + 
".PlaceholderRenderServiceDefault")
+@Priority(PriorityPrecedence.MIDPOINT)
+@Qualifier("Default")
+public class PlaceholderRenderServiceDefault
+implements PlaceholderRenderService {
+
+    @Inject private TranslationService translationService;
+
+    @Override
+    public String asText(@NonNull final PlaceholderLiteral placeholderLiteral) 
{
+        val translatedPlainText = translationService
+                .translate(TranslationContext.empty(), 
placeholderLiteral.getLiteral());
+        return "(" + translatedPlainText + ")";
+    }
+
+    @Override
+    public String asHtml(@NonNull final PlaceholderLiteral placeholderLiteral) 
{
+        return String.format("<span class=\"%s\">%s</span>",
+                "badge bg-light placeholder-literal-" + 
placeholderLiteral.getLiteral(),
+                asText(placeholderLiteral));
+    }
+
+}
diff --git 
a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
 
b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
index 0ba600df51..60e7d6f32e 100644
--- 
a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
+++ 
b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
@@ -37,11 +37,6 @@ import org.junit.jupiter.params.provider.MethodSource;
 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.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.graph.tree.TreeNode;
 import org.apache.isis.applib.locale.UserLocale;
@@ -53,7 +48,6 @@ import org.apache.isis.applib.value.Password;
 import org.apache.isis.applib.value.semantics.Parser;
 import org.apache.isis.applib.value.semantics.Renderer;
 import org.apache.isis.applib.value.semantics.ValueDecomposition;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
 import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
 import org.apache.isis.commons.functional.Try;
@@ -76,6 +70,11 @@ import 
org.apache.isis.testdomain.value.ValueSemanticsTester.PropertyInteraction
 import org.apache.isis.valuetypes.asciidoc.applib.value.AsciiDoc;
 import org.apache.isis.valuetypes.markdown.applib.value.Markdown;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import lombok.val;
 
 @SpringBootTest(
@@ -240,7 +239,7 @@ class ValueSemanticsTest {
 
                             if(valueType.equals(Password.class)) {
                                 val recoveredValue = 
(Password)parser.parseTextRepresentation(context, stringified);
-                                
assertTrue(recoveredValue.checkPassword(PlaceholderLiteral.SUPPRESSED.getLiteral()));
+                                
assertTrue(recoveredValue.checkPassword("(suppressed)"));
 
                             } else {
 
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
index 320a41fdf7..552db98006 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
@@ -29,7 +29,7 @@ import org.apache.wicket.markup.repeater.RepeatingView;
 import org.apache.wicket.model.IModel;
 import org.springframework.lang.Nullable;
 
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.core.metamodel.commons.ScalarRepresentation;
 import org.apache.isis.viewer.commons.model.StringForRendering;
 import org.apache.isis.viewer.wicket.model.models.InlinePromptContext;
@@ -45,12 +45,11 @@ import 
org.apache.isis.viewer.wicket.ui.panels.FormExecutorDefault;
 import org.apache.isis.viewer.wicket.ui.util.Wkt;
 import org.apache.isis.viewer.wicket.ui.util.WktTooltips;
 
+import 
de.agilecoders.wicket.extensions.markup.html.bootstrap.form.fileinput.BootstrapFileInputField;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.val;
 
-import 
de.agilecoders.wicket.extensions.markup.html.bootstrap.form.fileinput.BootstrapFileInputField;
-
 /**
  *  Adds inline prompt logic.
  */
@@ -187,7 +186,9 @@ extends ScalarPanelAbstract {
     protected StringForRendering obtainOutputFormat() {
         val proposedValue = scalarModel().proposedValue();
         if(!proposedValue.isPresent()) {
-            return 
StringForRendering.markup(PlaceholderLiteral.NULL_REPRESENTATION.asHtml(this::translate));
+            return StringForRendering.markup(
+                    getPlaceholderRenderService()
+                    .asHtml(PlaceholderLiteral.NULL_REPRESENTATION));
         }
         val useText = isUsingTextarea()
                 || getFormatModifiers().contains(FormatModifier.BADGE);
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
index 322e152bc4..3b9715e5f3 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/blobclob/IsisBlobOrClobPanelAbstract.java
@@ -29,10 +29,10 @@ import org.apache.wicket.markup.html.form.upload.FileUpload;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.request.resource.IResource;
 
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.applib.value.Blob;
 import org.apache.isis.applib.value.Clob;
 import org.apache.isis.applib.value.NamedWithMimeType;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
 import org.apache.isis.viewer.commons.model.StringForRendering;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import 
org.apache.isis.viewer.wicket.ui.components.scalars.ScalarFragmentFactory.CompactFragment;
@@ -89,7 +89,8 @@ extends ScalarPanelFormFieldAbstract<T> {
         val caption = getBlobOrClobFromModel()
                 .map(NamedWithMimeType::getName)
                 .orElseGet(()->
-                    
PlaceholderLiteral.NULL_REPRESENTATION.asText(this::translate));
+                    getPlaceholderRenderService()
+                    .asText(PlaceholderLiteral.NULL_REPRESENTATION));
         return StringForRendering.text(caption);
     }
 
@@ -124,7 +125,8 @@ extends ScalarPanelFormFieldAbstract<T> {
             // represent null reference by a simple markup displaying '(none)'
             val linkContainer = Wkt.container(id);
             Wkt.markupAdd(linkContainer, CompactFragment.ID_LINK_LABEL,
-                    
PlaceholderLiteral.NULL_REPRESENTATION.asHtml(this::translate));
+                    getPlaceholderRenderService()
+                    .asHtml(PlaceholderLiteral.NULL_REPRESENTATION));
             return linkContainer;
         });
     }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
index 8edb6cee80..87c0cae502 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java
@@ -31,7 +31,7 @@ import org.apache.wicket.util.convert.IConverter;
 import org.wicketstuff.select2.ChoiceProvider;
 import org.wicketstuff.select2.Settings;
 
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMemento;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.util.Facets;
@@ -208,7 +208,7 @@ public class ReferencePanel extends 
ScalarPanelSelectAbstract {
                 WktComponents.permanentlyHide(container, 
ID_ENTITY_TITLE_IF_NULL);
             } else {
                 Wkt.markupAdd(container, ID_ENTITY_TITLE_IF_NULL,
-                        
PlaceholderLiteral.NULL_REPRESENTATION.asHtml(this::translate));
+                        
getPlaceholderRenderService().asHtml(PlaceholderLiteral.NULL_REPRESENTATION));
             }
         });
 
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/entitysimplelink/EntityLinkSimplePanel.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/entitysimplelink/EntityLinkSimplePanel.java
index 358ad2a65c..10fa23f559 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/entitysimplelink/EntityLinkSimplePanel.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/entitysimplelink/EntityLinkSimplePanel.java
@@ -24,16 +24,19 @@ import 
org.apache.wicket.markup.html.form.FormComponentPanel;
 import org.apache.wicket.model.IModel;
 
 import org.apache.isis.applib.services.i18n.TranslationContext;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
+import org.apache.isis.core.runtime.context.IsisAppCommonContext;
 import 
org.apache.isis.core.runtime.context.IsisAppCommonContext.HasCommonContext;
 import org.apache.isis.viewer.commons.model.components.ComponentType;
 import 
org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.CancelHintRequired;
 import 
org.apache.isis.viewer.wicket.ui.components.widgets.formcomponent.FormComponentPanelAbstract;
 import org.apache.isis.viewer.wicket.ui.util.Wkt;
 
+import lombok.Getter;
 import lombok.val;
 
 /**
@@ -69,7 +72,7 @@ implements CancelHintRequired  {
         if(isEmpty) {
             // represent null reference by a simple markup displaying '(none)'
             Wkt.markupAdd(this, ID_ENTITY_TITLE_NULL,
-                    
PlaceholderLiteral.NULL_REPRESENTATION.asHtml(this::translate));
+                    
getPlaceholderRenderService().asHtml(PlaceholderLiteral.NULL_REPRESENTATION));
             permanentlyHide(ID_ENTITY_ICON_AND_TITLE);
 
         } else {
@@ -111,9 +114,20 @@ implements CancelHintRequired  {
      * Translate without context: Tooltips, Button-Labels, etc.
      */
     public final String translate(final String input) {
-        return 
((HasCommonContext)getModel()).getCommonContext().getTranslationService()
+        return getCommonContext().getTranslationService()
                 .translate(TranslationContext.empty(), input);
     }
 
+    // -- DEPENDENCIES
+
+    @Getter(lazy=true)
+    private final PlaceholderRenderService placeholderRenderService =
+        getCommonContext().lookupService(PlaceholderRenderService.class)
+            .orElseGet(PlaceholderRenderService::fallback);
+
+    private IsisAppCommonContext getCommonContext() {
+        return ((HasCommonContext)getModel()).getCommonContext();
+    }
+
 
 }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderAbstract.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderAbstract.java
index 54129f2f16..a2a909bd37 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderAbstract.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/select2/providers/ObjectAdapterMementoProviderAbstract.java
@@ -28,7 +28,8 @@ import org.wicketstuff.select2.ChoiceProvider;
 
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.i18n.TranslationContext;
-import 
org.apache.isis.applib.value.semantics.ValueSemanticsAbstract.PlaceholderLiteral;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
+import 
org.apache.isis.applib.services.placeholder.PlaceholderRenderService.PlaceholderLiteral;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Lists;
@@ -60,7 +61,7 @@ extends ChoiceProvider<ObjectMemento> {
     public String getDisplayValue(final ObjectMemento choiceMemento) {
         if (choiceMemento == null
                 || choiceMemento instanceof ObjectMementoForEmpty) {
-            return 
PlaceholderLiteral.NULL_REPRESENTATION.asText(this::translate);
+            return 
getPlaceholderRenderService().asText(PlaceholderLiteral.NULL_REPRESENTATION);
         }
         return translate(choiceMemento.getTitle());
     }
@@ -161,5 +162,9 @@ extends ChoiceProvider<ObjectMemento> {
         return 
getCommonContext().getTranslationService().translate(TranslationContext.empty(),
 input);
     }
 
+    @Getter(lazy=true)
+    private final PlaceholderRenderService placeholderRenderService =
+        getCommonContext().lookupService(PlaceholderRenderService.class)
+            .orElseGet(PlaceholderRenderService::fallback);
 
 }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelBase.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelBase.java
index 390e566f32..6c1181a95c 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelBase.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/panels/PanelBase.java
@@ -28,6 +28,7 @@ import org.apache.isis.applib.services.i18n.LanguageProvider;
 import org.apache.isis.applib.services.i18n.TranslationContext;
 import org.apache.isis.applib.services.i18n.TranslationService;
 import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.placeholder.PlaceholderRenderService;
 import org.apache.isis.applib.services.userreg.EmailNotificationService;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.config.IsisConfiguration;
@@ -50,6 +51,10 @@ import 
org.apache.isis.viewer.wicket.ui.pages.EmailVerificationUrlService;
 import org.apache.isis.viewer.wicket.ui.pages.PageClassRegistry;
 import org.apache.isis.viewer.wicket.ui.pages.PageNavigationService;
 
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+
 /**
  * Provides the <em>common context</em> for all implementing sub-classes.
  * @since 2.0
@@ -140,6 +145,11 @@ implements HasCommonContext {
         return pageNavigationService = 
computeIfAbsent(PageNavigationService.class, pageNavigationService);
     }
 
+    @Getter(lazy=true, value = AccessLevel.PROTECTED) @Accessors(makeFinal = 
true)
+    private final PlaceholderRenderService placeholderRenderService =
+        getCommonContext().lookupService(PlaceholderRenderService.class)
+            .orElseGet(PlaceholderRenderService::fallback);
+
     protected MessageBroker getMessageBroker() {
         return getCommonContext().getMessageBroker()
         .orElseThrow(()->_Exceptions.illegalState(

Reply via email to