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 0112b375ee ISIS-2994: further remove direct uses of facets in RO
0112b375ee is described below

commit 0112b375ee2dfb521e9718c5fd47e472742f67d6
Author: Andi Huber <[email protected]>
AuthorDate: Thu Apr 7 13:51:36 2022 +0200

    ISIS-2994: further remove direct uses of facets in RO
---
 .../metamodel/facets/object/value/ValueFacet.java  |  2 +
 .../facets/object/value/ValueFacetAbstract.java    |  5 ++
 ...ionOrAnyMatchingValueSemanticsFacetFactory.java | 51 +++++++--------
 .../vsp/ValueFacetUsingSemanticsProvider.java      | 11 +++-
 .../apache/isis/core/metamodel/util/Facets.java    | 76 ++++++++++++++++++++++
 .../components/temporal/TemporalFieldFactory.java  | 10 +--
 .../components/temporal/TemporalFieldFactory.java  | 10 +--
 .../model/components/UiComponentFactory.java       | 19 +-----
 .../rendering/domainobjects/JsonValueEncoder.java  | 61 ++++++++---------
 .../domainobjects/ObjectPropertyReprRenderer.java  | 32 ++++-----
 .../domainobjects/ScalarValueReprRenderer.java     |  7 +-
 .../JsonValueEncoderTest_appendValueAndFormat.java | 50 +++++++-------
 .../viewer/wicket/model/models/ScalarModel.java    | 23 -------
 .../viewer/wicket/ui/components/scalars/_Util.java | 24 ++++++-
 14 files changed, 211 insertions(+), 170 deletions(-)

diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacet.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacet.java
index bea8c873e7..78caf452d3 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacet.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacet.java
@@ -55,6 +55,8 @@ extends
     ValueSerializer<T>,
     Facet {
 
+    Class<T> getValueClass();
+
     LogicalType getLogicalType();
 
     Can<ValueSemanticsProvider<T>> getAllValueSemantics();
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetAbstract.java
index 9ead446925..d706c6074c 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/ValueFacetAbstract.java
@@ -66,16 +66,21 @@ implements ValueFacet<T> {
         return ValueFacet.class;
     }
 
+    @Getter(onMethod_ = {@Override})
+    private final Class<T> valueClass;
+
     @Getter(onMethod_ = {@Override})
     private final Can<ValueSemanticsProvider<T>> allValueSemantics;
     private final ValueSerializer<T> valueSerializer;
 
     protected ValueFacetAbstract(
+            final Class<T> valueClass,
             final Can<ValueSemanticsProvider<T>> allValueSemantics,
             final FacetHolder holder,
             final Facet.Precedence precedence) {
 
         super(type(), holder, precedence);
+        this.valueClass = valueClass;
         this.allValueSemantics = allValueSemantics;
         this.valueSerializer = selectDefaultSemantics()
                 .map(ValueSerializerDefault::forSemantics)
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java
index 527f7ffbc8..38c8c3b416 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java
@@ -18,13 +18,13 @@
  */
 package org.apache.isis.core.metamodel.facets.object.value.annotcfg;
 
+import java.util.Optional;
+
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Value;
 import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
-import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -68,7 +68,6 @@ import lombok.extern.log4j.Log4j2;
  * <p>
  * Note that {@link ParentedCollectionFacet} is <i>not</i> installed.
  */
-@SuppressWarnings("rawtypes")
 @Log4j2
 public class 
ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory
 extends FacetFactoryAbstract {
@@ -81,48 +80,42 @@ extends FacetFactoryAbstract {
     @Override
     public void process(final ProcessClassContext processClassContext) {
 
-        val cls = processClassContext.getCls();
+        val valueClass = processClassContext.getCls();
         val facetHolder = processClassContext.getFacetHolder();
         val valueIfAny = processClassContext.synthesizeOnType(Value.class);
 
         val logicalTypeFacetIfAny = addFacetIfPresent(
                 LogicalTypeFacetForValueAnnotation
-                .create(valueIfAny, cls, facetHolder));
+                .create(valueIfAny, valueClass, facetHolder));
 
         val logicalType = logicalTypeFacetIfAny
                 .map(logicalTypeFacet->logicalTypeFacet.getLogicalType())
-                .orElseGet(()->LogicalType.fqcn(cls));
+                .orElseGet(()->LogicalType.fqcn(valueClass));
 
         val identifier = Identifier.classIdentifier(logicalType);
 
-        final Can<ValueSemanticsProvider> valueSemantics = 
_Casts.uncheckedCast(
-                getValueSemanticsResolver().selectValueSemantics(identifier, 
cls));
-
-        if(!valueSemantics.isEmpty()) {
-            addAllFacetsForValueSemantics(valueSemantics, facetHolder);
-            log.debug("found ValueSemanticsProvider for value type {}", cls);
-        }
-
-        valueIfAny
-        .ifPresent(value->{
-
-            if(valueSemantics.isCardinalityMultiple()) {
-                log.warn("found multiple ValueSemanticsProvider for value type 
{}; using the first", cls);
-            } else if(valueSemantics.isEmpty()) {
-                log.warn("could not find a ValueSemanticsProvider for value 
type {}; ", cls);
-                addAllFacetsForValueSemantics(Can.empty(), facetHolder);
-            }
-
-        });
+        addAllFacetsForValueSemantics(identifier, valueClass, facetHolder, 
valueIfAny);
     }
 
     // -- HELPER
 
-    private void addAllFacetsForValueSemantics(
-            final Can<ValueSemanticsProvider> semanticsProviders,
-            final FacetHolder holder) {
+    private <T> void addAllFacetsForValueSemantics(
+            final Identifier identifier,
+            final Class<T> valueClass,
+            final FacetHolder holder,
+            final Optional<Value> valueIfAny) {
+
+        val semanticsProviders = 
getValueSemanticsResolver().selectValueSemantics(identifier, valueClass);
+        if(semanticsProviders.isEmpty()) {
+            if(valueIfAny.isPresent()) {
+                log.warn("could not find a ValueSemanticsProvider for value 
type {}; "
+                        + "the type was found to be annotated with @Value", 
valueClass);
+            }
+        } else {
+            log.debug("found {} ValueSemanticsProvider(s) for value type {}", 
semanticsProviders.size(), valueClass);
+        }
 
-        val valueFacet = new 
ValueFacetUsingSemanticsProvider(semanticsProviders, holder);
+        val valueFacet = ValueFacetUsingSemanticsProvider.create(valueClass, 
semanticsProviders, holder);
 
         addFacet(valueFacet);
         addFacet(new ImmutableFacetViaValueSemantics(holder));
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
index 4333f21268..829d92d810 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueFacetUsingSemanticsProvider.java
@@ -26,11 +26,18 @@ import 
org.apache.isis.core.metamodel.facets.object.value.ValueFacetAbstract;
 public class ValueFacetUsingSemanticsProvider<T>
 extends ValueFacetAbstract<T> {
 
-    public ValueFacetUsingSemanticsProvider(
+    public static <T> ValueFacetUsingSemanticsProvider<T> create(
+            final Class<T> valueClass,
             final Can<ValueSemanticsProvider<T>> valueSemantics,
             final FacetHolder holder) {
+        return new ValueFacetUsingSemanticsProvider<T>(valueClass, 
valueSemantics, holder);
+    }
 
-        super(valueSemantics, holder, Precedence.DEFAULT);
+    protected ValueFacetUsingSemanticsProvider(
+            final Class<T> valueClass,
+            final Can<ValueSemanticsProvider<T>> valueSemantics,
+            final FacetHolder holder) {
+        super(valueClass, valueSemantics, holder, Precedence.DEFAULT);
     }
 
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java
index 3ba4cb3cd8..12c0213eff 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java
@@ -30,10 +30,13 @@ import 
org.apache.isis.applib.annotation.DomainServiceLayout.MenuBar;
 import org.apache.isis.applib.annotation.LabelPosition;
 import org.apache.isis.applib.annotation.PromptStyle;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.layout.grid.bootstrap.BSGrid;
+import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._NullSafe;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -52,6 +55,7 @@ import 
org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet;
 import org.apache.isis.core.metamodel.facets.object.projection.ProjectionFacet;
 import 
org.apache.isis.core.metamodel.facets.object.promptStyle.PromptStyleFacet;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.facets.object.value.ValueSerializer;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.daterenderedadjust.DateRenderAdjustFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.digits.MaxFractionalDigitsFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.digits.MaxTotalDigitsFacet;
@@ -60,8 +64,11 @@ import 
org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.maxlen.MaxLengthFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.multiline.MultiLineFacet;
 import 
org.apache.isis.core.metamodel.facets.objectvalue.typicallen.TypicalLengthFacet;
+import org.apache.isis.core.metamodel.interactions.managed.ManagedProperty;
+import 
org.apache.isis.core.metamodel.interactions.managed.ParameterNegotiationModel;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
 
 import lombok.val;
@@ -321,10 +328,79 @@ public final class Facets {
                 .orElseGet(OptionalInt::empty);
     }
 
+    // -- VALUE FACET
+
     public boolean valueIsPresent(final ObjectSpecification objectSpec) {
         return objectSpec.containsFacet(ValueFacet.class);
     }
 
+    public static Predicate<ObjectSpecification> valueTypeMatches(final 
Predicate<Class<?>> typeMatcher) {
+        return spec->
+            spec.lookupFacet(ValueFacet.class)
+            .map(ValueFacet::getLogicalType)
+            .map(LogicalType::getCorrespondingClass)
+            .map(typeMatcher::test)
+            .orElse(false);
+    }
+
+    @SuppressWarnings("unchecked")
+    public Optional<ObjectAction> valueCompositeMixinForParameter(
+            final ObjectFeature param,
+            final ParameterNegotiationModel parameterNegotiationModel,
+            final int paramIndex) {
+        val objectSpec = param.getElementType();
+        //if(!objectSpec.isValue()) return Optional.empty(); // optimization
+        return objectSpec.lookupFacet(ValueFacet.class)
+        .<ObjectAction>flatMap(valueFacet->
+            valueFacet.selectCompositeValueMixinForParameter(
+                    parameterNegotiationModel,paramIndex));
+    }
+
+    @SuppressWarnings("unchecked")
+    public Optional<ObjectAction> valueCompositeMixinForProperty(
+            final ObjectFeature prop,
+            final ManagedProperty managedProperty) {
+        val objectSpec = prop.getElementType();
+        //if(!objectSpec.isValue()) return Optional.empty(); // optimization
+        return objectSpec.lookupFacet(ValueFacet.class)
+        .<ObjectAction>flatMap(valueFacet->
+            valueFacet.selectCompositeValueMixinForProperty(managedProperty));
+    }
+
+    @SuppressWarnings("unchecked")
+    public <X> Stream<X> valueStreamSemantics(
+            final ObjectSpecification objectSpec, final Class<X> requiredType) 
{
+        //if(!objectSpec.isValue()) return Stream.empty(); // optimization
+        return objectSpec.lookupFacet(ValueFacet.class)
+        .map(valueFacet->valueFacet.streamValueSemantics(requiredType))
+        .orElseGet(Stream::empty);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <X> Optional<ValueSemanticsProvider<X>> valueDefaultSemantics(
+            final ObjectSpecification objectSpec,
+            final Class<X> requiredType) {
+        return objectSpec.lookupFacet(ValueFacet.class)
+        .filter(valueFacet->valueFacet.getValueClass().equals(requiredType))
+        .flatMap(ValueFacet::selectDefaultSemantics);
+    }
+
+    @SuppressWarnings("unchecked")
+    public <X> Optional<ValueSerializer<X>> valueSerializer(
+            final ObjectSpecification objectSpec,
+            final Class<X> requiredType) {
+        return objectSpec.lookupFacet(ValueFacet.class)
+        .filter(valueFacet->valueFacet.getValueClass().equals(requiredType))
+        .map(valueFacet->(ValueSerializer<X>)valueFacet);
+    }
 
+    public <X> ValueSerializer<X> valueSerializerElseFail(
+            final ObjectSpecification objectSpec,
+            final Class<X> requiredType) {
+        return valueSerializer(objectSpec, requiredType)
+        .orElseThrow(()->_Exceptions.illegalArgument(
+                "ObjectSpec is expected to have a ValueFacet<%s>",
+                objectSpec.getCorrespondingClass().getName()));
+    }
 
 }
diff --git 
a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/temporal/TemporalFieldFactory.java
 
b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/temporal/TemporalFieldFactory.java
index 86d41008c0..f5a4afb46c 100644
--- 
a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/temporal/TemporalFieldFactory.java
+++ 
b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/temporal/TemporalFieldFactory.java
@@ -26,7 +26,7 @@ import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.apache.isis.applib.value.semantics.TemporalValueSemantics;
 import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics.OffsetCharacteristic;
 import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalCharacteristic;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.incubator.viewer.javafx.model.binding.BindingsFx;
 import org.apache.isis.incubator.viewer.javafx.model.util._fx;
 import 
org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentHandlerFx;
@@ -47,13 +47,7 @@ public class TemporalFieldFactory implements 
UiComponentHandlerFx {
 
     @Override
     public boolean isHandling(final ComponentRequest request) {
-        ValueFacet<?> valueFacet = request
-                .getFeatureTypeSpec()
-                .getFacet(ValueFacet.class);
-        if(valueFacet==null) {
-            return false;
-        }
-        return valueFacet.streamValueSemantics(TemporalValueSemantics.class)
+        return Facets.valueStreamSemantics(request.getFeatureTypeSpec(), 
TemporalValueSemantics.class)
                 .anyMatch(valueSemantics->
                         
valueSemantics.getTemporalCharacteristic()==TemporalCharacteristic.DATE_ONLY
                         && 
valueSemantics.getOffsetCharacteristic()==OffsetCharacteristic.LOCAL);
diff --git 
a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/temporal/TemporalFieldFactory.java
 
b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/temporal/TemporalFieldFactory.java
index ce6eebc848..3613711fc5 100644
--- 
a/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/temporal/TemporalFieldFactory.java
+++ 
b/incubator/viewers/vaadin/ui/src/main/java/org/apache/isis/incubator/viewer/vaadin/ui/components/temporal/TemporalFieldFactory.java
@@ -30,7 +30,7 @@ import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics;
 import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics.OffsetCharacteristic;
 import 
org.apache.isis.applib.value.semantics.TemporalValueSemantics.TemporalCharacteristic;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.incubator.viewer.vaadin.ui.binding.BindingsVaa;
 import 
org.apache.isis.incubator.viewer.vaadin.ui.components.UiComponentHandlerVaa;
 import 
org.apache.isis.viewer.common.model.components.UiComponentFactory.ComponentRequest;
@@ -123,13 +123,7 @@ public class TemporalFieldFactory implements 
UiComponentHandlerVaa {
     }
 
     private Optional<TemporalValueSemantics<?>> 
getTemporalValueSemantics(final ComponentRequest request) {
-        ValueFacet<?> valueFacet = request
-                .getFeatureTypeSpec()
-                .getFacet(ValueFacet.class);
-        if(valueFacet==null) {
-            return Optional.empty();
-        }
-        return valueFacet.streamValueSemantics(TemporalValueSemantics.class)
+        return Facets.valueStreamSemantics(request.getFeatureTypeSpec(), 
TemporalValueSemantics.class)
                 .findFirst()
                 .map(v->(TemporalValueSemantics<?>)v);
     }
diff --git 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/components/UiComponentFactory.java
 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/components/UiComponentFactory.java
index 7ba0e949e6..ff40643bf9 100644
--- 
a/viewers/common/src/main/java/org/apache/isis/viewer/common/model/components/UiComponentFactory.java
+++ 
b/viewers/common/src/main/java/org/apache/isis/viewer/common/model/components/UiComponentFactory.java
@@ -24,13 +24,9 @@ import java.util.function.Consumer;
 import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.annotation.LabelPosition;
-import org.apache.isis.applib.id.LogicalType;
-import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.handler.ChainOfResponsibility;
-import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.functions._Predicates;
 import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedAction;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedFeature;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedParameter;
@@ -39,6 +35,7 @@ import 
org.apache.isis.core.metamodel.interactions.managed.ManagedValue;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.common.model.decorator.disable.DisablingUiModel;
 
 import lombok.NonNull;
@@ -119,21 +116,11 @@ public interface UiComponentFactory<B, C> {
 
         public boolean hasFacetForValueType(final @Nullable Class<?> 
valueType) {
             return valueType!=null
-                    ? getFeatureTypeSpec().lookupFacet(ValueFacet.class)
-                            .map(ValueFacet::getLogicalType)
-                            .map(LogicalType::getCorrespondingClass)
-                            .map(valueType::equals)
-                            .orElse(false)
+                    ? Facets.valueTypeMatches(valueType::equals)
+                            .test(getFeatureTypeSpec())
                     : false;
         }
 
-        public <T extends Facet> boolean hasFeatureTypeFacetAnyOf(
-                final @NonNull Can<Class<? extends Facet>> facetTypes) {
-            return facetTypes.stream()
-                    .map(getFeatureTypeSpec()::getFacet)
-                    .anyMatch(_NullSafe::isPresent);
-        }
-
         //TODO are there ever parameters that might render readonly?
         public boolean isReadOnly() {
             return 
((ManagedProperty)managedFeature).checkUsability().isPresent();
diff --git 
a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
 
b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
index 8b14a7a561..9411afaeb2 100644
--- 
a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
+++ 
b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoder.java
@@ -36,15 +36,15 @@ import org.springframework.stereotype.Service;
 import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
 import org.apache.isis.applib.value.semantics.ValueDecomposition;
-import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
 import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.collections._Maps;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import 
org.apache.isis.core.metamodel.facets.object.value.ValueSerializer.Format;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 
 import lombok.Getter;
@@ -96,22 +96,19 @@ public class JsonValueEncoder {
         if (!argValueRepr.isValue()) {
             throw new IllegalArgumentException("Representation must be of a 
value");
         }
-        val valueFacet = objectSpec.getFacet(ValueFacet.class);
-        if (valueFacet == null) {
-            String reason = "ObjectSpec expected to have a ValueFacet";
-            throw new IllegalArgumentException(reason);
-        }
 
-        val cls = objectSpec.getCorrespondingClass();
-        final JsonValueConverter jvc = converterByClass.get(cls);
+        val valueClass = objectSpec.getCorrespondingClass();
+        val valueSerializer =
+                Facets.valueSerializerElseFail(objectSpec, valueClass);
+
+        final JsonValueConverter jvc = converterByClass.get(valueClass);
         if(jvc == null) {
             // best effort
             if (argValueRepr.isString()) {
                 final String argStr = argValueRepr.asString();
                 return ManagedObject.of(objectSpec,
-                        valueFacet.fromEncodedString(Format.JSON, argStr));
+                        valueSerializer.fromEncodedString(Format.JSON, 
argStr));
             }
-
             throw new IllegalArgumentException("Unable to parse value");
         }
 
@@ -125,7 +122,7 @@ public class JsonValueEncoder {
             final String argStr = argValueRepr.asString();
             try {
                 return ManagedObject.of(objectSpec,
-                        valueFacet.fromEncodedString(Format.JSON, argStr));
+                        valueSerializer.fromEncodedString(Format.JSON, 
argStr));
             } catch(TextEntryParseException ex) {
                 throw new IllegalArgumentException(ex.getMessage());
             }
@@ -135,30 +132,30 @@ public class JsonValueEncoder {
     }
 
     public Object appendValueAndFormat(
-            final ManagedObject objectAdapter,
-            final ObjectSpecification objectSpecification,
+            final ManagedObject valueAdapter,
             final JsonRepresentation repr,
             final String format,
             final boolean suppressExtensions) {
 
-        val cls = objectSpecification.getCorrespondingClass();
-        val jsonValueConverter = converterByClass.get(cls);
+        val valueSpec = valueAdapter.getSpecification();
+        val valueClass = valueSpec.getCorrespondingClass();
+        val jsonValueConverter = converterByClass.get(valueClass);
         if(jsonValueConverter != null) {
-            return jsonValueConverter.appendValueAndFormat(objectAdapter, 
format, repr, suppressExtensions);
+            return jsonValueConverter.appendValueAndFormat(valueAdapter, 
format, repr, suppressExtensions);
         } else {
 
-            final Object value = 
ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)
+            final Object value = 
ManagedObjects.isNullOrUnspecifiedOrEmpty(valueAdapter)
                     ? NullNode.getInstance()
-                    : decomposeToJson(objectSpecification, 
objectAdapter.getPojo())
+                    : decomposeToJson(valueAdapter)
                         .map(Object.class::cast)
                         .orElseGet(()->{
                             log.warn("{Could not resolve a ValueComposer for 
{}, "
                                     + "falling back to rendering as 'null'. "
                                     + "Make sure the framework has access to a 
ValueSemanticsProvider<{}> "
                                     + "that implements ValueComposer<{}>}",
-                                    objectSpecification.getLogicalTypeName(),
-                                    
objectSpecification.getCorrespondingClass().getSimpleName(),
-                                    
objectSpecification.getCorrespondingClass().getSimpleName());
+                                    valueSpec.getLogicalTypeName(),
+                                    
valueSpec.getCorrespondingClass().getSimpleName(),
+                                    
valueSpec.getCorrespondingClass().getSimpleName());
                             return NullNode.getInstance();
                         });
 
@@ -168,15 +165,14 @@ public class JsonValueEncoder {
         }
     }
 
-    @SuppressWarnings("unchecked")
-    private static <T> Optional<ValueDecomposition> decompose(final 
ObjectSpecification spec, final T pojo) {
-        return spec.lookupFacet(ValueFacet.class)
-            .flatMap(ValueFacet::selectDefaultSemantics)
-            
.<ValueDecomposition>map(composer->((ValueSemanticsProvider<T>)composer).decompose(pojo));
+    private static Optional<ValueDecomposition> decompose(final ManagedObject 
valueAdapter) {
+        val valueClass = 
valueAdapter.getSpecification().getCorrespondingClass();
+        return Facets.valueDefaultSemantics(valueAdapter.getSpecification(), 
valueClass)
+                
.map(composer->composer.decompose(_Casts.uncheckedCast(valueAdapter.getPojo())));
     }
 
-    private static <T> Optional<String> decomposeToJson(final 
ObjectSpecification spec, final T pojo) {
-        return decompose(spec, pojo)
+    private static Optional<String> decomposeToJson(final ManagedObject 
valueAdapter) {
+        return decompose(valueAdapter)
                 .map(ValueDecomposition::toJson);
     }
 
@@ -192,11 +188,8 @@ public class JsonValueEncoder {
         }
 
         // else
-        val valueFacet = objectSpec.getFacet(ValueFacet.class);
-        if (valueFacet == null) {
-            throw new IllegalArgumentException("objectSpec expected to have 
ValueFacet");
-        }
-        return valueFacet.toEncodedString(Format.JSON, adapter.getPojo());
+        return Facets.valueSerializerElseFail(objectSpec, cls)
+                .toEncodedString(Format.JSON, 
_Casts.uncheckedCast(adapter.getPojo()));
     }
 
 
diff --git 
a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
 
b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
index 42d7c285fc..a9d4527528 100644
--- 
a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
+++ 
b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
@@ -26,8 +26,8 @@ import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedProperty;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.metamodel.util.Facets;
@@ -81,23 +81,22 @@ extends 
AbstractObjectMemberReprRenderer<OneToOneAssociation> {
     // ///////////////////////////////////////////////////
 
     private Object addValue(final LinkFollowSpecs linkFollower) {
-        val valueAdapterIfAny = objectMember.get(objectAdapter, 
getInteractionInitiatedBy());
+        val valueAdapterIfAny2 = objectMember.get(objectAdapter, 
getInteractionInitiatedBy());
 
-        // use the runtime type if we have a value, otherwise the compile time 
type of the member
-        val spec = ManagedObjects.isSpecified(valueAdapterIfAny)
-                ? valueAdapterIfAny.getSpecification()
-                : objectMember.getElementType();
+        // use the runtime type if we have a value, otherwise fallback to the 
compile time type of the member
+        val valueAdapter = ManagedObjects.isSpecified(valueAdapterIfAny2)
+                ? valueAdapterIfAny2
+                : ManagedObject.empty(objectMember.getElementType());
 
-        val valueFacet = spec.getFacet(ValueFacet.class);
-        if (valueFacet != null) {
+        val spec = valueAdapter.getSpecification();
+
+        if (Facets.valueIsPresent(objectAdapter.getSpecification())) {
             String format = null;
             final Class<?> valueType = spec.getCorrespondingClass();
             if(valueType == java.math.BigDecimal.class) {
                 // look for facet on member, else on the value's spec
 
-                val facetHolders = Can.<FacetHolder>of(
-                        objectMember,
-                        valueAdapterIfAny != null ? 
valueAdapterIfAny.getSpecification() : null);
+                val facetHolders = Can.<FacetHolder>of(objectMember, spec);
 
                 final int totalDigits = 
Facets.maxTotalDigits(facetHolders).orElse(-1);
                 final int scale = 
Facets.maxFractionalDigits(facetHolders).orElse(-1);
@@ -110,8 +109,7 @@ extends 
AbstractObjectMemberReprRenderer<OneToOneAssociation> {
             }
             return jsonValueEncoder
                     .appendValueAndFormat(
-                            valueAdapterIfAny,
-                            spec,
+                            valueAdapter,
                             representation,
                             format,
                             resourceContext.suppressMemberExtensions());
@@ -119,22 +117,20 @@ extends 
AbstractObjectMemberReprRenderer<OneToOneAssociation> {
 
         final boolean eagerlyRender =
                 (Facets.defaultViewIsTable(objectMember)
-                        && resourceContext.canEagerlyRender(valueAdapterIfAny))
+                        && resourceContext.canEagerlyRender(valueAdapter))
                 || (linkFollower != null
                         && !linkFollower.isTerminated());
 
-        if(valueAdapterIfAny == null) {
+        if(valueAdapter.getPojo() == null) {
             final NullNode value = NullNode.getInstance();
             representation.mapPut("value", value);
             return value;
         }
 
-        val valueAdapter = valueAdapterIfAny;
-
         final String title = valueAdapter.getTitle();
 
         final LinkBuilder valueLinkBuilder = DomainObjectReprRenderer
-                .newLinkToBuilder(resourceContext, Rel.VALUE, 
valueAdapterIfAny).withTitle(title);
+                .newLinkToBuilder(resourceContext, Rel.VALUE, 
valueAdapter).withTitle(title);
         if(eagerlyRender) {
             final DomainObjectReprRenderer renderer =
                     new DomainObjectReprRenderer(resourceContext, 
linkFollower, JsonRepresentation.newMap());
diff --git 
a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
 
b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
index 456dbb3a8d..83b6e4444f 100644
--- 
a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
+++ 
b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ScalarValueReprRenderer.java
@@ -20,9 +20,9 @@ package 
org.apache.isis.viewer.restfulobjects.rendering.domainobjects;
 
 import javax.ws.rs.core.MediaType;
 
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
@@ -30,8 +30,6 @@ import 
org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs;
 import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererAbstract;
 import org.apache.isis.viewer.restfulobjects.rendering.ReprRendererException;
 
-import lombok.val;
-
 public class ScalarValueReprRenderer
 extends ReprRendererAbstract<ManagedObject> {
 
@@ -58,8 +56,7 @@ extends ReprRendererAbstract<ManagedObject> {
 
     @Override
     public ScalarValueReprRenderer with(final ManagedObject objectAdapter) {
-        val valueFacet = 
objectAdapter.getSpecification().getFacet(ValueFacet.class);
-        if (valueFacet == null) {
+        if (!Facets.valueIsPresent(objectAdapter.getSpecification())) {
             throw ReprRendererException.create("Not an (encodable) value", 
objectAdapter.titleString());
         }
         String format = null; // TODO
diff --git 
a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_appendValueAndFormat.java
 
b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_appendValueAndFormat.java
index a77fd7221d..4d751f33cc 100644
--- 
a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_appendValueAndFormat.java
+++ 
b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_appendValueAndFormat.java
@@ -73,7 +73,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(String.class);
         allowingObjectAdapterToReturn("aString");
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getString("value"), is("aString"));
 
@@ -86,7 +86,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Boolean.class);
         allowingObjectAdapterToReturn(Boolean.TRUE);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isBoolean("value"), is(true));
         assertThat(representation.getBoolean("value"), is(Boolean.TRUE));
 
@@ -98,7 +98,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(boolean.class);
         allowingObjectAdapterToReturn(true);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isBoolean("value"), is(true));
         assertThat(representation.getBoolean("value"), is(true));
 
@@ -110,7 +110,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Byte.class);
         allowingObjectAdapterToReturn(Byte.valueOf((byte)123));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getByte("value"), 
is(Byte.valueOf((byte)123)));
 
@@ -123,7 +123,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(byte.class);
         allowingObjectAdapterToReturn((byte)123);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getByte("value"), is((byte)123));
 
@@ -136,7 +136,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Short.class);
         allowingObjectAdapterToReturn(Short.valueOf((short)12345));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getShort("value"), 
is(Short.valueOf((short)12345)));
 
@@ -149,7 +149,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(short.class);
         allowingObjectAdapterToReturn((short)12345);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getShort("value"), is((short)12345));
 
@@ -162,7 +162,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Integer.class);
         allowingObjectAdapterToReturn(Integer.valueOf(12345678));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getInt("value"), 
is(Integer.valueOf(12345678)));
 
@@ -175,7 +175,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(int.class);
         allowingObjectAdapterToReturn(12345678);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getInt("value"), is(12345678));
 
@@ -188,7 +188,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Long.class);
         allowingObjectAdapterToReturn(Long.valueOf(12345678901234L));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getLong("value"), 
is(Long.valueOf(12345678901234L)));
 
@@ -201,7 +201,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(long.class);
         allowingObjectAdapterToReturn(12345678901234L);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isIntegralNumber("value"), is(true));
         assertThat(representation.getLong("value"), is(12345678901234L));
 
@@ -214,7 +214,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Float.class);
         allowingObjectAdapterToReturn(Float.valueOf((float)123.45));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isDecimal("value"), is(true));
         assertThat(representation.getFloat("value"), 
is(Float.valueOf((float)123.45)));
 
@@ -227,7 +227,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Float.class);
         allowingObjectAdapterToReturn((float)123.45);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isDecimal("value"), is(true));
         assertThat(representation.getFloat("value"), is((float)123.45));
 
@@ -240,7 +240,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Double.class);
         allowingObjectAdapterToReturn(Double.valueOf(12345.6789));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isDecimal("value"), is(true));
         assertThat(representation.getDouble("value"), 
is(Double.valueOf(12345.6789)));
 
@@ -253,7 +253,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(double.class);
         allowingObjectAdapterToReturn(12345.6789);
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isDecimal("value"), is(true));
         assertThat(representation.getDouble("value"), is(12345.6789));
 
@@ -266,7 +266,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(Character.class);
         allowingObjectAdapterToReturn(Character.valueOf('a'));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getChar("value"), 
is(Character.valueOf('a')));
 
@@ -279,7 +279,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(char.class);
         allowingObjectAdapterToReturn('a');
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getChar("value"), is('a'));
 
@@ -292,7 +292,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(java.util.Date.class);
         allowingObjectAdapterToReturn(asDateTime("2014-04-25T12:34:45Z"));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getString("value"), 
is("2014-04-25T12:34:45Z"));
 
