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 2022/02/02 16:30:15 UTC
[isis] 02/02: ISIS-2877: use ValueComposer on all remaining types
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
commit 19a1c46a5f25639c0947b459ecceb75197bff458
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Feb 2 17:29:57 2022 +0100
ISIS-2877: use ValueComposer on all remaining types
---
.../isis/applib/util/schema/CommonDtoUtils.java | 92 +++++++++++++++++++++-
.../isis/applib/value/semantics/ValueComposer.java | 18 +++++
.../value/semantics/ValueSemanticsAbstract.java | 10 +--
.../value/semantics/ValueSemanticsProvider.java | 5 --
.../isis/commons/internal/base/_NullSafe.java | 9 +++
.../encoder/EncodableFacetFromValueFacet.java | 32 +++++---
.../metamodel/facets/object/value/ValueFacet.java | 6 --
.../facets/object/value/ValueFacetAbstract.java | 13 ---
.../value/vsp/ValueSemanticsFacetAbstract.java | 6 --
.../identify/ObjectBookmarker_builtinHandlers.java | 11 +--
.../schema/SchemaValueMarshallerAbstract.java | 4 +-
.../BufferedImageValueSemantics.java | 64 +++++++++++----
.../valuesemantics/CharacterValueSemantics.java | 25 ++++--
.../valuesemantics/EnumValueSemanticsAbstract.java | 29 ++++---
.../valuesemantics/PasswordValueSemantics.java | 22 +++---
.../value/CharacterValueSemanticsProviderTest.java | 15 ++--
.../value/PasswordValueSemanticsProviderTest.java | 16 +++-
.../ValueSemanticsProviderAbstractTestCase.java | 6 +-
.../jdo/ComplexNumberJdoValueSemantics.java | 74 ++++++++++-------
.../jpa/ComplexNumberJpaValueSemantics.java | 74 ++++++++++-------
.../testdomain/value/ValueSemanticsTester.java | 16 +---
.../rendering/domainobjects/JsonValueEncoder.java | 23 ++++--
22 files changed, 370 insertions(+), 200 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java b/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
index 17c56b9..89aa9e8 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
@@ -40,9 +40,11 @@ import org.apache.isis.applib.value.Clob;
import org.apache.isis.applib.value.semantics.ValueComposer.ValueDecomposition;
import org.apache.isis.commons.internal.assertions._Assert;
import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.context._Context;
import org.apache.isis.commons.internal.exceptions._Exceptions;
+import org.apache.isis.commons.internal.resources._Json;
import org.apache.isis.schema.cmd.v2.MapDto;
import org.apache.isis.schema.cmd.v2.ParamDto;
import org.apache.isis.schema.common.v2.BlobDto;
@@ -66,10 +68,96 @@ import lombok.experimental.UtilityClass;
@UtilityClass
public final class CommonDtoUtils {
+ // -- VALUE EXTRACT
+
+ public String getFundamentalValueAsJson(
+ final @Nullable ValueWithTypeDto valueDto) {
+ if(valueDto==null) {
+ return null;
+ }
+ return getFundamentalValueAsJson(valueDto.getType(),valueDto);
+ }
+
+ @SneakyThrows
+ public String getFundamentalValueAsJson(
+ final @NonNull ValueType valueType,
+ final @Nullable ValueDto valueDto) {
+
+ _NullSafe.toString(7);
+
+ if(valueDto==null) {
+ return null;
+ }
+ switch(valueType) {
+ case REFERENCE:
+ case COMPOSITE:
+ case COLLECTION:
+ throw _Exceptions.unsupportedOperation("valueType %s is not fundamental", valueType);
+
+ case STRING:
+ return valueDto.getString();
+ case BYTE:
+ return _NullSafe.toString(valueDto.getByte());
+ case SHORT:
+ return _NullSafe.toString(valueDto.getShort());
+ case INT:
+ return _NullSafe.toString(valueDto.getInt());
+ case LONG:
+ return _NullSafe.toString(valueDto.getLong());
+ case FLOAT:
+ return _NullSafe.toString(valueDto.getFloat());
+ case DOUBLE:
+ return _NullSafe.toString(valueDto.getDouble());
+ case BOOLEAN:
+ return _NullSafe.toString(valueDto.isBoolean());
+ case CHAR:
+ final String aChar = valueDto.getChar();
+ if(_Strings.isNullOrEmpty(aChar)) { return null; }
+ return ""+aChar.charAt(0);
+ case BIG_DECIMAL:
+ return _NullSafe.toString(valueDto.getBigDecimal());
+ case BIG_INTEGER:
+ return _NullSafe.toString(valueDto.getBigInteger());
+ case LOCAL_DATE:
+ return _NullSafe.toString(valueDto.getLocalDate());
+ case LOCAL_TIME:
+ return _NullSafe.toString(valueDto.getLocalTime());
+ case LOCAL_DATE_TIME:
+ return _NullSafe.toString(valueDto.getLocalDateTime());
+ case OFFSET_DATE_TIME:
+ return _NullSafe.toString(valueDto.getOffsetDateTime());
+ case OFFSET_TIME:
+ return _NullSafe.toString(valueDto.getOffsetTime());
+ case ZONED_DATE_TIME:
+ return _NullSafe.toString(valueDto.getZonedDateTime());
+ case ENUM:
+ final EnumDto enumDto = valueDto.getEnum();
+ final String enumType = enumDto.getEnumType();
+ @SuppressWarnings("rawtypes")
+ final Class<? extends Enum> enumClass =
+ _Casts.uncheckedCast(_Context.loadClassAndInitialize(enumType));
+ return Enum.valueOf(_Casts.uncheckedCast(enumClass), enumDto.getEnumName()).name();
+ case BLOB:
+ final BlobDto blobDto = valueDto.getBlob();
+ return blobDto!=null
+ ? _Json.toString(blobDto).presentElseFail()
+ : null;
+ case CLOB:
+ final ClobDto clobDto = valueDto.getClob();
+ return clobDto!=null
+ ? _Json.toString(clobDto).presentElseFail()
+ : null;
+ case VOID:
+ return null;
+ default:
+ throw _Exceptions.unmatchedCase(valueType);
+ }
+ }
+
// -- VALUE RECORD
- public <D extends ValueDto, T> D recordFundamentalValue(
- final @NonNull ValueType valueType,
+ public <D extends ValueDto> D recordFundamentalValue(
+ final @NonNull ValueType valueType,
final D valueDto,
final Object pojo) {
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueComposer.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueComposer.java
index 21f7665..4fc42b9 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueComposer.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueComposer.java
@@ -18,7 +18,9 @@
*/
package org.apache.isis.applib.value.semantics;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.commons.internal.base._Either;
+import org.apache.isis.commons.internal.resources._Json;
import org.apache.isis.schema.common.v2.TypedTupleDto;
import org.apache.isis.schema.common.v2.ValueWithTypeDto;
@@ -51,6 +53,22 @@ public interface ValueComposer<T> {
private ValueDecomposition(final ValueWithTypeDto left, final TypedTupleDto right) {
super(left, right);
}
+
+ // used by RO-Viewer to render values
+ public String toJson() {
+ return this.<String>fold(
+ fundamental->CommonDtoUtils.getFundamentalValueAsJson(fundamental),
+ composite->composite!=null
+ ? _Json.toString(composite).presentElseFail()
+ : null);
+ }
+
+ // used by EncodableFacet
+ public static ValueDecomposition fromJson(final String encodedData) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
/**
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
index c85c136..00b996f 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsAbstract.java
@@ -86,11 +86,11 @@ implements
return this instanceof Renderer ? (Renderer<T>)this : null;
}
- @SuppressWarnings("unchecked")
- @Override
- public EncoderDecoder<T> getEncoderDecoder() {
- return this instanceof EncoderDecoder ? (EncoderDecoder<T>)this : null;
- }
+// @SuppressWarnings("unchecked")
+// @Override
+// public EncoderDecoder<T> getEncoderDecoder() {
+// return this instanceof EncoderDecoder ? (EncoderDecoder<T>)this : null;
+// }
@SuppressWarnings("unchecked")
@Override
diff --git a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsProvider.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsProvider.java
index 54b4a37..fb2f28b 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsProvider.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/ValueSemanticsProvider.java
@@ -91,11 +91,6 @@ public interface ValueSemanticsProvider<T> {
Parser<T> getParser();
/**
- * The {@link EncoderDecoder}, if any.
- */
- EncoderDecoder<T> getEncoderDecoder();
-
- /**
* The {@link DefaultsProvider}, if any.
*
* <p>
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java b/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java
index 72d8ff2..469c14c 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/base/_NullSafe.java
@@ -302,6 +302,13 @@ public final class _NullSafe {
public static int size(final @Nullable short[] array){ return array!=null ? array.length : 0; }
public static <T> int size(final @Nullable T[] array){ return array!=null ? array.length : 0; }
+ // -- TO STRING
+
+ public static String toString(final @Nullable Object obj) {
+ return obj!=null
+ ? obj.toString()
+ : null;
+ }
// -- MAP
@@ -336,4 +343,6 @@ public final class _NullSafe {
: map.entrySet();
}
+
+
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/encodeable/encoder/EncodableFacetFromValueFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/encodeable/encoder/EncodableFacetFromValueFacet.java
index 1f8cd1b..2677a97 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/encodeable/encoder/EncodableFacetFromValueFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/encodeable/encoder/EncodableFacetFromValueFacet.java
@@ -21,7 +21,8 @@ package org.apache.isis.core.metamodel.facets.object.encodeable.encoder;
import java.util.Optional;
import java.util.function.BiConsumer;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
+import org.apache.isis.applib.value.semantics.ValueComposer;
+import org.apache.isis.applib.value.semantics.ValueComposer.ValueDecomposition;
import org.apache.isis.commons.internal.assertions._Assert;
import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -29,6 +30,8 @@ import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
import org.apache.isis.core.metamodel.spec.ManagedObject;
+import lombok.val;
+
public class EncodableFacetFromValueFacet
extends FacetAbstract
implements EncodableFacet {
@@ -37,24 +40,25 @@ implements EncodableFacet {
public static final String ENCODED_NULL = "NULL";
public static Optional<EncodableFacet> create(final ValueFacet<?> valueFacet, final FacetHolder holder) {
- return valueFacet.selectDefaultEncoderDecoder()
- .map(encoderDecoder->new EncodableFacetFromValueFacet(encoderDecoder, holder));
+ return valueFacet.selectDefaultComposer()
+ .map(composer->new EncodableFacetFromValueFacet(composer, holder));
}
/**
* JUnit support.
*/
- public static EncodableFacetFromValueFacet forTesting(final EncoderDecoder<?> encoderDecoder, final FacetHolder holder) {
- return new EncodableFacetFromValueFacet(encoderDecoder, holder);
+ public static EncodableFacetFromValueFacet forTesting(
+ final ValueComposer<?> composer, final FacetHolder holder) {
+ return new EncodableFacetFromValueFacet(composer, holder);
}
// -- CONSTRUCTION
- private final EncoderDecoder<?> encoderDecoder;
+ private final ValueComposer<?> composer;
- private EncodableFacetFromValueFacet(final EncoderDecoder<?> encoderDecoder, final FacetHolder holder) {
+ private EncodableFacetFromValueFacet(final ValueComposer<?> encoderDecoder, final FacetHolder holder) {
super(EncodableFacet.class, holder);
- this.encoderDecoder = encoderDecoder;
+ this.composer = encoderDecoder;
}
@Override
@@ -63,7 +67,7 @@ implements EncodableFacet {
if (ENCODED_NULL.equals(encodedData)) {
return null;
} else {
- final Object decodedObject = encoderDecoder.fromEncodedString(encodedData);
+ final Object decodedObject = composer.compose(ValueDecomposition.fromJson(encodedData));
return getObjectManager().adapt(decodedObject);
}
}
@@ -72,21 +76,23 @@ implements EncodableFacet {
public String toEncodedString(final ManagedObject adapter) {
return adapter == null
? ENCODED_NULL
- : encode(encoderDecoder, adapter.getPojo());
+ : encode(composer, adapter.getPojo());
}
@Override
public void visitAttributes(final BiConsumer<String, Object> visitor) {
super.visitAttributes(visitor);
- visitor.accept("codec", encoderDecoder.toString());
+ visitor.accept("composer", composer.toString());
}
// -- HELPER
- private static <T> String encode(final EncoderDecoder<T> encoderDecoder, final Object pojo) {
+ private static <T> String encode(final ValueComposer<T> composer, final Object pojo) {
@SuppressWarnings("unchecked")
T pojoAsT = (T) pojo;
- return encoderDecoder.toEncodedString(pojoAsT);
+ val valueAsJson = composer.decompose(pojoAsT)
+ .toJson();
+ return valueAsJson;
}
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 2ca7786..976aa0d 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
@@ -26,7 +26,6 @@ import org.springframework.lang.Nullable;
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.id.LogicalType;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.OrderRelation;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
@@ -74,11 +73,6 @@ public interface ValueFacet<T> extends Facet {
/** no qualifiers allowed on the default semantics provider*/
Optional<DefaultsProvider<T>> selectDefaultDefaultsProvider();
- // -- ENCODER DECODER
-
- /** no qualifiers allowed on the default semantics provider*/
- Optional<EncoderDecoder<T>> selectDefaultEncoderDecoder();
-
// -- COMPOSER
/** no qualifiers allowed on the default semantics provider*/
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 6a9f1b7..e5a9497 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
@@ -28,7 +28,6 @@ import org.springframework.lang.Nullable;
import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.id.LogicalType;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.OrderRelation;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
@@ -134,18 +133,6 @@ implements ValueFacet<T> {
.findFirst();
}
- // -- ENCODER DECODER
-
- @Override
- public Optional<EncoderDecoder<T>> selectDefaultEncoderDecoder() {
- return getValueSemantics()
- .stream()
- .filter(isMatchingAnyOf(Can.empty()))
- .map(ValueSemanticsProvider::getEncoderDecoder)
- .filter(_NullSafe::isPresent)
- .findFirst();
- }
-
// -- COMPOSER
@Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueSemanticsFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueSemanticsFacetAbstract.java
index d7e8158..12ff50c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueSemanticsFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/vsp/ValueSemanticsFacetAbstract.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.metamodel.facets.object.value.vsp;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
import org.apache.isis.core.metamodel.facetapi.Facet;
@@ -59,11 +58,6 @@ implements ValueSemanticsProvider<T> {
}
@Override
- public final EncoderDecoder<T> getEncoderDecoder() {
- return valueSemantics.getEncoderDecoder();
- }
-
- @Override
public final DefaultsProvider<T> getDefaultsProvider() {
return valueSemantics.getDefaultsProvider();
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java
index 4fddfc3..1c7276f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/identify/ObjectBookmarker_builtinHandlers.java
@@ -25,7 +25,7 @@ import java.util.UUID;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.bookmark.Oid;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.commons.internal.base._Bytes;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.debug._Debug;
@@ -151,16 +151,17 @@ class ObjectBookmarker_builtinHandlers {
}
val valueFacet = spec.getFacet(ValueFacet.class);
- EncoderDecoder<Object> codec = (EncoderDecoder) valueFacet.selectDefaultEncoderDecoder()
+ ValueComposer<Object> composer = (ValueComposer) valueFacet.selectDefaultComposer()
.orElseThrow(()->_Exceptions.illegalArgument(
"Cannot create a bookmark for the value type %s, "
- + "as no appropriate EncoderDecoder could be found.",
+ + "as no appropriate ValueComposer could be found.",
managedObject.getSpecification().getCorrespondingClass().getName()));
- val encoded = codec.toEncodedString(managedObject.getPojo()).getBytes();
+ val valueAsJson = composer.decompose(managedObject.getPojo())
+ .toJson();
val identifier = _Strings.ofBytes(
- _Bytes.asUrlBase64.apply(encoded),
+ _Bytes.asUrlBase64.apply(valueAsJson.getBytes()),
StandardCharsets.UTF_8);
return Bookmark.forLogicalTypeAndIdentifier(spec.getLogicalType(), identifier);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/schema/SchemaValueMarshallerAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/schema/SchemaValueMarshallerAbstract.java
index f1c9343..a0ab3ae 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/schema/SchemaValueMarshallerAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/schema/SchemaValueMarshallerAbstract.java
@@ -81,9 +81,7 @@ implements SchemaValueMarshaller {
&& !semantics.getCorrespondingClass().equals(String.class);
return of(correspondingClass, feature, Optional.ofNullable(semantics),
- supportsConversionViaEncoderDecoder
- ? Optional.ofNullable(semantics.getEncoderDecoder())
- : Optional.empty(),
+ Optional.empty(),
semantics!=null
? Optional.ofNullable(semantics.getConverter())
: Optional.empty(),
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BufferedImageValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BufferedImageValueSemantics.java
index 840ca01..b79ee92 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BufferedImageValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BufferedImageValueSemantics.java
@@ -26,15 +26,18 @@ import javax.inject.Named;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
+import org.apache.isis.applib.value.Blob;
+import org.apache.isis.applib.value.NamedWithMimeType.CommonMimeType;
import org.apache.isis.applib.value.semantics.OrderRelation;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.image._Images;
import org.apache.isis.core.metamodel.spec.ManagedObject;
import org.apache.isis.core.metamodel.spec.ManagedObjects;
+import org.apache.isis.schema.common.v2.BlobDto;
import org.apache.isis.schema.common.v2.ValueType;
+import org.apache.isis.schema.common.v2.ValueWithTypeDto;
@Component
@Named("isis.val.BufferedImageValueSemantics")
@@ -43,7 +46,7 @@ extends ValueSemanticsAbstract<BufferedImage>
implements
ImageValueSemantics,
OrderRelation<BufferedImage, Void>,
- EncoderDecoder<BufferedImage> {
+ ValueComposer<BufferedImage> {
@Override
public Class<BufferedImage> getCorrespondingClass() {
@@ -52,7 +55,7 @@ implements
@Override
public ValueType getSchemaValueType() {
- return UNREPRESENTED;
+ return ValueType.BLOB;
}
// -- ORDER RELATION
@@ -72,26 +75,53 @@ implements
return compare(a, b, epsilon) == 0;
}
- // -- ENCODER DECODER
+ // -- COMPOSER
@Override
- public String toEncodedString(final @Nullable BufferedImage image) {
- if(image==null) {
- return null;
- }
- return _Images.toBase64(image);
+ public ValueDecomposition decompose(final BufferedImage value) {
+ return decomposeAsNullable(value, this::toBlob, ()->null);
}
@Override
- public BufferedImage fromEncodedString(final @Nullable String base64ImageData) {
- if(_Strings.isNullOrEmpty(base64ImageData)) {
- return null;
- }
- /*sonar-ignore-on*/
- return _Images.fromBase64(base64ImageData);
- /*sonar-ignore-off*/
+ public BufferedImage compose(final ValueDecomposition decomposition) {
+ return composeFromNullable(
+ decomposition, ValueWithTypeDto::getBlob, this::fromBlobDto, ()->null);
+ }
+
+ private BufferedImage fromBlobDto(final BlobDto blobDto) {
+ return blobDto!=null
+ && blobDto.getBytes()!=null
+ ? _Images.fromBytes(blobDto.getBytes())
+ : null;
+ }
+
+ private Blob toBlob(final BufferedImage img) {
+ return img!=null
+ // arbitrary name and mimetype - not used when recovering the image
+ ? new Blob("image", CommonMimeType.PNG.getBaseType(), _Images.toBytes(img))
+ : null;
}
+ // -- ENCODER DECODER
+
+// @Override
+// public String toEncodedString(final @Nullable BufferedImage image) {
+// if(image==null) {
+// return null;
+// }
+// return _Images.toBase64(image);
+// }
+//
+// @Override
+// public BufferedImage fromEncodedString(final @Nullable String base64ImageData) {
+// if(_Strings.isNullOrEmpty(base64ImageData)) {
+// return null;
+// }
+// /*sonar-ignore-on*/
+// return _Images.fromBase64(base64ImageData);
+// /*sonar-ignore-off*/
+// }
+
// -- FACET
@Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/CharacterValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/CharacterValueSemantics.java
index 3b00f28..56765a8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/CharacterValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/CharacterValueSemantics.java
@@ -18,18 +18,21 @@
*/
package org.apache.isis.core.metamodel.valuesemantics;
+import java.util.function.UnaryOperator;
+
import javax.inject.Named;
import org.springframework.stereotype.Component;
import org.apache.isis.applib.exceptions.recoverable.InvalidEntryException;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.schema.common.v2.ValueDto;
import org.apache.isis.schema.common.v2.ValueType;
import lombok.val;
@@ -43,7 +46,7 @@ public class CharacterValueSemantics
extends ValueSemanticsAbstract<Character>
implements
DefaultsProvider<Character>,
- EncoderDecoder<Character>,
+ ValueComposer<Character>,
Parser<Character>,
Renderer<Character> {
@@ -62,16 +65,24 @@ implements
return (char) 0;
}
- // -- ENCODER DECODER
+ // -- COMPOSER
@Override
- public String toEncodedString(final Character object) {
- return object.toString();
+ public ValueDecomposition decompose(final Character value) {
+ return decomposeAsNullable(value, UnaryOperator.identity(), ()->null);
}
@Override
- public Character fromEncodedString(final String data) {
- return Character.valueOf(data.charAt(0));
+ public Character compose(final ValueDecomposition decomposition) {
+ return composeFromNullable(
+ decomposition, ValueDto::getChar, this::fromString, ()->null);
+ }
+
+ private Character fromString(final String data) {
+ return data!=null
+ && data.length()>0
+ ? Character.valueOf(data.charAt(0))
+ : null;
}
// -- RENDERER
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java
index 95fb8c9..f626154 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/EnumValueSemanticsAbstract.java
@@ -19,6 +19,7 @@
package org.apache.isis.core.metamodel.valuesemantics;
import java.lang.reflect.Method;
+import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import org.apache.isis.applib.annotation.Introspection.IntrospectionPolicy;
@@ -28,9 +29,9 @@ import org.apache.isis.applib.services.i18n.TranslationContext;
import org.apache.isis.applib.services.i18n.TranslationService;
import org.apache.isis.applib.util.Enums;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
import org.apache.isis.commons.collections.Can;
@@ -39,7 +40,9 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.config.progmodel.ProgrammingModelConstants.ObjectSupportMethod;
import org.apache.isis.core.metamodel.commons.MethodExtensions;
import org.apache.isis.core.metamodel.methods.MethodFinder;
+import org.apache.isis.schema.common.v2.EnumDto;
import org.apache.isis.schema.common.v2.ValueType;
+import org.apache.isis.schema.common.v2.ValueWithTypeDto;
import lombok.Getter;
import lombok.val;
@@ -49,7 +52,7 @@ public class EnumValueSemanticsAbstract<T extends Enum<T>>
extends ValueSemanticsAbstract<T>
implements
DefaultsProvider<T>,
- EncoderDecoder<T>,
+ ValueComposer<T>,
Parser<T>,
Renderer<T> {
@@ -108,23 +111,31 @@ implements
return correspondingClass.getEnumConstants()[0];
}
- // -- ENCODER/DECODER
+ // -- COMPOSER
@Override
- public String toEncodedString(final T object) {
- return object!=null ? object.name() : null;
+ public ValueDecomposition decompose(final T value) {
+ return decomposeAsNullable(value, UnaryOperator.identity(), ()->null);
}
@Override
- public T fromEncodedString(final String data) {
- return data!=null
+ public T compose(final ValueDecomposition decomposition) {
+ return composeFromNullable(
+ decomposition, ValueWithTypeDto::getEnum, this::fromEnumName, ()->null);
+ }
+
+ private T fromEnumName(final EnumDto enumDto) {
+
+ val enumName = enumDto.getEnumName();
+
+ return enumName!=null
? Stream.of(correspondingClass.getEnumConstants())
- .filter(e->e.name().equals(data))
+ .filter(e->e.name().equals(enumName))
.findFirst()
.orElseThrow(()->_Exceptions
.noSuchElement("enum %s has no matching %s",
correspondingClass.getName(),
- data))
+ enumName))
: null;
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
index 9202ad2..4a1f7e4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/PasswordValueSemantics.java
@@ -23,20 +23,21 @@ import javax.inject.Named;
import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.Password;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.schema.common.v2.ValueType;
+import org.apache.isis.schema.common.v2.ValueWithTypeDto;
@Component
@Named("isis.val.PasswordValueSemantics")
public class PasswordValueSemantics
extends ValueSemanticsAbstract<Password>
implements
- EncoderDecoder<Password>,
+ ValueComposer<Password>,
Parser<Password>,
Renderer<Password> {
@@ -50,22 +51,17 @@ implements
return ValueType.STRING;
}
- // -- ENCODER DECODER
+ // -- COMPOSER
@Override
- public String toEncodedString(final Password value) {
- if(value==null) {
- return null;
- }
- return value.getPassword();
+ public ValueDecomposition decompose(final Password value) {
+ return decomposeAsNullable(value, Password::getPassword, ()->null);
}
@Override
- public Password fromEncodedString(final String data) {
- if(data==null) {
- return null;
- }
- return new Password(data);
+ public Password compose(final ValueDecomposition decomposition) {
+ return composeFromNullable(
+ decomposition, ValueWithTypeDto::getString, Password::new, ()->null);
}
// -- RENDERER
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/CharacterValueSemanticsProviderTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/CharacterValueSemanticsProviderTest.java
index f5dde9c..44e7068 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/CharacterValueSemanticsProviderTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/CharacterValueSemanticsProviderTest.java
@@ -25,25 +25,26 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import org.apache.isis.applib.exceptions.recoverable.InvalidEntryException;
+import org.apache.isis.applib.value.semantics.ValueComposer.ValueDecomposition;
import org.apache.isis.core.metamodel.valuesemantics.CharacterValueSemantics;
public class CharacterValueSemanticsProviderTest
extends ValueSemanticsProviderAbstractTestCase {
- private CharacterValueSemantics value;
+ private CharacterValueSemantics valueSemantics;
private Character character;
@Before
public void setUpObjects() throws Exception {
character = Character.valueOf('r');
- setSemantics(value = new CharacterValueSemantics());
+ setSemantics(valueSemantics = new CharacterValueSemantics());
}
@Test
public void testParseLongString() throws Exception {
try {
- value.parseTextRepresentation(null, "one");
+ valueSemantics.parseTextRepresentation(null, "one");
fail();
} catch (final InvalidEntryException expected) {
}
@@ -51,23 +52,23 @@ extends ValueSemanticsProviderAbstractTestCase {
@Test
public void testTitleOf() {
- assertEquals("r", value.simpleTextPresentation(null, character));
+ assertEquals("r", valueSemantics.simpleTextPresentation(null, character));
}
@Test
public void testValidParse() throws Exception {
- final Object parse = value.parseTextRepresentation(null, "t");
+ final Object parse = valueSemantics.parseTextRepresentation(null, "t");
assertEquals(Character.valueOf('t'), parse);
}
@Test
public void testEncode() throws Exception {
- assertEquals("r", value.toEncodedString(character));
+ assertEquals("r", valueSemantics.decompose(character).toJson());
}
@Test
public void testDecode() throws Exception {
- final Object restore = value.fromEncodedString("Y");
+ final Object restore = valueSemantics.compose(ValueDecomposition.fromJson("Y"));
assertEquals(Character.valueOf('Y'), restore);
}
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/PasswordValueSemanticsProviderTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/PasswordValueSemanticsProviderTest.java
index 4f94cd0..837fccf 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/PasswordValueSemanticsProviderTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/PasswordValueSemanticsProviderTest.java
@@ -24,22 +24,30 @@ import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.apache.isis.applib.value.Password;
+import org.apache.isis.applib.value.semantics.ValueComposer.ValueDecomposition;
import org.apache.isis.core.metamodel.valuesemantics.PasswordValueSemantics;
public class PasswordValueSemanticsProviderTest
extends ValueSemanticsProviderAbstractTestCase {
- private PasswordValueSemantics adapter;
+ private PasswordValueSemantics valueSemantics;
private Password password;
@Before
public void setUpObjects() throws Exception {
- setSemantics(adapter = new PasswordValueSemantics());
+ setSemantics(valueSemantics = new PasswordValueSemantics());
password = new Password("secret");
}
@Test
- public void testEncoding() {
- assertEquals("secret", adapter.toEncodedString(password));
+ public void testEncode() throws Exception {
+ assertEquals("secret", valueSemantics.decompose(password).toJson());
}
+
+ @Test
+ public void testDecode() throws Exception {
+ final Object restore = valueSemantics.compose(ValueDecomposition.fromJson("secret"));
+ assertEquals(password, restore);
+ }
+
}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
index a25f2e4..c72d766 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/value/ValueSemanticsProviderAbstractTestCase.java
@@ -100,7 +100,7 @@ public abstract class ValueSemanticsProviderAbstractTestCase {
protected void setSemantics(final ValueSemanticsAbstract<?> valueSemantics) {
this.valueSemanticsProvider = valueSemantics;
this.encodeableFacet = EncodableFacetFromValueFacet.forTesting(
- valueSemantics.getEncoderDecoder(),
+ valueSemantics.getComposer(),
mockFacetHolder);
}
@@ -135,7 +135,7 @@ public abstract class ValueSemanticsProviderAbstractTestCase {
@Test
public void testDecodeNULL() throws Exception {
- Assume.assumeThat(valueSemanticsProvider.getEncoderDecoder(), is(not(nullValue())));
+ Assume.assumeThat(valueSemanticsProvider.getComposer(), is(not(nullValue())));
final Object newValue = encodeableFacet.fromEncodedString(EncodableFacetFromValueFacet.ENCODED_NULL);
assertNull(newValue);
@@ -143,7 +143,7 @@ public abstract class ValueSemanticsProviderAbstractTestCase {
@Test
public void testEmptyEncoding() {
- Assume.assumeThat(valueSemanticsProvider.getEncoderDecoder(), is(not(nullValue())));
+ Assume.assumeThat(valueSemanticsProvider.getComposer(), is(not(nullValue())));
assertEquals(EncodableFacetFromValueFacet.ENCODED_NULL, encodeableFacet.toEncodedString(null));
}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jdo/ComplexNumberJdoValueSemantics.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jdo/ComplexNumberJdoValueSemantics.java
index 9526f2a..ca8fe16 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jdo/ComplexNumberJdoValueSemantics.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jdo/ComplexNumberJdoValueSemantics.java
@@ -18,22 +18,17 @@
*/
package demoapp.dom.domain.objects.other.embedded.jdo;
-import java.util.stream.Collectors;
-
import org.springframework.stereotype.Component;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
-import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.schema.common.v2.ValueType;
-import lombok.val;
-
// tag::class[]
@Component
public class ComplexNumberJdoValueSemantics
@@ -90,36 +85,55 @@ public class ComplexNumberJdoValueSemantics
// tag::getEncoderDecoder[]
@Override
- public EncoderDecoder<ComplexNumberJdo> getEncoderDecoder() {
+ public ValueComposer<ComplexNumberJdo> getComposer() {
// end::getEncoderDecoder[]
// ...
// tag::getEncoderDecoder[]
- return new EncoderDecoder<ComplexNumberJdo>() {
+ return new ValueComposer<ComplexNumberJdo>() {
+
@Override
- public String toEncodedString(final ComplexNumberJdo cn) {
- if(cn==null) {
- return null;
- }
- val re = Double.doubleToLongBits(cn.getRe());
- val im = Double.doubleToLongBits(cn.getIm());
- return String.format("%s:%s",
- Long.toHexString(re), Long.toHexString(im));
+ public ValueDecomposition decompose(final ComplexNumberJdo value) {
+ return CommonDtoUtils.typedTupleBuilder(value)
+ .addFundamentalType(ValueType.DOUBLE, "re", ComplexNumberJdo::getRe)
+ .addFundamentalType(ValueType.DOUBLE, "im", ComplexNumberJdo::getIm)
+ .buildAsDecomposition();
}
+
@Override
- public ComplexNumberJdo fromEncodedString(final String str) {
- if(_NullSafe.isEmpty(str)) {
- return null;
- }
- val chunks = _Strings.splitThenStream(str, ":")
- .limit(2)
- .collect(Collectors.toList());
- if(chunks.size()<2) {
- throw new IllegalArgumentException("Invalid format " + str);
- }
- val re = Double.longBitsToDouble(Long.parseLong(chunks.get(0), 16));
- val im = Double.longBitsToDouble(Long.parseLong(chunks.get(1), 16));
- return ComplexNumberJdo.of(re, im);
+ public ComplexNumberJdo compose(final ValueDecomposition decomposition) {
+ return decomposition.right()
+ .map(CommonDtoUtils::typedTupleAsMap)
+ .map(map->ComplexNumberJdo.of(
+ (Double)map.get("re"),
+ (Double)map.get("im")))
+ .orElse(null);
}
+
+// @Override
+// public String toEncodedString(final ComplexNumberJdo cn) {
+// if(cn==null) {
+// return null;
+// }
+// val re = Double.doubleToLongBits(cn.getRe());
+// val im = Double.doubleToLongBits(cn.getIm());
+// return String.format("%s:%s",
+// Long.toHexString(re), Long.toHexString(im));
+// }
+// @Override
+// public ComplexNumberJdo fromEncodedString(final String str) {
+// if(_NullSafe.isEmpty(str)) {
+// return null;
+// }
+// val chunks = _Strings.splitThenStream(str, ":")
+// .limit(2)
+// .collect(Collectors.toList());
+// if(chunks.size()<2) {
+// throw new IllegalArgumentException("Invalid format " + str);
+// }
+// val re = Double.longBitsToDouble(Long.parseLong(chunks.get(0), 16));
+// val im = Double.longBitsToDouble(Long.parseLong(chunks.get(1), 16));
+// return ComplexNumberJdo.of(re, im);
+// }
};
}
// end::getEncoderDecoder[]
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jpa/ComplexNumberJpaValueSemantics.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jpa/ComplexNumberJpaValueSemantics.java
index 889a5fb..ce1190e 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jpa/ComplexNumberJpaValueSemantics.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/objects/other/embedded/jpa/ComplexNumberJpaValueSemantics.java
@@ -18,23 +18,18 @@
*/
package demoapp.dom.domain.objects.other.embedded.jpa;
-import java.util.stream.Collectors;
-
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.applib.value.semantics.DefaultsProvider;
-import org.apache.isis.applib.value.semantics.EncoderDecoder;
import org.apache.isis.applib.value.semantics.Parser;
import org.apache.isis.applib.value.semantics.Renderer;
+import org.apache.isis.applib.value.semantics.ValueComposer;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
-import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.schema.common.v2.ValueType;
-import lombok.val;
-
@Profile("demo-jpa")
// tag::class[]
@Component
@@ -92,36 +87,55 @@ public class ComplexNumberJpaValueSemantics
// tag::getEncoderDecoder[]
@Override
- public EncoderDecoder<ComplexNumberJpa> getEncoderDecoder() {
+ public ValueComposer<ComplexNumberJpa> getComposer() {
// end::getEncoderDecoder[]
// ...
// tag::getEncoderDecoder[]
- return new EncoderDecoder<ComplexNumberJpa>() {
+ return new ValueComposer<ComplexNumberJpa>() {
+
@Override
- public String toEncodedString(final ComplexNumberJpa cn) {
- if(cn==null) {
- return null;
- }
- val re = Double.doubleToLongBits(cn.getRe());
- val im = Double.doubleToLongBits(cn.getIm());
- return String.format("%s:%s",
- Long.toHexString(re), Long.toHexString(im));
+ public ValueDecomposition decompose(final ComplexNumberJpa value) {
+ return CommonDtoUtils.typedTupleBuilder(value)
+ .addFundamentalType(ValueType.DOUBLE, "re", ComplexNumberJpa::getRe)
+ .addFundamentalType(ValueType.DOUBLE, "im", ComplexNumberJpa::getIm)
+ .buildAsDecomposition();
}
+
@Override
- public ComplexNumberJpa fromEncodedString(final String str) {
- if(_NullSafe.isEmpty(str)) {
- return null;
- }
- val chunks = _Strings.splitThenStream(str, ":")
- .limit(2)
- .collect(Collectors.toList());
- if(chunks.size()<2) {
- throw new IllegalArgumentException("Invalid format " + str);
- }
- val re = Double.longBitsToDouble(Long.parseLong(chunks.get(0), 16));
- val im = Double.longBitsToDouble(Long.parseLong(chunks.get(1), 16));
- return ComplexNumberJpa.of(re, im);
+ public ComplexNumberJpa compose(final ValueDecomposition decomposition) {
+ return decomposition.right()
+ .map(CommonDtoUtils::typedTupleAsMap)
+ .map(map->ComplexNumberJpa.of(
+ (Double)map.get("re"),
+ (Double)map.get("im")))
+ .orElse(null);
}
+
+// @Override
+// public String toEncodedString(final ComplexNumberJpa cn) {
+// if(cn==null) {
+// return null;
+// }
+// val re = Double.doubleToLongBits(cn.getRe());
+// val im = Double.doubleToLongBits(cn.getIm());
+// return String.format("%s:%s",
+// Long.toHexString(re), Long.toHexString(im));
+// }
+// @Override
+// public ComplexNumberJpa fromEncodedString(final String str) {
+// if(_NullSafe.isEmpty(str)) {
+// return null;
+// }
+// val chunks = _Strings.splitThenStream(str, ":")
+// .limit(2)
+// .collect(Collectors.toList());
+// if(chunks.size()<2) {
+// throw new IllegalArgumentException("Invalid format " + str);
+// }
+// val re = Double.longBitsToDouble(Long.parseLong(chunks.get(0), 16));
+// val im = Double.longBitsToDouble(Long.parseLong(chunks.get(1), 16));
+// return ComplexNumberJpa.of(re, im);
+// }
};
}
// end::getEncoderDecoder[]
diff --git a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTester.java b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTester.java
index 2ce3797..333e2a5 100644
--- a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTester.java
+++ b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTester.java
@@ -99,14 +99,8 @@ public class ValueSemanticsTester<T> {
probe.testComposer(context, composerIfAny.get());
}
- val codecIfAny = codec(prop);
- if(codecIfAny.isPresent()) {
- probe.testEncoderDecoder(context, codecIfAny.get());
- }
-
- assertTrue(composerIfAny.isPresent()
- || codecIfAny.isPresent(), ()->
- "either codec or composer must be available for "
+ assertTrue(composerIfAny.isPresent(), ()->
+ "composer must be available for "
+ context.getFeatureIdentifier());
val parserIfAny = parser(prop);
@@ -190,12 +184,6 @@ public class ValueSemanticsTester<T> {
return valueFacet.selectDefaultComposer();
}
- private Optional<EncoderDecoder<T>> codec(
- final ObjectFeature feature) {
- val valueFacet = valueFacet(feature);
- return valueFacet.selectDefaultEncoderDecoder();
- }
-
private Optional<Parser<T>> parser(
final ObjectFeature feature) {
val valueFacet = valueFacet(feature);
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 f935602..e0049f9 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
@@ -35,7 +35,8 @@ 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.EncoderDecoder;
+import org.apache.isis.applib.value.semantics.ValueComposer;
+import org.apache.isis.applib.value.semantics.ValueComposer.ValueDecomposition;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.core.metamodel.facets.object.encodeable.EncodableFacet;
@@ -146,13 +147,13 @@ public class JsonValueEncoder {
final Object value = ManagedObjects.isNullOrUnspecifiedOrEmpty(objectAdapter)
? NullNode.getInstance()
- : toEncodedString(objectSpecification, objectAdapter.getPojo())
+ : decomposeToJson(objectSpecification, objectAdapter.getPojo())
.map(Object.class::cast)
.orElseGet(()->{
- log.warn("{Could not resolve an EncoderDecoder for {}, "
+ 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 EncoderDecoder<{}>}",
+ + "that implements ValueComposer<{}>}",
objectSpecification.getLogicalTypeName(),
objectSpecification.getCorrespondingClass().getSimpleName(),
objectSpecification.getCorrespondingClass().getSimpleName());
@@ -165,11 +166,17 @@ public class JsonValueEncoder {
}
}
- private static <T> Optional<String> toEncodedString(final ObjectSpecification spec, final T pojo) {
+ @SuppressWarnings("unchecked")
+ private static <T> Optional<ValueDecomposition> decompose(final ObjectSpecification spec, final T pojo) {
return spec.lookupFacet(ValueFacet.class)
- .flatMap(ValueFacet::selectDefaultEncoderDecoder)
- .map(EncoderDecoder.class::cast)
- .map(codec->((EncoderDecoder<T>)codec).toEncodedString(pojo));
+ .flatMap(ValueFacet::selectDefaultComposer)
+ .map(ValueComposer.class::cast)
+ .<ValueDecomposition>map(composer->((ValueComposer<T>)composer).decompose(pojo));
+ }
+
+ private static <T> Optional<String> decomposeToJson(final ObjectSpecification spec, final T pojo) {
+ return decompose(spec, pojo)
+ .map(ValueDecomposition::toJson);
}
@Nullable