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/02 09:56:39 UTC
[isis] branch master updated: ISIS-2741: introduce IConverter (wkt)
which is purely based on value-semantics
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 061f712 ISIS-2741: introduce IConverter (wkt) which is purely based on value-semantics
061f712 is described below
commit 061f71280f01b3e13808b65857504df239098782
Author: andi-huber <ah...@apache.org>
AuthorDate: Tue Nov 2 10:55:59 2021 +0100
ISIS-2741: introduce IConverter (wkt) which is purely based on
value-semantics
---
.../_testing/MetaModelContext_forTesting.java | 21 +++-
.../interaction/DomainObjectTesterFactory.java | 2 +-
.../scalars/ConverterBasedOnValueSemantics.java | 133 +++++++++++++++++++++
.../components/scalars/IsisConverterLocator.java | 3 +
...BigDecimalConverterWithScaleTest_roundtrip.java | 92 +++++++-------
5 files changed, 197 insertions(+), 54 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java
index 56ea5a5..e0d8563 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java
@@ -28,10 +28,9 @@ import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static java.util.Objects.requireNonNull;
-
import org.springframework.core.env.AbstractEnvironment;
+import org.apache.isis.applib.adapters.ValueSemanticsProvider;
import org.apache.isis.applib.services.factory.FactoryService;
import org.apache.isis.applib.services.grid.GridLoaderService;
import org.apache.isis.applib.services.grid.GridService;
@@ -63,6 +62,7 @@ import org.apache.isis.core.config.beans.IsisBeanTypeClassifier;
import org.apache.isis.core.config.beans.IsisBeanTypeRegistry;
import org.apache.isis.core.config.beans.IsisBeanTypeRegistryDefault;
import org.apache.isis.core.config.environment.IsisSystemEnvironment;
+import org.apache.isis.core.config.valuetypes.ValueSemanticsRegistry;
import org.apache.isis.core.metamodel.context.MetaModelContext;
import org.apache.isis.core.metamodel.execution.MemberExecutorService;
import org.apache.isis.core.metamodel.facets.object.icon.ObjectIconService;
@@ -91,6 +91,8 @@ import org.apache.isis.core.metamodel.valuetypes.ValueSemanticsRegistryDefault;
import org.apache.isis.core.security.authentication.manager.AuthenticationManager;
import org.apache.isis.core.security.authorization.manager.AuthorizationManager;
+import static java.util.Objects.requireNonNull;
+
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;
@@ -131,7 +133,7 @@ implements MetaModelContext {
private SpecificationLoader specificationLoader;
@Builder.Default
- private Function<MetaModelContext, ProgrammingModel> programmingModelFactory = ProgrammingModelFacetsJava11::new;
+ private Function<MetaModelContext, ProgrammingModel> programmingModelFactory = ProgrammingModelFacetsJava11::new;
private InteractionProvider interactionProvider;
@@ -168,6 +170,9 @@ implements MetaModelContext {
private List<Object> singletons;
@Singular
+ private List<ValueSemanticsProvider<?>> valueSemantics;
+
+ @Singular
private List<_ManagedBeanAdapter> singletonProviders;
// -- SERVICE SUPPORT
@@ -213,7 +218,7 @@ implements MetaModelContext {
repositoryService,
transactionService,
transactionState,
- new ValueSemanticsRegistryDefault(List.of(), getTranslationService()),
+ getValueSemanticsRegistry(),
new ObjectMementoService_forTesting(),
new BigDecimalValueSemantics(),
new URLValueSemantics(),
@@ -290,6 +295,14 @@ implements MetaModelContext {
return translationService;
}
+ private ValueSemanticsRegistry valueSemanticsRegistry;
+ private ValueSemanticsRegistry getValueSemanticsRegistry(){
+ if(valueSemanticsRegistry==null) {
+ valueSemanticsRegistry = new ValueSemanticsRegistryDefault(valueSemantics, getTranslationService());
+ }
+ return valueSemanticsRegistry;
+ }
+
private final IsisBeanFactoryPostProcessorForSpring isisBeanFactoryPostProcessorForSpring =
new IsisBeanFactoryPostProcessorForSpring();
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 09ee8f4..2cd23f5 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
@@ -743,7 +743,7 @@ public class DomainObjectTesterFactory {
protected abstract Optional<ObjectSpecification> getElementType();
- public ObjectSpecification getElementTypeElseFaile() {
+ public ObjectSpecification getElementTypeElseFail() {
return getElementType().orElseThrow();
}
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
new file mode 100644
index 0000000..8f0b61a
--- /dev/null
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ConverterBasedOnValueSemantics.java
@@ -0,0 +1,133 @@
+/*
+ * 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.viewer.wicket.ui.components.scalars;
+
+import java.util.Locale;
+
+import org.apache.wicket.util.convert.ConversionException;
+import org.apache.wicket.util.convert.IConverter;
+
+import org.apache.isis.applib.Identifier;
+import org.apache.isis.commons.internal.base._Either;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+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 org.apache.isis.core.runtime.context.IsisAppCommonContext;
+import org.apache.isis.core.runtime.context.IsisAppCommonContext.HasCommonContext;
+import org.apache.isis.viewer.wicket.model.util.CommonContextUtils;
+
+import lombok.Synchronized;
+import lombok.val;
+
+public abstract class ConverterBasedOnValueSemantics<T>
+implements
+ IConverter<T>,
+ HasCommonContext {
+
+ private static final long serialVersionUID = 1L;
+
+ private final Identifier featureIdentifier;
+ private final int paramIndex;
+ private transient _Either<OneToOneAssociation, ObjectActionParameter> propOrParam;
+ private transient IsisAppCommonContext commonContext;
+
+ protected ConverterBasedOnValueSemantics(final ObjectFeature propOrParam) {
+ this.propOrParam = propOrParam instanceof OneToOneAssociation // memoize
+ ? _Either.left((OneToOneAssociation)propOrParam)
+ : _Either.right((ObjectActionParameter)propOrParam);
+ this.featureIdentifier = propOrParam.getFeatureIdentifier();
+ this.paramIndex = this.propOrParam.fold(
+ prop->-1,
+ param->param.getParameterIndex());
+ }
+
+ /**
+ * Parameter {@code locale} is ignored!
+ * @see IConverter#convertToObject(String, Locale)
+ */
+ @Override
+ public T convertToObject(final String text, final Locale locale) throws ConversionException {
+
+ val feature = feature();
+ val valueFacet = valueFacet();
+
+ val context = valueFacet
+ .createValueSemanticsContext(feature.getFeatureIdentifier());
+
+ return valueFacet.selectParserForFeatureElseFallback(feature)
+ .parseTextRepresentation(context, text);
+ }
+
+ /**
+ * Parameter {@code locale} is ignored!
+ * @see IConverter#convertToString(String, Locale)
+ */
+ @Override
+ public String convertToString(final T value, final Locale locale) {
+
+ val feature = feature();
+ val valueFacet = valueFacet();
+
+ val context = valueFacet
+ .createValueSemanticsContext(feature.getFeatureIdentifier());
+
+ return valueFacet.selectParserForFeatureElseFallback(feature)
+ .parseableTextRepresentation(context, value);
+ }
+
+ // -- HELPER
+
+ @Synchronized
+ private ObjectFeature feature() {
+ if(propOrParam==null) {
+ val typeSpec = getSpecificationLoader().specForLogicalTypeElseFail(featureIdentifier.getLogicalType());
+ val member = typeSpec.getMemberElseFail(featureIdentifier.getMemberLogicalName());
+ this.propOrParam = this.paramIndex<0
+ ? _Either.left((OneToOneAssociation)member)
+ : _Either.right(((ObjectAction)member).getParameters().getElseFail(paramIndex));
+ }
+ return propOrParam.fold(
+ ObjectFeature.class::cast,
+ ObjectFeature.class::cast);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ValueFacet<T> valueFacet() {
+
+ val feature = feature();
+ val valueFacet = feature.getElementType()
+ .lookupFacet(ValueFacet.class)
+ .orElseThrow(()->_Exceptions.noSuchElement(
+ "Value type Property or Parameter %s is missing a ValueFacet",
+ feature.getFeatureIdentifier()));
+
+ return valueFacet;
+ }
+
+ // -- DEPENDENCIES
+
+ @Override
+ public IsisAppCommonContext getCommonContext() {
+ return commonContext = CommonContextUtils.computeIfAbsent(commonContext);
+ }
+
+}
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/IsisConverterLocator.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/IsisConverterLocator.java
index 969b07d..2ab8fd7 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/IsisConverterLocator.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/IsisConverterLocator.java
@@ -23,6 +23,7 @@ import org.apache.wicket.IConverterLocator;
import org.apache.wicket.util.convert.IConverter;
import org.apache.wicket.util.convert.converter.BigIntegerConverter;
+import org.apache.isis.applib.adapters.ValueSemanticsProvider;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.core.metamodel.facets.objectvalue.maxlen.MaxFractionalDigitsFacet;
@@ -41,7 +42,9 @@ import lombok.val;
/**
* A locator for IConverters for ObjectAdapters
+ * @deprecated instead use {@link ValueSemanticsProvider}
*/
+@Deprecated(forRemoval = true, since = "2.0.0-M7")
public class IsisConverterLocator {
/**
diff --git a/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java b/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java
index 554fcdb..98b8040 100644
--- a/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java
+++ b/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/components/scalars/jdkmath/BigDecimalConverterWithScaleTest_roundtrip.java
@@ -22,13 +22,14 @@ import java.math.BigDecimal;
import java.util.Locale;
import org.apache.wicket.util.convert.ConversionException;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
-public class BigDecimalConverterWithScaleTest_roundtrip {
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+class BigDecimalConverterWithScaleTest_roundtrip {
final BigDecimal bd_123_45_scale2 = new BigDecimal("123.45").setScale(2);
final BigDecimal bd_123_4500_scale2 = new BigDecimal("123.4500").setScale(2);
@@ -40,104 +41,97 @@ public class BigDecimalConverterWithScaleTest_roundtrip {
private BigDecimalConverterWithScale converter;
- @Rule
- public ExpectedException exception = ExpectedException.none();
-
- @Before
- public void setUp() throws Exception {
+ @BeforeEach
+ void setUp() throws Exception {
converter = newConverter(2);
}
@Test
- public void scale2_english() {
+ void scale2_english() {
// when
final BigDecimal actual = converter.convertToObject("123.45", Locale.ENGLISH);
- Assert.assertEquals(bd_123_4500_scale2, actual);
- Assert.assertEquals(bd_123_45_scale2, actual);
+ assertEquals(bd_123_4500_scale2, actual);
+ assertEquals(bd_123_45_scale2, actual);
- Assert.assertNotEquals(bd_123_4500_scale4, actual);
- Assert.assertNotEquals(bd_123_45_scale4, actual);
+ assertNotEquals(bd_123_4500_scale4, actual);
+ assertNotEquals(bd_123_45_scale4, actual);
// when
String actualStr = converter.convertToString(actual, Locale.ENGLISH);
- Assert.assertEquals("123.45", actualStr);
+ assertEquals("123.45", actualStr);
}
@Test
- public void scale4_english() {
+ void scale4_english() {
converter = newConverter(4);
final BigDecimal actual = converter.convertToObject("123.45", Locale.ENGLISH);
- Assert.assertNotEquals(bd_123_4500_scale2, actual);
- Assert.assertNotEquals(bd_123_45_scale2, actual);
+ assertNotEquals(bd_123_4500_scale2, actual);
+ assertNotEquals(bd_123_45_scale2, actual);
- Assert.assertEquals(bd_123_4500_scale4, actual);
- Assert.assertEquals(bd_123_45_scale4, actual);
+ assertEquals(bd_123_4500_scale4, actual);
+ assertEquals(bd_123_45_scale4, actual);
// when
String actualStr = converter.convertToString(actual, Locale.ENGLISH);
- Assert.assertEquals("123.4500", actualStr);
+ assertEquals("123.4500", actualStr);
}
@Test
- public void scaleNull_english() {
+ void scaleNull_english() {
converter = newConverter(null);
final BigDecimal actual = converter.convertToObject("123.45", Locale.ENGLISH);
- Assert.assertEquals(bd_123_4500_scale2, actual);
- Assert.assertEquals(bd_123_45_scale2, actual);
+ assertEquals(bd_123_4500_scale2, actual);
+ assertEquals(bd_123_45_scale2, actual);
final BigDecimal actual2 = converter.convertToObject("123.4500", Locale.ENGLISH);
- Assert.assertEquals(bd_123_4500_scale4, actual2);
- Assert.assertEquals(bd_123_45_scale4, actual2);
+ assertEquals(bd_123_4500_scale4, actual2);
+ assertEquals(bd_123_45_scale4, actual2);
}
@Test
- public void scale2_italian() {
+ void scale2_italian() {
final BigDecimal actual = converter.convertToObject("123,45", Locale.ITALIAN);
- Assert.assertEquals(bd_123_4500_scale2, actual);
- Assert.assertEquals(bd_123_45_scale2, actual);
+ assertEquals(bd_123_4500_scale2, actual);
+ assertEquals(bd_123_45_scale2, actual);
- Assert.assertNotEquals(bd_123_4500_scale4, actual);
- Assert.assertNotEquals(bd_123_45_scale4, actual);
+ assertNotEquals(bd_123_4500_scale4, actual);
+ assertNotEquals(bd_123_45_scale4, actual);
}
@Test
- public void scale2_english_withThousandSeparators() {
-
- exception.expect(ConversionException.class);
- exception.expectMessage("Thousands separator ',' is not allowed in input");
-
- converter.convertToObject("789,123.45", Locale.ENGLISH);
+ void scale2_english_withThousandSeparators() {
+ assertThrows(ConversionException.class, ()->
+ converter.convertToObject("789,123.45", Locale.ENGLISH),
+ "Thousands separator ',' is not allowed in input");
}
@Test
- public void scale2_english_withoutThousandSeparators() {
+ void scale2_english_withoutThousandSeparators() {
// when
final BigDecimal actual = converter.convertToObject("789123.45", Locale.ENGLISH);
- Assert.assertEquals(bd_789123_45_scale2, actual);
+ assertEquals(bd_789123_45_scale2, actual);
// when
String actualStr = converter.convertToString(actual, Locale.ENGLISH);
- Assert.assertEquals("789123.45", actualStr);
+ assertEquals("789123.45", actualStr);
}
@Test
- public void scale2_english_tooLargeScale() {
-
- exception.expect(ConversionException.class);
- exception.expectMessage("No more than 2 digits can be entered after the decimal place");
-
- converter.convertToObject("123.454", Locale.ENGLISH);
+ void scale2_english_tooLargeScale() {
+ assertThrows(ConversionException.class, ()->
+ converter.convertToObject("123.454", Locale.ENGLISH),
+ "No more than 2 digits can be entered after the decimal place");
}
- private BigDecimalConverterWithScale newConverter(Integer scale) {
+ private BigDecimalConverterWithScale newConverter(final Integer scale) {
return new BigDecimalConverterWithScale(scale);
}