You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/11/03 07:54:16 UTC

[isis] branch master updated: ISIS-2741: support for Identifier to also represent action parameters

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 a70605b  ISIS-2741: support for Identifier to also represent action parameters
a70605b is described below

commit a70605b5008f57d74768b534272c1b52a1c71111
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Nov 3 08:54:07 2021 +0100

    ISIS-2741: support for Identifier to also represent action parameters
---
 .../java/org/apache/isis/applib/Identifier.java    | 24 ++++++++++++++++++++-
 .../applib/adapters/ValueSemanticsAbstract.java    | 19 +++++++++-------
 .../applib/adapters/ValueSemanticsProvider.java    | 12 +----------
 .../title/parser/TitleFacetUsingValueFacet.java    |  9 ++++----
 .../metamodel/facets/object/value/ValueFacet.java  |  4 +++-
 .../facets/object/value/ValueFacetAbstract.java    |  8 +++++--
 .../metamodel/specloader/SpecificationLoader.java  | 25 ++++++++++++++++++++++
 .../specimpl/ObjectActionParameterAbstract.java    |  2 +-
 .../valuesemantics/BigDecimalValueSemantics.java   | 24 ++++++++++++++++++++-
 .../AsciiDocValueSemanticsWithPreprocessing.java   |  2 +-
 .../interaction/DomainObjectTesterFactory.java     | 14 ++++++------
 .../scalars/ConverterBasedOnValueSemantics.java    |  6 +++---
 .../jdkmath/BigDecimalConverter_roundtrip.java     | 14 ++++++------
 13 files changed, 116 insertions(+), 47 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/Identifier.java b/api/applib/src/main/java/org/apache/isis/applib/Identifier.java
index f0d09e3..0f6965e 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/Identifier.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/Identifier.java
@@ -108,6 +108,11 @@ implements
 
     @Getter private final String memberLogicalName;
 
+    /**
+     * Optional. Used for <i>Action Parameters</i>, otherwise {@code -1}.
+     */
+    @Getter private final int parameterIndex;
+
     @Getter private final Can<String> memberParameterClassNames;
 
     @Getter private final Type type;
@@ -128,19 +133,29 @@ implements
      */
     @Getter(onMethod_ = {@Override}) private final TranslationContext translationContext;
 