@@ -305,7 +305,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(java.sql.Date.class);
         allowingObjectAdapterToReturn(asSqlDate("2014-04-25"));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getString("value"), is("2014-04-25"));
 
@@ -318,7 +318,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(org.joda.time.DateTime.class);
         allowingObjectAdapterToReturn(new 
org.joda.time.DateTime(asDateTime("2014-04-25T12:34:45Z")));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getString("value"), 
is("2014-04-25T12:34:45Z"));
 
@@ -331,7 +331,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         
allowingLogicalTypeReturnObjectTypeFor(org.joda.time.LocalDateTime.class);
         allowingObjectAdapterToReturn(new 
org.joda.time.LocalDateTime(asDateTime("2014-04-25T12:34:45Z")));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getString("value"), 
is("2014-04-25T12:34:45Z"));
 
@@ -344,7 +344,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(org.joda.time.LocalDate.class);
         allowingObjectAdapterToReturn(new org.joda.time.LocalDate(2014,4,25));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.getString("value"), is("2014-04-25"));
 
@@ -358,7 +358,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         final long time = asDateTime("2014-04-25T12:34:45Z").getTime();
         allowingObjectAdapterToReturn(new Timestamp(time));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, null, false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, null, false);
         assertThat(representation.isLong("value"), is(true));
         assertThat(representation.getLong("value"), is(time));
 