-    // -- CONSTRUCTOR
+    // -- CONSTRUCTION
 
     private Identifier(
             final LogicalType logicalType,
             final String memberLogicalName,
             final Can<String> memberParameterClassNames,
             final Type type) {
+        this(logicalType, memberLogicalName, memberParameterClassNames, type, -1);
+    }
+
+    private Identifier(
+            final LogicalType logicalType,
+            final String memberLogicalName,
+            final Can<String> memberParameterClassNames,
+            final Type type,
+            final int parameterIndex) {
 
         this.logicalType = logicalType;
         this.className = logicalType.getClassName();
         this.memberLogicalName = memberLogicalName;
         this.memberParameterClassNames = memberParameterClassNames;
         this.type = type;
+        this.parameterIndex = parameterIndex;
 
         this.memberNameAndParameterClassNamesIdentityString =
                 memberLogicalName + (type.isAction()
@@ -155,6 +170,13 @@ implements
                 : className + "#" + memberNameAndParameterClassNamesIdentityString;
     }
 
+    // -- WITHERS
+
+    public Identifier withParameterIndex(final int parameterIndex) {
+        return new Identifier(logicalType, memberLogicalName, memberParameterClassNames, type, parameterIndex);
+    }
+
+
     // -- LOGICAL ID
 
     public String getLogicalIdentityString(final @NonNull String delimiter) {
diff --git a/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsAbstract.java b/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsAbstract.java
index fafd203..913a914 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsAbstract.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsAbstract.java
@@ -41,7 +41,8 @@ import lombok.val;
  * @since 2.x {@index}
  */
 public abstract class ValueSemanticsAbstract<T>
-implements ValueSemanticsProvider<T> {
+implements
+    ValueSemanticsProvider<T> {
 
     public static final String NULL_REPRESENTATION = "(none)";
     protected static final ValueType UNREPRESENTED = ValueType.STRING;
@@ -121,25 +122,27 @@ implements ValueSemanticsProvider<T> {
         }
         val format = getNumberFormat(context);
         format.setParseBigDecimal(true);
-        if(context!=null
-                && context.getMaximumFractionDigits()>-1) {
-            format.setMaximumFractionDigits(context.getMaximumFractionDigits());
-        }
-        val position = new ParsePosition(0);
+        configureDecimalFormat(context, format);
 
+        val position = new ParsePosition(0);
         try {
             val number = (BigDecimal)format.parse(input, position);
             if (position.getErrorIndex() != -1) {
                 throw new ParseException("could not parse input='" + input + "'", position.getErrorIndex());
             } else if (position.getIndex() < input.length()) {
-                throw new ParseException("input='" + input + "' wasnt processed completely", position.getIndex());
+                throw new ParseException("input='" + input + "' was not processed completely", position.getIndex());
             }
             return number;
         } catch (final NumberFormatException | ParseException e) {
             System.err.printf("suppressed message %s%n", e.getMessage());
             throw new TextEntryParseException("Not a decimal value " + input, e);
         }
-
     }
 
+    /**
+     * typically overridden by BigDecimalValueSemantics to set MaximumFractionDigits
+     * @param format
+     */
+    protected void configureDecimalFormat(final Context context, final DecimalFormat format) {}
+
 }
diff --git a/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsProvider.java b/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsProvider.java
index 955a65e..55d2437 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsProvider.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/adapters/ValueSemanticsProvider.java
@@ -50,18 +50,8 @@ public interface ValueSemanticsProvider<T> {
 
     @lombok.Value(staticConstructor = "of")
     class Context {
-
-        Identifier identifier;
+        Identifier featureIdentifier;
         InteractionContext interactionContext;
-        /**
-         * Optional. Used for for decimal values, when a fixed amount of fractional digits is specified, otherwise {@code -1}
-         */
-        public int getMaximumFractionDigits() {
-            // FIXME[ISIS-2741] provide some means to recover the meta-model member from feature-id,
-            // so we can evaluate facets that provide the MaximumFractionDigits
-            // - as an alternative move this to the Parser<T>
-            return -1;
-        }
     }
 
     Class<T> getCorrespondingClass();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/parser/TitleFacetUsingValueFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/parser/TitleFacetUsingValueFacet.java
index afd7c9c..3f5b6cf 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/parser/TitleFacetUsingValueFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/parser/TitleFacetUsingValueFacet.java
@@ -64,26 +64,25 @@ implements TitleFacet {
 
         if(renderRequest.getFeature() instanceof OneToOneAssociation) {
             val prop = (OneToOneAssociation)renderRequest.getFeature();
-            val featureId = prop.getFeatureIdentifier();
             final Renderer renderer = valueFacet
                     .selectRendererForPropertyElseFallback(prop);
-            return renderer.simpleTextPresentation(valueFacet.createValueSemanticsContext(featureId), pojo);
+            return renderer.simpleTextPresentation(valueFacet.createValueSemanticsContext(prop), pojo);
         }
         if(renderRequest.getFeature() instanceof ObjectActionParameter) {
             val param = (ObjectActionParameter)renderRequest.getFeature();
-            val featureId = param.getFeatureIdentifier();
             final Renderer renderer = valueFacet
                     .selectRendererForParameterElseFallback(param);
-            return renderer.simpleTextPresentation(valueFacet.createValueSemanticsContext(featureId), pojo);
+            return renderer.simpleTextPresentation(valueFacet.createValueSemanticsContext(param), pojo);
         }
 
         // fall back to default value semantics ...
 
         val featureId = getFacetHolder().getFeatureIdentifier();
+        val feature = getSpecificationLoader().loadFeature(featureId).orElse(null);
 
         return valueFacet.selectDefaultRenderer()
         .map(renderer->(Renderer) renderer)
-        .map(renderer->renderer.simpleTextPresentation(valueFacet.createValueSemanticsContext(featureId), pojo))
+        .map(renderer->renderer.simpleTextPresentation(valueFacet.createValueSemanticsContext(feature), pojo))
         .orElseGet(()->String.format("Value type %s has no value semantics for title rendering.",
                 renderRequest.getObject().getSpecification().getCorrespondingClass()));
 
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 a207b7a..fa46cdd 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
@@ -21,6 +21,8 @@ package org.apache.isis.core.metamodel.facets.object.value;
 import java.util.Optional;
 import java.util.stream.Stream;
 
+import org.springframework.lang.Nullable;
+
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.adapters.EncoderDecoder;
 import org.apache.isis.applib.adapters.Parser;
@@ -47,7 +49,7 @@ public interface ValueFacet<T> extends Facet {
 
     LogicalType getValueType();
     Can<ValueSemanticsProvider<T>> getValueSemantics();
-    Context createValueSemanticsContext(Identifier featureIdentifier);
+    Context createValueSemanticsContext(@Nullable ObjectFeature feature);
     <X> Stream<X> streamValueSemantics(Class<X> requiredType);
 
     // -- ENCODER DECODER
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 cf71a19..933f9a4 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
@@ -23,6 +23,7 @@ import java.util.function.Predicate;
 import java.util.stream.Stream;
 
 import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.lang.Nullable;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.adapters.EncoderDecoder;
@@ -41,6 +42,7 @@ import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.objectvalue.valuesemantics.ValueSemanticsSelectingFacet;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectFeature;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 
 import lombok.Getter;
@@ -92,13 +94,15 @@ implements ValueFacet<T> {
     }
 
     @Override
-    public ValueSemanticsProvider.Context createValueSemanticsContext(final Identifier featureIdentifier) {
+    public ValueSemanticsProvider.Context createValueSemanticsContext(final @Nullable ObjectFeature feature) {
         val iaProvider = super.getInteractionProvider();
         if(iaProvider==null) {
             return null; // JUnit context
         }
         return ValueSemanticsProvider.Context.of(
-                featureIdentifier,
+                feature!=null
+                    ? feature.getFeatureIdentifier()
+                    : null,
                 iaProvider.currentInteractionContext().orElse(null));
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index 95ce52f..cfcc695 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -23,6 +23,7 @@ import java.util.function.Consumer;
 
 import org.springframework.lang.Nullable;
 
+import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.commons.collections.Can;
@@ -31,6 +32,8 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutor;
 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 org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
 import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
@@ -218,4 +221,26 @@ public interface SpecificationLoader {
         return loadSpecification(domainType, TYPE_INTROSPECTED);
     }
 
+    // -- FEATURE RECOVERY
+
+    default Optional<ObjectFeature> loadFeature(final @Nullable Identifier featureIdentifier) {
+        if(featureIdentifier==null) {
+            return Optional.empty();
+        }
+        val typeSpec = specForLogicalType(featureIdentifier.getLogicalType()).orElse(null);
+        if(typeSpec==null) {
+            return Optional.empty();
+        }
+        val member = typeSpec.getMember(featureIdentifier.getMemberLogicalName()).orElse(null);
+        if(member==null) {
+            return Optional.empty();
+        }
+
+        final int paramIndex = featureIdentifier.getParameterIndex();
+
+        return featureIdentifier.getParameterIndex()<0
+                ? Optional.of(member)
+                : Optional.of(((ObjectAction)member).getParameters().getElseFail(paramIndex));
+    }
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
index 6635add..4821e4c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
@@ -118,7 +118,7 @@ implements
 
     @Override
     public Identifier getFeatureIdentifier() {
-        return getAction().getFeatureIdentifier();
+        return getAction().getFeatureIdentifier().withParameterIndex(number);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BigDecimalValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BigDecimalValueSemantics.java
index c723a9e..88a55f8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BigDecimalValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BigDecimalValueSemantics.java
@@ -19,20 +19,26 @@
 package org.apache.isis.core.metamodel.valuesemantics;
 
 import java.math.BigDecimal;
+import java.text.DecimalFormat;
 
+import javax.inject.Inject;
 import javax.inject.Named;
 
 import org.springframework.stereotype.Component;
 
-import org.apache.isis.applib.adapters.ValueSemanticsAbstract;
 import org.apache.isis.applib.adapters.DefaultsProvider;
 import org.apache.isis.applib.adapters.EncoderDecoder;
 import org.apache.isis.applib.adapters.Parser;
 import org.apache.isis.applib.adapters.Renderer;
+import org.apache.isis.applib.adapters.ValueSemanticsAbstract;
 import org.apache.isis.applib.adapters.ValueSemanticsProvider;
 import org.apache.isis.applib.exceptions.UnrecoverableException;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.schema.common.v2.ValueType;
 
+import lombok.Setter;
+import lombok.val;
+
 @Component
 @Named("isis.val.BigDecimalValueSemantics")
 public class BigDecimalValueSemantics
@@ -43,6 +49,9 @@ implements
     Parser<BigDecimal>,
     Renderer<BigDecimal> {
 
+    @Setter @Inject
+    private SpecificationLoader specificationLoader;
+
     @Override
     public Class<BigDecimal> getCorrespondingClass() {
         return BigDecimal.class;
@@ -101,4 +110,17 @@ implements
         return 10;
     }
 
+    @Override
+    protected void configureDecimalFormat(final Context context, final DecimalFormat format) {
+        if(context==null) {
+            return;
+        }
+        context.getFeatureIdentifier();
+        val feature = specificationLoader.loadFeature(context.getFeatureIdentifier());
+
+        // FIXME[ISIS-2741] evaluate any facets that provide the MaximumFractionDigits
+
+        //format.setMaximumFractionDigits(...);
+    }
+
 }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/_infra/resources/AsciiDocValueSemanticsWithPreprocessing.java b/examples/demo/domain/src/main/java/demoapp/dom/_infra/resources/AsciiDocValueSemanticsWithPreprocessing.java
index b46fe09..057546d 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/_infra/resources/AsciiDocValueSemanticsWithPreprocessing.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/_infra/resources/AsciiDocValueSemanticsWithPreprocessing.java
@@ -24,7 +24,7 @@ extends AsciiDocValueSemantics {
         return render(adoc, plainAdoc->
             asciiDocConverterService
             .adocToHtml(
-                    context.getIdentifier().getLogicalType().getCorrespondingClass(),
+                    context.getFeatureIdentifier().getLogicalType().getCorrespondingClass(),
                     plainAdoc.getAdoc()));
     }
 
diff --git a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java
index 2cd23f5..31e2f36 100644
--- a/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java
+++ b/regressiontests/stable/src/main/java/org/apache/isis/testdomain/util/interaction/DomainObjectTesterFactory.java
@@ -31,6 +31,12 @@ import org.junit.jupiter.api.function.ThrowingSupplier;
 import org.springframework.lang.Nullable;
 import org.springframework.stereotype.Service;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.exceptions.unrecoverable.DomainModelException;
@@ -69,12 +75,6 @@ import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.testdomain.util.CollectionAssertions;
 import org.apache.isis.testing.integtestsupport.applib.validate.DomainModelValidator;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
 import lombok.Getter;
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -625,7 +625,7 @@ public class DomainObjectTesterFactory {
             val prop = this.getMetaModel().get();
 
             val context = valueFacet
-                    .createValueSemanticsContext(prop.getFeatureIdentifier());
+                    .createValueSemanticsContext(prop);
 
             return valueFacet.selectParserForPropertyElseFallback(prop)
                     .parseableTextRepresentation(context, managedPropertyIfAny.get().getPropertyValue().getPojo());
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ConverterBasedOnValueSemantics.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ConverterBasedOnValueSemantics.java
index 4c1bb5f..70d9d92 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ConverterBasedOnValueSemantics.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ConverterBasedOnValueSemantics.java
@@ -71,7 +71,7 @@ implements
         val valueFacet = valueFacet();
 
         val context = valueFacet
-                .createValueSemanticsContext(feature.getFeatureIdentifier());
+                .createValueSemanticsContext(feature);
 
         return valueFacet.selectParserForFeatureElseFallback(feature)
                 .parseTextRepresentation(context, text);
@@ -79,7 +79,7 @@ implements
 
     /**
      * Parameter {@code locale} is ignored!
-     * @see IConverter#convertToString(String, Locale)
+     * @see IConverter#convertToString(Object, Locale)
      */
     @Override
     public final String convertToString(final T value, final Locale locale) {
@@ -88,7 +88,7 @@ implements
         val valueFacet = valueFacet();
 
         val context = valueFacet
-                .createValueSemanticsContext(feature.getFeatureIdentifier());
+                .createValueSemanticsContext(feature);
 
         return valueFacet.selectParserForFeatureElseFallback(feature)
                 .parseableTextRepresentation(context, value);
diff --git a/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverter_roundtrip.java b/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverter_roundtrip.java
index 8b70978..fcc8b13 100644
--- a/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverter_roundtrip.java
+++ b/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverter_roundtrip.java
@@ -27,6 +27,11 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.Property;
 import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException;
@@ -40,11 +45,6 @@ import org.apache.isis.core.metamodel.valuesemantics.BigDecimalValueSemantics;
 import org.apache.isis.core.security._testing.InteractionService_forTesting;
 import org.apache.isis.viewer.wicket.ui.components.scalars.ConverterBasedOnValueSemantics;
 
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
 import lombok.Getter;
 import lombok.Setter;
 import lombok.val;
@@ -75,10 +75,12 @@ class BigDecimalConverter_roundtrip {
     @BeforeEach
     void setUp() throws Exception {
 
+        BigDecimalValueSemantics valueSemantics;
         mmc = MetaModelContext_forTesting.builder()
-                .valueSemantic(new BigDecimalValueSemantics())
+                .valueSemantic(valueSemantics = new BigDecimalValueSemantics())
                 .interactionProvider(interactionService = new InteractionService_forTesting())
                 .build();
+        valueSemantics.setSpecificationLoader(mmc.getSpecificationLoader());
 
         // pre-requisites for testing
         val reg = mmc.getServiceRegistry().lookupServiceElseFail(ValueSemanticsRegistry.class);