@@ -371,7 +371,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(BigInteger.class);
         allowingObjectAdapterToReturn(new BigInteger("12345678901234567890"));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, "big-integer(22)", false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, "big-integer(22)", false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.isBigInteger("value"), is(true));
         assertThat(representation.getBigInteger("value"), is(new 
BigInteger("12345678901234567890")));
@@ -385,7 +385,7 @@ public class JsonValueEncoderTest_appendValueAndFormat {
         allowingLogicalTypeReturnObjectTypeFor(BigDecimal.class);
         allowingObjectAdapterToReturn(new 
BigDecimal("12345678901234567890.1234"));
 
-        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
mockObjectSpec, representation, "big-decimal(27,4)", false);
+        jsonValueEncoder.appendValueAndFormat(mockObjectAdapter, 
representation, "big-decimal(27,4)", false);
         assertThat(representation.isString("value"), is(true));
         assertThat(representation.isBigDecimal("value"), is(true));
         assertThat(representation.getBigDecimal("value"), is(new 
BigDecimal("12345678901234567890.1234")));
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
index 48a42164dd..f6a7687074 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
@@ -34,7 +34,6 @@ import org.apache.isis.commons.internal.debug.xray.XrayUi;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.commons.ScalarRepresentation;
 import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.interactions.managed.ManagedValue;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ManagedObjects;
@@ -345,26 +344,4 @@ implements HasRenderingHints, ScalarUiModel, 
LinksProvider, FormExecutorContext
         return 
getAssociatedActions().getFirstAssociatedWithInlineAsIfEdit().isPresent();
     }
 
-    @SuppressWarnings("unchecked")
-    public Optional<ObjectAction> lookupCompositeValueMixinForFeature() {
-        val spec = getScalarTypeSpec();
-        if(!spec.isValue()) {
-            return Optional.empty();
-        }
-        return getSpecialization().<Optional<ObjectAction>>fold(
-                param->{
-                    return spec.lookupFacet(ValueFacet.class)
-                            .<ObjectAction>flatMap(valueFacet->
-                                
valueFacet.selectCompositeValueMixinForParameter(
-                                        param.getParameterNegotiationModel(), 
param.getParameterIndex()));
-
-
-                },
-                prop->{
-                    return spec.lookupFacet(ValueFacet.class)
-                            .<ObjectAction>flatMap(valueFacet->
-                                
valueFacet.selectCompositeValueMixinForProperty(prop.getManagedProperty()));
-                });
-    }
-
 }
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/_Util.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/_Util.java
index 90ad5159fc..0c23d23ea3 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/_Util.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/_Util.java
@@ -31,11 +31,13 @@ import org.apache.isis.commons.internal.assertions._Assert;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.util.Facets;
 import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ScalarModel;
 import 
org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.LinkAndLabelFactory;
 
+import lombok.val;
 import lombok.experimental.UtilityClass;
 
 @UtilityClass
@@ -49,11 +51,11 @@ class _Util {
     boolean canParameterEnterNestedEdit(final ScalarModel scalarModel) {
         return scalarModel.isParameter()
                 && !scalarModel.hasChoices() // handled by select2 panels 
instead
-                && 
scalarModel.lookupCompositeValueMixinForFeature().isPresent();
+                && 
lookupCompositeValueMixinForFeature(scalarModel).isPresent();
     }
 
     Optional<LinkAndLabel> lookupMixinForCompositeValueUpdate(final 
ScalarModel scalarModel) {
-        return scalarModel.lookupCompositeValueMixinForFeature()
+        return lookupCompositeValueMixinForFeature(scalarModel)
             .flatMap(compositeValueMixinForFeature->
                 toLinkAndLabelWithRuleChecking(compositeValueMixinForFeature, 
scalarModel))
             .filter(_Util::guardAgainstInvalidCompositeMixinScenarios);
@@ -135,6 +137,24 @@ class _Util {
                 .adapt(validatable.getValue()));
     }
 
+    // -- HELPER
+
+    private Optional<ObjectAction> lookupCompositeValueMixinForFeature(final 
ScalarModel scalarModel) {
+        val spec = scalarModel.getScalarTypeSpec();
+        if(!spec.isValue()) {
+            return Optional.empty();
+        }
+        return scalarModel.getSpecialization().<Optional<ObjectAction>>fold(
+                param->
+                    Facets.valueCompositeMixinForParameter(
+                            scalarModel.getMetaModel(),
+                            param.getParameterNegotiationModel(), 
param.getParameterIndex()),
+                prop->
+                    Facets.valueCompositeMixinForProperty(
+                            scalarModel.getMetaModel(),
+                            prop.getManagedProperty()));
+    }
+
     // -- PROBABLY NO LONGER NEEDED
 
 //    private Optional<ManagedObject> recoverProposedValue2(

Reply via email to