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/28 17:24:08 UTC
[isis] 01/01: ISIS-2877: refactor CommonDtoUtils into its own Service
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch 2877_dto_rountrip_using_value_semantics
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 8b517712e7a32658dcfc335fd1197a785d7b23ef
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sun Nov 28 18:23:49 2021 +0100
ISIS-2877: refactor CommonDtoUtils into its own Service
- so we can serialize InteractionDtos using ValueSemantics, while not
having to rely on static value-type mappings
---
.../JavaTimeXMLGregorianCalendarMarshalling.java | 24 +-
.../services/schema/SchemaValueMarshaller.java | 60 +++
.../isis/applib/util/schema/CommonDtoUtils.java | 528 +-------------------
.../applib/util/schema/InteractionDtoUtils.java | 24 +-
.../semantics/Converter.java} | 22 +-
.../value/semantics/ValueSemanticsAbstract.java | 6 +
.../value/semantics/ValueSemanticsProvider.java | 5 +
.../applib/util/schema/CommonDtoUtils_Test.java | 39 +-
.../schema/CommonDtoUtils_setValueOn_Test.java | 82 ++--
.../apache/isis/applib/util/schema/Roundtrip.java | 65 ++-
.../services/metamodel/MetaModelExporter.java | 4 +-
.../valuesemantics/BookmarkValueSemantics.java | 8 -
.../LocalResourcePathValueSemantics.java | 2 +-
.../valuesemantics/MarkupValueSemantics.java | 2 +-
.../valuesemantics/OidDtoValueSemantics.java | 2 +-
.../valuesemantics/URLValueSemantics.java | 2 +-
.../valuesemantics/UUIDValueSemantics.java | 2 +-
.../temporal/legacy/JavaSqlDateValueSemantics.java | 6 -
.../legacy/JavaSqlTimeStampValueSemantics.java | 6 -
.../temporal/legacy/JavaSqlTimeValueSemantics.java | 6 -
.../legacy/JavaUtilDateValueSemantics.java | 6 -
.../valuetypes/ValueSemanticsAdapter.java | 17 +-
.../IsisModuleCoreRuntimeServices.java | 6 +-
.../command/CommandDtoFactoryDefault.java | 19 +-
.../command/CommandExecutorServiceDefault.java | 63 ++-
.../runtimeservices/command/DtoContextDefault.java | 29 --
.../command/SchemaValueMarshallerDefault.java | 529 +++++++++------------
.../interaction/InteractionDtoFactoryDefault.java | 6 +-
.../isis/extensions/restclient/ResponseDigest.java | 26 +-
.../isis/testdomain/value/ValueSemanticsTest.java | 209 ++++----
.../testdomain/value/ValueSemanticsTester.java | 21 +-
.../valuesemantics/JodaDateTimeValueSemantics.java | 6 -
.../JodaLocalDateTimeValueSemantics.java | 6 -
.../JodaLocalDateValueSemantics.java | 6 -
.../JodaLocalTimeValueSemantics.java | 6 -
35 files changed, 686 insertions(+), 1164 deletions(-)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/jaxb/JavaTimeXMLGregorianCalendarMarshalling.java b/api/applib/src/main/java/org/apache/isis/applib/jaxb/JavaTimeXMLGregorianCalendarMarshalling.java
index 377401c..b688899 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/jaxb/JavaTimeXMLGregorianCalendarMarshalling.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/jaxb/JavaTimeXMLGregorianCalendarMarshalling.java
@@ -37,43 +37,43 @@ import lombok.experimental.UtilityClass;
@UtilityClass
public final class JavaTimeXMLGregorianCalendarMarshalling {
- public static LocalDate toLocalDate(XMLGregorianCalendar cal) {
+ public static LocalDate toLocalDate(final XMLGregorianCalendar cal) {
return LocalDate.of(cal.getYear(), cal.getMonth(), cal.getDay());
}
- public static LocalTime toLocalTime(XMLGregorianCalendar cal) {
+ public static LocalTime toLocalTime(final XMLGregorianCalendar cal) {
return LocalTime.of(cal.getHour(), cal.getMinute(), cal.getSecond(),
cal.getMillisecond()*1000_000);
}
- public static LocalDateTime toLocalDateTime(XMLGregorianCalendar cal) {
+ public static LocalDateTime toLocalDateTime(final XMLGregorianCalendar cal) {
return LocalDateTime.of(cal.getYear(), cal.getMonth(), cal.getDay(),
cal.getHour(), cal.getMinute(), cal.getSecond(),
cal.getMillisecond()*1000_000);
}
- public static OffsetDateTime toOffsetDateTime(XMLGregorianCalendar cal) {
+ public static OffsetDateTime toOffsetDateTime(final XMLGregorianCalendar cal) {
return OffsetDateTime.of(cal.getYear(), cal.getMonth(), cal.getDay(),
cal.getHour(), cal.getMinute(), cal.getSecond(),
cal.getMillisecond()*1000_000,
ZoneOffset.ofTotalSeconds(cal.getTimezone()*60));
}
- public static OffsetTime toOffsetTime(XMLGregorianCalendar cal) {
+ public static OffsetTime toOffsetTime(final XMLGregorianCalendar cal) {
return OffsetTime.of(
cal.getHour(), cal.getMinute(), cal.getSecond(),
cal.getMillisecond()*1000_000,
ZoneOffset.ofTotalSeconds(cal.getTimezone()*60));
}
- public static ZonedDateTime toZonedDateTime(XMLGregorianCalendar cal) {
+ public static ZonedDateTime toZonedDateTime(final XMLGregorianCalendar cal) {
return ZonedDateTime.of(cal.getYear(), cal.getMonth(), cal.getDay(),
cal.getHour(), cal.getMinute(), cal.getSecond(),
cal.getMillisecond()*1000_000,
ZoneOffset.ofTotalSeconds(cal.getTimezone()*60));
}
- public static XMLGregorianCalendar toXMLGregorianCalendar2(LocalDate localDate) {
+ public static XMLGregorianCalendar toXMLGregorianCalendar(final LocalDate localDate) {
return localDate!=null
? DataTypeFactory.withTypeFactoryDo(factory->factory.newXMLGregorianCalendarDate(
localDate.getYear(),
@@ -84,7 +84,7 @@ public final class JavaTimeXMLGregorianCalendarMarshalling {
: null;
}
- public static XMLGregorianCalendar toXMLGregorianCalendar2(LocalTime localTime) {
+ public static XMLGregorianCalendar toXMLGregorianCalendar(final LocalTime localTime) {
return localTime!=null
? DataTypeFactory.withTypeFactoryDo(factory->factory.newXMLGregorianCalendarTime(
localTime.getHour(),
@@ -96,7 +96,7 @@ public final class JavaTimeXMLGregorianCalendarMarshalling {
: null;
}
- public static XMLGregorianCalendar toXMLGregorianCalendar2(LocalDateTime localDateTime) {
+ public static XMLGregorianCalendar toXMLGregorianCalendar(final LocalDateTime localDateTime) {
return localDateTime!=null
? DataTypeFactory.withTypeFactoryDo(factory->factory.newXMLGregorianCalendar(
localDateTime.getYear(),
@@ -111,7 +111,7 @@ public final class JavaTimeXMLGregorianCalendarMarshalling {
: null;
}
- public static XMLGregorianCalendar toXMLGregorianCalendar2(OffsetTime offsetTime) {
+ public static XMLGregorianCalendar toXMLGregorianCalendar(final OffsetTime offsetTime) {
return offsetTime!=null
? DataTypeFactory.withTypeFactoryDo(factory->factory.newXMLGregorianCalendarTime(
offsetTime.getHour(),
@@ -123,7 +123,7 @@ public final class JavaTimeXMLGregorianCalendarMarshalling {
: null;
}
- public static XMLGregorianCalendar toXMLGregorianCalendar2(OffsetDateTime offsetDateTime) {
+ public static XMLGregorianCalendar toXMLGregorianCalendar(final OffsetDateTime offsetDateTime) {
return offsetDateTime!=null
? DataTypeFactory.withTypeFactoryDo(factory->factory.newXMLGregorianCalendar(
offsetDateTime.getYear(),
@@ -138,7 +138,7 @@ public final class JavaTimeXMLGregorianCalendarMarshalling {
: null;
}
- public static XMLGregorianCalendar toXMLGregorianCalendar2(ZonedDateTime zonedDateTime) {
+ public static XMLGregorianCalendar toXMLGregorianCalendar(final ZonedDateTime zonedDateTime) {
return zonedDateTime!=null
? DataTypeFactory.withTypeFactoryDo(factory->factory.newXMLGregorianCalendar(
zonedDateTime.getYear(),
diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/schema/SchemaValueMarshaller.java b/api/applib/src/main/java/org/apache/isis/applib/services/schema/SchemaValueMarshaller.java
new file mode 100644
index 0000000..b28d8db
--- /dev/null
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/schema/SchemaValueMarshaller.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.applib.services.schema;
+
+import org.apache.isis.schema.cmd.v2.ParamDto;
+import org.apache.isis.schema.cmd.v2.PropertyDto;
+import org.apache.isis.schema.ixn.v2.ActionInvocationDto;
+
+/**
+ * Provides the runtime context for converting values
+ * between their XML <i>Schema</i> and their <i>Java</i> type representation.
+ *
+ * @since 2.x {@index}
+ */
+public interface SchemaValueMarshaller {
+
+ // -- RECOVER VALUES FROM DTO
+
+ Object recoverValueFrom(PropertyDto propertyDto);
+ Object recoverValueFrom(String logicalActionIdentifier, ParamDto paramDto);
+
+ // -- PUT VALUES INTO DTO
+
+ ActionInvocationDto putActionResult(
+ ActionInvocationDto invocationDto,
+ Class<?> returnType,
+ Object result);
+
+ PropertyDto putValueInto(
+ PropertyDto propertyDto,
+ Class<?> propertyType,
+ Object valuePojo);
+
+ ParamDto newParamDtoScalar(
+ String parameterName,
+ Class<?> paramType,
+ Object valuePojo);
+
+ ParamDto newParamDtoNonScalar(
+ String parameterName,
+ Class<?> paramElementType,
+ Object valuePojo);
+
+}
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 a4bd003..38a43f5 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
@@ -26,42 +26,18 @@ import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import org.springframework.lang.Nullable;
-
-import org.apache.isis.applib.jaxb.JavaTimeXMLGregorianCalendarMarshalling;
-import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.value.Blob;
import org.apache.isis.applib.value.Clob;
-import org.apache.isis.commons.internal.base._Casts;
-import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.base._Refs;
-import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.collections._Maps;
-import org.apache.isis.commons.internal.context._Context;
-import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.schema.cmd.v2.MapDto;
-import org.apache.isis.schema.cmd.v2.ParamDto;
-import org.apache.isis.schema.common.v2.BlobDto;
-import org.apache.isis.schema.common.v2.ClobDto;
-import org.apache.isis.schema.common.v2.CollectionDto;
-import org.apache.isis.schema.common.v2.EnumDto;
-import org.apache.isis.schema.common.v2.OidDto;
-import org.apache.isis.schema.common.v2.TypedTupleDto;
-import org.apache.isis.schema.common.v2.ValueDto;
import org.apache.isis.schema.common.v2.ValueType;
-import org.apache.isis.schema.common.v2.ValueWithTypeDto;
import static org.apache.isis.commons.internal.collections._Maps.entry;
-import lombok.NonNull;
import lombok.val;
/**
@@ -69,13 +45,8 @@ import lombok.val;
*/
public final class CommonDtoUtils {
- // -- PARAM_DTO_TO_NAME, PARAM_DTO_TO_TYPE
-
- public static final Function<ParamDto, String> PARAM_DTO_TO_NAME = ParamDto::getName;
- public static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = ParamDto::getType;
-
// -- asValueType
- public static final Map<Class<?>, ValueType> valueTypeByClass =
+ private static final Map<Class<?>, ValueType> valueTypeByClass =
_Maps.unmodifiableEntries(
entry(Void.class, ValueType.VOID),
entry(String.class, ValueType.STRING),
@@ -110,474 +81,29 @@ public final class CommonDtoUtils {
entry(Clob.class, ValueType.CLOB)
);
- private static final Set<Class<?>> VALUE_TYPES = valueTypeByClass.keySet();
-
- public static ValueType asValueType(final @NonNull Class<?> type) {
- if(Iterable.class.isAssignableFrom(type)
- || type.isArray()) {
- return ValueType.COLLECTION;
- }
- final ValueType valueType = valueTypeByClass.get(type);
- if (valueType != null) {
- return valueType;
- }
- if (type.isEnum()) {
- return ValueType.ENUM;
- }
- // assume reference otherwise
- return ValueType.REFERENCE;
- }
-
-
- // -- newValueDto, setValueOn
-
- public static ValueDto newValueDto(
- final ValueType valueType,
- final Object value,
- final @NonNull DtoContext dtoContext) {
-
- if(value == null) {
- return null;
- }
-
- final ValueDto valueDto = new ValueDto();
- return setValueOn(valueDto, valueType, value, dtoContext);
- }
-
- public static <T extends ValueWithTypeDto> T setValueOn(
- final T valueWithTypeDto,
- final ValueType valueType,
- final Object value,
- final @NonNull DtoContext dtoContext) {
-
- valueWithTypeDto.setType(valueType);
-
- setValueOn((ValueDto)valueWithTypeDto, valueType, value, dtoContext);
- valueWithTypeDto.setNull(value == null);
-
- return valueWithTypeDto;
- }
-
- public static <T extends ValueWithTypeDto> T setValueOnNonScalar(
- final T valueWithTypeDto,
- final ValueType elementValueType,
- final Object value,
- final @NonNull DtoContext dtoContext) {
-
- valueWithTypeDto.setType(ValueType.COLLECTION);
-
- val collectionDto = asCollectionDto(value, elementValueType, dtoContext);
- valueWithTypeDto.setCollection(collectionDto);
- valueWithTypeDto.setNull(value == null);
-
- return valueWithTypeDto;
- }
-
- public static <T extends ValueDto> T setValueOn(
- final T valueDto,
- final ValueType valueType,
- final Object pojo,
- final @NonNull DtoContext dtoContext) {
-
- switch (valueType) {
- case COLLECTION: {
- final CollectionDto collectionDto = asCollectionDto(
- pojo, ValueType.VOID, dtoContext);
- valueDto.setCollection(collectionDto);
- return valueDto;
- }
- case COMPOSITE: {
- final TypedTupleDto typedTupleDto = asTypedTupleDto(pojo, dtoContext);
- valueDto.setComposite(typedTupleDto);
- return valueDto;
- }
- case STRING: {
- final String argValue = (String) pojo;
- valueDto.setString(argValue);
- return valueDto;
- }
- case BYTE: {
- final Byte argValue = (Byte) pojo;
- valueDto.setByte(argValue);
- return valueDto;
- }
- case SHORT: {
- final Short argValue = (Short) pojo;
- valueDto.setShort(argValue);
- return valueDto;
- }
- case INT: {
- final Integer argValue = (Integer) pojo;
- valueDto.setInt(argValue);
- return valueDto;
- }
- case LONG: {
- final Long argValue = (Long) pojo;
- valueDto.setLong(argValue);
- return valueDto;
- }
- case CHAR: {
- final Character argValue = (Character) pojo;
- valueDto.setChar("" + argValue);
- return valueDto;
- }
- case BOOLEAN: {
- final Boolean argValue = (Boolean) pojo;
- valueDto.setBoolean(argValue);
- return valueDto;
- }
- case FLOAT: {
- final Float argValue = (Float) pojo;
- valueDto.setFloat(argValue);
- return valueDto;
- }
- case DOUBLE: {
- final Double argValue = (Double) pojo;
- valueDto.setDouble(argValue);
- return valueDto;
- }
- case BIG_INTEGER: {
- final BigInteger argValue = (BigInteger) pojo;
- valueDto.setBigInteger(argValue);
- return valueDto;
- }
- case BIG_DECIMAL: {
- final BigDecimal argValue = (BigDecimal) pojo;
- valueDto.setBigDecimal(argValue);
- return valueDto;
- }
- case LOCAL_DATE: {
- final LocalDate argValue = (LocalDate) pojo;
- valueDto.setLocalDate(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
- return valueDto;
- }
- case LOCAL_TIME: {
- final LocalTime argValue = (LocalTime) pojo;
- valueDto.setLocalTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
- return valueDto;
- }
- case LOCAL_DATE_TIME: {
- final LocalDateTime argValue = (LocalDateTime) pojo;
- valueDto.setLocalDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
- return valueDto;
- }
- case OFFSET_DATE_TIME: {
- final OffsetDateTime argValue = (OffsetDateTime) pojo;
- valueDto.setOffsetDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
- return valueDto;
- }
- case OFFSET_TIME: {
- final OffsetTime argValue = (OffsetTime) pojo;
- valueDto.setOffsetTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
- return valueDto;
- }
- case ZONED_DATE_TIME: {
- final ZonedDateTime argValue = (ZonedDateTime) pojo;
- valueDto.setZonedDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
- return valueDto;
- }
- case ENUM: {
- final Enum<?> argValue = (Enum<?>) pojo;
- if(argValue == null) {
- return null;
- }
- final EnumDto enumDto = new EnumDto();
- valueDto.setEnum(enumDto);
- enumDto.setEnumType(argValue.getClass().getName());
- enumDto.setEnumName(argValue.name());
- return valueDto;
- }
- case REFERENCE: {
- final Bookmark bookmark = pojo instanceof Bookmark
- ? (Bookmark) pojo
- : dtoContext.getBookmarkService()!=null
- ? dtoContext.getBookmarkService().bookmarkFor(pojo).orElse(null)
- : null;
-
- if (bookmark != null) {
- OidDto argValue = bookmark.toOidDto();
- valueDto.setReference(argValue);
- }
- return valueDto;
- }
- case BLOB: {
- final Blob blob = (Blob) pojo;
- if(blob != null) {
- final BlobDto blobDto = new BlobDto();
- blobDto.setName(blob.getName());
- blobDto.setBytes(blob.getBytes());
- blobDto.setMimeType(blob.getMimeType().toString());
- valueDto.setBlob(blobDto);
- }
- return valueDto;
- }
- case CLOB: {
- final Clob clob = (Clob) pojo;
- if(clob != null) {
- final ClobDto clobDto = new ClobDto();
- clobDto.setName(clob.getName());
- clobDto.setChars(clob.getChars().toString());
- clobDto.setMimeType(clob.getMimeType().toString());
- valueDto.setClob(clobDto);
- }
- return valueDto;
- }
- case VOID: {
- return null;
- }
- default:
- throw _Exceptions.unmatchedCase(valueType);
- }
- }
-
- private static CollectionDto asCollectionDto(
- final @Nullable Object iterableOrArray,
- final @NonNull ValueType commonElementValueType,
- final @NonNull DtoContext dtoContext) {
-
- val collectionDto = new CollectionDto();
- collectionDto.setType(commonElementValueType);
-
- val needsCommonElementValueTypeAutodetect = commonElementValueType==ValueType.VOID;
-
- val commonElementValueTypeRef = _Refs.<ValueType>objectRef(null);
-
- _NullSafe.streamAutodetect(iterableOrArray)
- .forEach(element->{
- val valueDto = new ValueDto();
- if(element==null) {
- setValueOn(valueDto, ValueType.VOID, element, dtoContext);
- } else {
- val elementValueType = asValueType(element.getClass());
- setValueOn(valueDto, elementValueType, element, dtoContext);
-
- if(needsCommonElementValueTypeAutodetect) {
- commonElementValueTypeRef.update(acc->reduce(acc, elementValueType));
- }
-
- }
- collectionDto.getValue().add(valueDto);
- });
-
- if(needsCommonElementValueTypeAutodetect) {
- collectionDto.setType(commonElementValueTypeRef.getValueElseDefault(ValueType.VOID));
- }
-
- return collectionDto;
- }
-
- private static TypedTupleDto asTypedTupleDto(
- final @Nullable Object composite,
- final @NonNull DtoContext dtoContext) {
- val typedTupleDto = new TypedTupleDto();
- //TODO implement
- return typedTupleDto;
- }
-
- // -- getValue (from valueDto)
-
- private static ValueType reduce(final ValueType acc, final ValueType next) {
- if(acc==null) {
- return next;
- }
- if(acc==next) {
- return acc;
- }
- throw _Exceptions.unsupportedOperation("mixing types within a collection is not supported yet");
- }
-
- public static <T> T getValue(
- final ValueDto valueDto,
- final ValueType valueType) {
- return _Casts.uncheckedCast(getValueAsObject(valueDto, valueType));
- }
-
- private static Object getValueAsObject(
- final ValueDto valueDto,
- final ValueType valueType) {
- switch(valueType) {
- case STRING:
- return valueDto.getString();
- case BYTE:
- return valueDto.getByte();
- case SHORT:
- return valueDto.getShort();
- case INT:
- return valueDto.getInt();
- case LONG:
- return valueDto.getLong();
- case FLOAT:
- return valueDto.getFloat();
- case DOUBLE:
- return valueDto.getDouble();
- case BOOLEAN:
- return valueDto.isBoolean();
- case CHAR:
- final String aChar = valueDto.getChar();
- if(_Strings.isNullOrEmpty(aChar)) { return null; }
- return aChar.charAt(0);
- case BIG_DECIMAL:
- return valueDto.getBigDecimal();
- case BIG_INTEGER:
- return valueDto.getBigInteger();
- // JAVA TIME
- case LOCAL_DATE:
- return JavaTimeXMLGregorianCalendarMarshalling.toLocalDate(valueDto.getLocalDate());
- case LOCAL_TIME:
- return JavaTimeXMLGregorianCalendarMarshalling.toLocalTime(valueDto.getLocalTime());
- case LOCAL_DATE_TIME:
- return JavaTimeXMLGregorianCalendarMarshalling.toLocalDateTime(valueDto.getLocalDateTime());
- case OFFSET_DATE_TIME:
- return JavaTimeXMLGregorianCalendarMarshalling.toOffsetDateTime(valueDto.getOffsetDateTime());
- case OFFSET_TIME:
- return JavaTimeXMLGregorianCalendarMarshalling.toOffsetTime(valueDto.getOffsetTime());
- case ZONED_DATE_TIME:
- return JavaTimeXMLGregorianCalendarMarshalling.toZonedDateTime(valueDto.getZonedDateTime());
-// case JAVA_SQL_TIMESTAMP:
-// return JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(valueDto.getTimestamp());
- case ENUM:
- final EnumDto enumDto = valueDto.getEnum();
- final String enumType = enumDto.getEnumType();
- @SuppressWarnings("rawtypes")
- final Class<? extends Enum> enumClass = loadClassElseThrow(enumType);
- return Enum.valueOf(_Casts.uncheckedCast(enumClass), enumDto.getEnumName());
- case REFERENCE:
- return valueDto.getReference();
- case COLLECTION:
- val collectionDto = valueDto.getCollection();
- if(_NullSafe.isEmpty(collectionDto.getValue())) {
- return Collections.emptyList();
- }
- val list = new ArrayList<Object>();
-
- val elementValueType = collectionDto.getType();
-
- for(val elementValueDto : collectionDto.getValue()) {
-
- if(elementValueDto instanceof ValueWithTypeDto) {
- list.add(getValueAsObject(elementValueDto, ((ValueWithTypeDto)elementValueDto).getType()));
- } else {
- list.add(getValueAsObject(elementValueDto, elementValueType));
- }
-
- }
- return list;
- case BLOB:
- final BlobDto blobDto = valueDto.getBlob();
- return new Blob(blobDto.getName(), blobDto.getMimeType(), blobDto.getBytes());
- case CLOB:
- final ClobDto clobDto = valueDto.getClob();
- return new Clob(clobDto.getName(), clobDto.getMimeType(), clobDto.getChars());
- case VOID:
- return null;
- default:
- throw _Exceptions.unmatchedCase(valueType);
- }
- }
-
- private static <T> Class<T> loadClassElseThrow(final String className) {
- try {
- return _Casts.uncheckedCast(_Context.loadClassAndInitialize(className));
- } catch (ClassNotFoundException e) {
-
- // [ahuber] fallback to pre 2.0.0 behavior, not sure if needed
- try {
- return _Casts.uncheckedCast(Class.forName(className));
- } catch (ClassNotFoundException e1) {
- throw new RuntimeException(e);
- }
- }
- }
-
-
-
- // -- newValueWithTypeDto
-
-
- public static ValueWithTypeDto newValueWithTypeDto(
- final Class<?> type,
- final Object val,
- final @NonNull DtoContext dtoContext) {
-
- final ValueWithTypeDto valueWithTypeDto = new ValueWithTypeDto();
-
- final ValueType valueType = asValueType(type);
- setValueOn(valueWithTypeDto, valueType, val, dtoContext);
-
- return valueWithTypeDto;
- }
-
-
-
- // -- getValue (from ValueWithTypeDto)
-
- public static <T> T getValue(final ValueWithTypeDto valueWithTypeDto) {
- if(valueWithTypeDto.isNull()) {
- return null;
- }
- final ValueType type = valueWithTypeDto.getType();
- return CommonDtoUtils.getValue(valueWithTypeDto, type);
- }
-
-
-
-
-
- // -- newParamDto
-
- public static ParamDto newParamDto(
- final String parameterName,
- final Class<?> parameterType,
- final Object arg,
- final @NonNull DtoContext dtoContext) {
-
- val paramDto = new ParamDto();
- paramDto.setName(parameterName);
-
- ValueType valueType = CommonDtoUtils.asValueType(parameterType);
- // this hack preserves previous behaviour before we were able to serialize blobs and clobs into XML
- // however, we also don't want this new behaviour for parameter arguments
- // (else these large objects could end up being persisted).
- if(valueType == ValueType.BLOB) valueType = ValueType.REFERENCE;
- if(valueType == ValueType.CLOB) valueType = ValueType.REFERENCE;
-
- paramDto.setType(valueType);
-
- CommonDtoUtils.setValueOn(paramDto, valueType, arg, dtoContext);
-
- return paramDto;
- }
-
- public static ParamDto newParamDtoNonScalar(
- final String parameterName,
- final Class<?> parameterElementType,
- final Object arg,
- final @NonNull DtoContext dtoContext) {
-
- val paramDto = new ParamDto();
- paramDto.setName(parameterName);
- paramDto.setType(ValueType.COLLECTION);
-
- val elementValueType = CommonDtoUtils.asValueType(parameterElementType);
- CommonDtoUtils.setValueOnNonScalar(paramDto, elementValueType, arg, dtoContext);
-
- return paramDto;
- }
-
-
- // -- getValue (from ParamDto)
-
- public static <T> T getValue(final ParamDto paramDto) {
- if(paramDto.isNull()) {
- return null;
- }
- final ValueType parameterType = paramDto.getType();
- return CommonDtoUtils.getValue(paramDto, parameterType);
- }
-
-
-
- public static String getMapValue(final MapDto mapDto, final String key) {
+// private static ValueTypeAndSemantics<?> asValueType(
+// final @NonNull Class<?> type,
+// final @NonNull SchemaValueMarshaller valueMarshaller) {
+//
+// if(Iterable.class.isAssignableFrom(type)
+// || type.isArray()) {
+// return ValueTypeAndSemantics.of(ValueType.COLLECTION, null);
+// }
+//// if (type.isEnum()) {
+//// return ValueType.ENUM;
+//// }
+//// // not strictly required: an optimization to infer ValueType, when directly mapped
+//// final ValueType valueType = valueTypeByClass.get(type);
+//// if (valueType != null) {
+//// return valueType;
+//// }
+// return ValueTypeAndSemantics.resolve(valueMarshaller, type);
+// }
+
+
+ // -- MAP-DTO SUPPORT
+
+ static String getMapValue(final MapDto mapDto, final String key) {
if(mapDto == null) {
return null;
}
@@ -585,7 +111,7 @@ public final class CommonDtoUtils {
return entryIfAny.map(MapDto.Entry::getValue).orElse(null);
}
- public static void putMapKeyValue(final MapDto mapDto, final String key, final String value) {
+ static void putMapKeyValue(final MapDto mapDto, final String key, final String value) {
if(mapDto == null) {
return;
}
@@ -607,8 +133,4 @@ public final class CommonDtoUtils {
}
- public static boolean isValueType(final Class<?> type) {
- return VALUE_TYPES.contains(type);
- }
-
}
diff --git a/api/applib/src/main/java/org/apache/isis/applib/util/schema/InteractionDtoUtils.java b/api/applib/src/main/java/org/apache/isis/applib/util/schema/InteractionDtoUtils.java
index c2d2cdd..20a4a7d 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/util/schema/InteractionDtoUtils.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/util/schema/InteractionDtoUtils.java
@@ -37,6 +37,7 @@ import javax.xml.bind.Unmarshaller;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.iactn.Execution;
import org.apache.isis.applib.services.iactn.Interaction;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.applib.util.JaxbUtil;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.collections._Lists;
@@ -60,12 +61,10 @@ import lombok.NonNull;
*/
public final class InteractionDtoUtils {
-
public static void init() {
getJaxbContext();
}
-
// -- marshalling
static JAXBContext jaxbContext;
static JAXBContext getJaxbContext() {
@@ -345,10 +344,10 @@ public final class InteractionDtoUtils {
final String parameterName,
final Class<?> parameterType,
final Object arg,
- final @NonNull DtoContext dtoContext) {
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
final List<ParamDto> params = parameterListFor(interactionDto);
- ParamDto paramDto = CommonDtoUtils.newParamDto(parameterName, parameterType, arg, dtoContext);
+ final ParamDto paramDto = valueMarshaller.newParamDtoScalar(parameterName, parameterType, arg);
params.add(paramDto);
}
@@ -359,17 +358,15 @@ public final class InteractionDtoUtils {
*
* @param returnType - to determine the value type (if any)
* @param result - either a value type (possibly boxed primitive), or a reference type
- * @param dtoContext - used if not a fundamental value type
+ * @param valueMarshaller - used if not a fundamental value type
*/
public static void addReturn(
final ActionInvocationDto invocationDto,
final Class<?> returnType,
final Object result,
- final @NonNull DtoContext dtoContext) {
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
- final ValueWithTypeDto returned = CommonDtoUtils
- .newValueWithTypeDto(returnType, result, dtoContext);
- invocationDto.setReturned(returned);
+ valueMarshaller.putActionResult(invocationDto, returnType, result);
}
@@ -393,14 +390,14 @@ public final class InteractionDtoUtils {
public static List<String> getParameterNames(final ActionInvocationDto ai) {
return Collections.unmodifiableList(
_NullSafe.stream(getParameters(ai))
- .map(CommonDtoUtils.PARAM_DTO_TO_NAME)
+ .map(ParamDto::getName)
.collect(Collectors.toList())
);
}
public static List<ValueType> getParameterTypes(final ActionInvocationDto ai) {
return Collections.unmodifiableList(
_NullSafe.stream(getParameters(ai))
- .map(CommonDtoUtils.PARAM_DTO_TO_TYPE)
+ .map(ParamDto::getType)
.collect(Collectors.toList())
);
}
@@ -438,9 +435,10 @@ public final class InteractionDtoUtils {
// -- getParameterArgValue
- public static <T> T getParameterArgValue(final ActionInvocationDto ai, final int paramNum) {
+ public static <T> T getParameterArgValue(final ActionInvocationDto ai, final int paramNum,
+ @NonNull final SchemaValueMarshaller valueMarshaller) {
final ParamDto paramDto = getParameter(ai, paramNum);
- return CommonDtoUtils.getValue(paramDto);
+ return (T) valueMarshaller.recoverValueFrom(ai.getLogicalMemberIdentifier(), paramDto);
}
// -- debugging (dump)
diff --git a/api/applib/src/main/java/org/apache/isis/applib/util/schema/DtoContext.java b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/Converter.java
similarity index 66%
rename from api/applib/src/main/java/org/apache/isis/applib/util/schema/DtoContext.java
rename to api/applib/src/main/java/org/apache/isis/applib/value/semantics/Converter.java
index 816a465..74bda7d 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/util/schema/DtoContext.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/value/semantics/Converter.java
@@ -16,20 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.applib.util.schema;
-
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
+package org.apache.isis.applib.value.semantics;
/**
- * Provides the runtime context for converting <i>Schema</i> DTOs
- * between their XML and their Java type representation.
+ * Provides forth and back conversion between 2 types.
+ *
+ * @param <T> - value-type
+ * @param <D> - value-type, the <i>delegate</i>
+ *
+ * @see DefaultsProvider
+ * @see Parser
+ * @see EncoderDecoder
+ * @see ValueSemanticsProvider
*
* @since 2.x {@index}
*/
-public interface DtoContext {
+public interface Converter<T, D> {
- BookmarkService getBookmarkService();
- ValueSemanticsResolver getValueSemanticsResolver();
+ public abstract T fromDelegateValue(D value);
+ public abstract D toDelegateValue(T value);
}
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 89f36ec..9adb8c2 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
@@ -60,6 +60,12 @@ implements
@SuppressWarnings("unchecked")
@Override
+ public Converter<T, ?> getConverter() {
+ return this instanceof Converter ? (Converter<T, ?>)this : null;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
public Renderer<T> getRenderer() {
return this instanceof Renderer ? (Renderer<T>)this : null;
}
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 2524887..3745b0c 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
@@ -71,6 +71,11 @@ public interface ValueSemanticsProvider<T> {
OrderRelation<T, ?> getOrderRelation();
/**
+ * The {@link Converter}, if any.
+ */
+ Converter<T, ?> getConverter();
+
+ /**
* The {@link Renderer}, if any.
*/
Renderer<T> getRenderer();
diff --git a/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_Test.java b/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_Test.java
index d6f9643..e94cb2a 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_Test.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_Test.java
@@ -20,18 +20,16 @@ package org.apache.isis.applib.util.schema;
import org.jmock.auto.Mock;
import org.jmock.integration.junit4.JUnitRuleMockery;
-import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.fail;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.schema.cmd.v2.MapDto;
-import org.apache.isis.schema.common.v2.ValueDto;
-import org.apache.isis.schema.common.v2.ValueType;
public class CommonDtoUtils_Test {
@@ -39,7 +37,7 @@ public class CommonDtoUtils_Test {
public JUnitRuleMockery context = new JUnitRuleMockery();
@Mock
- private DtoContext mockDtoContext;
+ private SchemaValueMarshaller mockDtoContext;
@Test
public void enums() {
@@ -57,20 +55,23 @@ public class CommonDtoUtils_Test {
private void test(final Enum<?> enumVal) {
- // when
- final ValueType valueType = CommonDtoUtils.asValueType(enumVal.getClass());
-
- // then
- assertThat(valueType, is(ValueType.ENUM));
-
- // and when
- final ValueDto valueDto = CommonDtoUtils.newValueDto(valueType, enumVal, mockDtoContext);
-
- // then
- Object value = CommonDtoUtils.getValue(valueDto, valueType);
- assertThat(value, is(notNullValue()));
-
- Assert.assertEquals(value, enumVal);
+ fail("not implemented");
+
+// // when
+// val valueTypeAndSemantics = CommonDtoUtils.asValueType(enumVal.getClass(), mockDtoContext);
+// final ValueType valueType = valueTypeAndSemantics.getValueType();
+//
+// // then
+// assertThat(valueType, is(ValueType.ENUM));
+//
+// // and when
+// final ValueDto valueDto = CommonDtoUtils.newValueDto(valueTypeAndSemantics, enumVal, mockDtoContext);
+//
+// // then
+// Object value = CommonDtoUtils.getValue(valueDto, valueTypeAndSemantics);
+// assertThat(value, is(notNullValue()));
+//
+// Assert.assertEquals(value, enumVal);
}
@Test
diff --git a/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_setValueOn_Test.java b/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_setValueOn_Test.java
index 30e5ae5..a0823af 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_setValueOn_Test.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/util/schema/CommonDtoUtils_setValueOn_Test.java
@@ -20,21 +20,14 @@ package org.apache.isis.applib.util.schema;
import org.jmock.auto.Mock;
import org.jmock.integration.junit4.JUnitRuleMockery;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.jupiter.api.Assertions.fail;
-import org.apache.isis.applib.value.Blob;
-import org.apache.isis.applib.value.Clob;
-import org.apache.isis.schema.common.v2.BlobDto;
-import org.apache.isis.schema.common.v2.ClobDto;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.schema.common.v2.ValueDto;
-import org.apache.isis.schema.common.v2.ValueType;
public class CommonDtoUtils_setValueOn_Test {
@@ -42,7 +35,7 @@ public class CommonDtoUtils_setValueOn_Test {
public JUnitRuleMockery context = new JUnitRuleMockery();
@Mock
- private DtoContext mockDtoContext;
+ private SchemaValueMarshaller mockDtoContext;
ValueDto valueDto;
@Before
@@ -51,38 +44,43 @@ public class CommonDtoUtils_setValueOn_Test {
}
@Test
- public void when_blob_is_null() {
- CommonDtoUtils.setValueOn(valueDto, ValueType.BLOB, null, mockDtoContext);
- final BlobDto blobDto = valueDto.getBlob();
- Assert.assertThat(blobDto, is(nullValue()));
+ public void not_implemented() {
+ fail("setValueOn not implemented");
}
- @Test
- public void when_blob_is_not_null() {
- final Blob val = new Blob("image.png", "image/png", new byte[]{1,2,3,4,5});
- CommonDtoUtils.setValueOn(valueDto, ValueType.BLOB, val, mockDtoContext);
- final BlobDto blobDto = valueDto.getBlob();
- Assert.assertThat(blobDto, is(notNullValue()));
- Assert.assertThat(blobDto.getBytes(), is(val.getBytes()));
- Assert.assertThat(blobDto.getName(), is(val.getName()));
- Assert.assertThat(blobDto.getMimeType(), is(val.getMimeType().toString()));
- }
-
- @Test
- public void when_clob_is_null() {
- CommonDtoUtils.setValueOn(valueDto, ValueType.CLOB, null, mockDtoContext);
- final ClobDto clobDto = valueDto.getClob();
- Assert.assertThat(clobDto, is(nullValue()));
- }
-
- @Test
- public void when_clob_is_not_null() {
- final Clob val = new Clob("image.png", "image/png", new char[]{1,2,3,4,5});
- CommonDtoUtils.setValueOn(valueDto, ValueType.CLOB, val, mockDtoContext);
- final ClobDto clobDto = valueDto.getClob();
- Assert.assertThat(clobDto, is(notNullValue()));
- Assert.assertThat(clobDto.getChars(), is(val.getChars()));
- Assert.assertThat(clobDto.getName(), is(val.getName()));
- Assert.assertThat(clobDto.getMimeType(), is(val.getMimeType().toString()));
- }
+// @Test
+// public void when_blob_is_null() {
+// CommonDtoUtils.setValueOn(valueDto, ValueTypeAndSemantics.of(ValueType.BLOB, null), null, mockDtoContext);
+// final BlobDto blobDto = valueDto.getBlob();
+// Assert.assertThat(blobDto, is(nullValue()));
+// }
+//
+// @Test
+// public void when_blob_is_not_null() {
+// final Blob val = new Blob("image.png", "image/png", new byte[]{1,2,3,4,5});
+// CommonDtoUtils.setValueOn(valueDto, ValueTypeAndSemantics.of(ValueType.BLOB, null), val, mockDtoContext);
+// final BlobDto blobDto = valueDto.getBlob();
+// Assert.assertThat(blobDto, is(notNullValue()));
+// Assert.assertThat(blobDto.getBytes(), is(val.getBytes()));
+// Assert.assertThat(blobDto.getName(), is(val.getName()));
+// Assert.assertThat(blobDto.getMimeType(), is(val.getMimeType().toString()));
+// }
+//
+// @Test
+// public void when_clob_is_null() {
+// CommonDtoUtils.setValueOn(valueDto, ValueTypeAndSemantics.of(ValueType.CLOB, null), null, mockDtoContext);
+// final ClobDto clobDto = valueDto.getClob();
+// Assert.assertThat(clobDto, is(nullValue()));
+// }
+//
+// @Test
+// public void when_clob_is_not_null() {
+// final Clob val = new Clob("image.png", "image/png", new char[]{1,2,3,4,5});
+// CommonDtoUtils.setValueOn(valueDto, ValueTypeAndSemantics.of(ValueType.CLOB, null), val, mockDtoContext);
+// final ClobDto clobDto = valueDto.getClob();
+// Assert.assertThat(clobDto, is(notNullValue()));
+// Assert.assertThat(clobDto.getChars(), is(val.getChars()));
+// Assert.assertThat(clobDto.getName(), is(val.getName()));
+// Assert.assertThat(clobDto.getMimeType(), is(val.getMimeType().toString()));
+// }
}
\ No newline at end of file
diff --git a/api/applib/src/test/java/org/apache/isis/applib/util/schema/Roundtrip.java b/api/applib/src/test/java/org/apache/isis/applib/util/schema/Roundtrip.java
index 77ff2fb..e971581 100644
--- a/api/applib/src/test/java/org/apache/isis/applib/util/schema/Roundtrip.java
+++ b/api/applib/src/test/java/org/apache/isis/applib/util/schema/Roundtrip.java
@@ -42,13 +42,13 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import org.apache.isis.applib.services.bookmark.Bookmark;
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.schema.cmd.v2.ParamDto;
+import org.apache.isis.schema.cmd.v2.PropertyDto;
import org.apache.isis.schema.common.v2.InteractionType;
import org.apache.isis.schema.common.v2.OidDto;
import org.apache.isis.schema.common.v2.ValueType;
@@ -90,17 +90,57 @@ public class Roundtrip {
private static void addArg(final InteractionDto interactionDto, final Object sampleValue) {
- val dtoContext = new DtoContext() {
- @Override public BookmarkService getBookmarkService() {
- return null; }
- @Override public ValueSemanticsResolver getValueSemanticsResolver() {
- return null; }
- };
+ val valueMarshaller = schemaValueMarshaller();
val type = sampleValue.getClass();
val name = type.getSimpleName();
- InteractionDtoUtils.addParamArg(interactionDto, "a"+name, type, sampleValue, dtoContext);
- InteractionDtoUtils.addParamArg(interactionDto, "null"+name, type, type.cast(null), dtoContext);
+ InteractionDtoUtils.addParamArg(interactionDto, "a"+name, type, sampleValue, valueMarshaller);
+ InteractionDtoUtils.addParamArg(interactionDto, "null"+name, type, type.cast(null), valueMarshaller);
+ }
+
+ private static SchemaValueMarshaller schemaValueMarshaller() {
+ return new SchemaValueMarshaller() {
+
+ @Override
+ public Object recoverValueFrom(final PropertyDto propertyDto) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+ @Override
+ public ActionInvocationDto putActionResult(final ActionInvocationDto invocationDto, final Class<?> returnType,
+ final Object result) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public PropertyDto putValueInto(final PropertyDto propertyDto, final Class<?> propertyType, final Object valuePojo) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ParamDto newParamDtoScalar(final String parameterName, final Class<?> paramType, final Object valuePojo) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ParamDto newParamDtoNonScalar(final String parameterName, final Class<?> paramElementType, final Object valuePojo) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+ @Override
+ public Object recoverValueFrom(final String logicalMemberIdentifier, final ParamDto paramDto) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ };
}
private static void testArg(
@@ -108,6 +148,7 @@ public class Roundtrip {
final LongAdder paramIndex,
final ValueType valueType,
final Object expectedValue) {
+
testArg(invocationDto, paramIndex, valueType, expectedValue, null);
}
@@ -118,6 +159,8 @@ public class Roundtrip {
final Object expectedValue,
final String nameOverride) {
+ val valueMarshaller = schemaValueMarshaller();
+
paramIndex.increment();
int param = paramIndex.intValue();
@@ -127,7 +170,7 @@ public class Roundtrip {
assertThat(InteractionDtoUtils.getParameterType(invocationDto, param), Matchers.is(valueType));
assertThat(InteractionDtoUtils.isNull(invocationDto, param), is(false));
- val actualValue = InteractionDtoUtils.getParameterArgValue(invocationDto, param);
+ val actualValue = InteractionDtoUtils.getParameterArgValue(invocationDto, param, valueMarshaller);
// equals test, some types need special checks ...
if(expectedValue instanceof OidDto) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
index 03372f4..03d1fe8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
@@ -29,7 +29,6 @@ import java.util.regex.Pattern;
import org.apache.isis.applib.services.commanddto.processor.CommandDtoProcessor;
import org.apache.isis.applib.services.metamodel.Config;
import org.apache.isis.applib.spec.Specification;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Maps;
@@ -454,10 +453,9 @@ class MetaModelExporter {
}
private boolean isValueType(final ObjectSpecification specification) {
- return CommonDtoUtils.isValueType(specification.getCorrespondingClass());
+ return specification.getBeanSort().isValue();
}
-
private String asStr(final Object attributeObj) {
String str;
if(attributeObj instanceof Method) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BookmarkValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BookmarkValueSemantics.java
index c07f79f..823cfb5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BookmarkValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/BookmarkValueSemantics.java
@@ -27,7 +27,6 @@ import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuetypes.ValueSemanticsAdapter;
import org.apache.isis.schema.common.v2.OidDto;
-import org.apache.isis.schema.common.v2.ValueType;
@Component
@Named("isis.val.BookmarkValueSemantics")
@@ -42,11 +41,6 @@ extends ValueSemanticsAdapter<Bookmark, OidDto, Void> {
}
@Override
- public ValueType getSchemaValueType() {
- return UNREPRESENTED;
- }
-
- @Override
public ValueSemanticsAbstract<OidDto> getDelegate() {
return oidDtoValueSemantics;
}
@@ -61,6 +55,4 @@ extends ValueSemanticsAdapter<Bookmark, OidDto, Void> {
return value!=null ? value.toOidDto() : null;
}
-
-
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/LocalResourcePathValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/LocalResourcePathValueSemantics.java
index 92b1773..cfb8fd0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/LocalResourcePathValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/LocalResourcePathValueSemantics.java
@@ -50,7 +50,7 @@ implements
@Override
public ValueType getSchemaValueType() {
- return UNREPRESENTED;
+ return ValueType.STRING; // this type can be easily converted to string and back
}
// -- ENCODER DECODER
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/MarkupValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/MarkupValueSemantics.java
index 76dd090..eac8f1a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/MarkupValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/MarkupValueSemantics.java
@@ -46,7 +46,7 @@ implements
@Override
public ValueType getSchemaValueType() {
- return UNREPRESENTED;
+ return ValueType.STRING; // this type can be easily converted to string and back;
}
// -- ENCODER DECODER
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java
index 906da73..43dfa80 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/OidDtoValueSemantics.java
@@ -55,7 +55,7 @@ implements
@Override
public ValueType getSchemaValueType() {
- return UNREPRESENTED;
+ return ValueType.REFERENCE;
}
// -- ORDER RELATION
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java
index 599bb68..5f74870 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/URLValueSemantics.java
@@ -50,7 +50,7 @@ implements
@Override
public ValueType getSchemaValueType() {
- return UNREPRESENTED;
+ return ValueType.STRING; // this type can be easily converted to string and back
}
// -- ENCODER DECODER
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/UUIDValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/UUIDValueSemantics.java
index afdf140..0be0511 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/UUIDValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/UUIDValueSemantics.java
@@ -50,7 +50,7 @@ implements
@Override
public ValueType getSchemaValueType() {
- return UNREPRESENTED;
+ return ValueType.STRING; // this type can be easily converted to string and back
}
// -- ENCODER DECODER
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlDateValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlDateValueSemantics.java
index 966a97e..2c1420b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlDateValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlDateValueSemantics.java
@@ -29,7 +29,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
/**
* An adapter that handles {@link java.sql.Date} with only date component.
@@ -50,11 +49,6 @@ extends TemporalSemanticsAdapter<Date, LocalDate> {
}
@Override
- public ValueType getSchemaValueType() {
- return UNREPRESENTED;
- }
-
- @Override
public ValueSemanticsAbstract<LocalDate> getDelegate() {
return localDateValueSemantics;
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeStampValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeStampValueSemantics.java
index fb448be..997dd86 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeStampValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeStampValueSemantics.java
@@ -29,7 +29,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateTimeValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
@Component
@Named("isis.val.JavaSqlTimeStampValueSemantics")
@@ -44,11 +43,6 @@ extends TemporalSemanticsAdapter<Timestamp, LocalDateTime> {
}
@Override
- public ValueType getSchemaValueType() {
- return ValueType.LOCAL_DATE_TIME;
- }
-
- @Override
public ValueSemanticsAbstract<LocalDateTime> getDelegate() {
return localDateTimeValueSemantics;
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeValueSemantics.java
index 8200432..2abba15 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaSqlTimeValueSemantics.java
@@ -29,7 +29,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalTimeValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
/**
* Treats {@link java.sql.Time} as a time-only value type.
@@ -48,11 +47,6 @@ extends TemporalSemanticsAdapter<Time, LocalTime> {
}
@Override
- public ValueType getSchemaValueType() {
- return UNREPRESENTED;
- }
-
- @Override
public ValueSemanticsAbstract<LocalTime> getDelegate() {
return localTimeValueSemantics;
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaUtilDateValueSemantics.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaUtilDateValueSemantics.java
index 08fff1d..f32c240 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaUtilDateValueSemantics.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuesemantics/temporal/legacy/JavaUtilDateValueSemantics.java
@@ -30,7 +30,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateTimeValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
/**
* An adapter that handles {@link java.util.Date} as both a date AND time
@@ -52,11 +51,6 @@ extends TemporalSemanticsAdapter<Date, LocalDateTime> {
}
@Override
- public ValueType getSchemaValueType() {
- return UNREPRESENTED;
- }
-
- @Override
public ValueSemanticsAbstract<LocalDateTime> getDelegate() {
return localDateTimeValueSemantics;
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuetypes/ValueSemanticsAdapter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuetypes/ValueSemanticsAdapter.java
index 4910f19..9b2aead 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuetypes/ValueSemanticsAdapter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/valuetypes/ValueSemanticsAdapter.java
@@ -18,12 +18,14 @@
*/
package org.apache.isis.core.metamodel.valuetypes;
+import org.apache.isis.applib.value.semantics.Converter;
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;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
+import org.apache.isis.schema.common.v2.ValueType;
import lombok.val;
@@ -33,12 +35,19 @@ implements
OrderRelation<T, E>,
EncoderDecoder<T>,
Parser<T>,
- Renderer<T> {
+ Renderer<T>,
+ Converter<T, D>{
public abstract ValueSemanticsAbstract<D> getDelegate();
- public abstract T fromDelegateValue(D value);
- public abstract D toDelegateValue(T value);
+ /**
+ * By design, adapters always share their <i>SchemaValueType</i> with their delegate.
+ * @see ValueSemanticsProvider#getSchemaValueType()
+ */
+ @Override
+ public final ValueType getSchemaValueType() {
+ return getDelegate().getSchemaValueType();
+ }
// -- ORDER RELATION
@@ -59,6 +68,8 @@ implements
.equals(toDelegateValue(a), toDelegateValue(b), epsilon);
}
+ // -- CONVERTER
+
// -- ENCODER DECODER
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
index 914e044..da7db926 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/IsisModuleCoreRuntimeServices.java
@@ -31,7 +31,7 @@ import org.apache.isis.core.runtime.IsisModuleCoreRuntime;
import org.apache.isis.core.runtimeservices.bookmarks.BookmarkServiceDefault;
import org.apache.isis.core.runtimeservices.command.CommandDtoFactoryDefault;
import org.apache.isis.core.runtimeservices.command.CommandExecutorServiceDefault;
-import org.apache.isis.core.runtimeservices.command.DtoContextDefault;
+import org.apache.isis.core.runtimeservices.command.SchemaValueMarshallerDefault;
import org.apache.isis.core.runtimeservices.email.EmailServiceDefault;
import org.apache.isis.core.runtimeservices.eventbus.EventBusServiceSpring;
import org.apache.isis.core.runtimeservices.executor.MemberExecutorServiceDefault;
@@ -107,9 +107,7 @@ import org.apache.isis.core.runtimeservices.xmlsnapshot.XmlSnapshotServiceDefaul
XmlServiceDefault.class,
XmlSnapshotServiceDefault.class,
ObjectLifecyclePublisherDefault.class,
-
- // @Component's
- DtoContextDefault.class,
+ SchemaValueMarshallerDefault.class,
// @Controller
RoutingServiceDefault.class,
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandDtoFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandDtoFactoryDefault.java
index 0c8f396..67894ab 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandDtoFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandDtoFactoryDefault.java
@@ -30,10 +30,9 @@ import org.springframework.stereotype.Service;
import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.clock.ClockService;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.applib.services.user.UserService;
import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
-import org.apache.isis.applib.util.schema.DtoContext;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.exceptions._Exceptions;
import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -66,7 +65,7 @@ import lombok.val;
@Qualifier("Default")
public class CommandDtoFactoryDefault implements CommandDtoFactory {
- @Inject private DtoContext dtoContext;
+ @Inject private SchemaValueMarshaller valueMarshaller;
@Inject private ClockService clockService;
@Inject private UserService userService;
@@ -127,18 +126,16 @@ public class CommandDtoFactoryDefault implements CommandDtoFactory {
val paramTypeOrElementType = actionParameter.getElementType().getCorrespondingClass();
val paramDto = actionParameter.getFeatureType() == FeatureType.ACTION_PARAMETER_COLLECTION
- ? CommonDtoUtils.newParamDtoNonScalar(
+ ? valueMarshaller.newParamDtoNonScalar(
actionParameter.getStaticFriendlyName()
.orElseThrow(_Exceptions::unexpectedCodeReach),
paramTypeOrElementType,
- arg,
- dtoContext)
- : CommonDtoUtils.newParamDto(
+ arg)
+ : valueMarshaller.newParamDtoScalar(
actionParameter.getStaticFriendlyName()
.orElseThrow(_Exceptions::unexpectedCodeReach),
paramTypeOrElementType,
- arg,
- dtoContext);
+ arg);
CommandDtoUtils.parametersFor(actionDto)
.getParameter()
@@ -158,9 +155,7 @@ public class CommandDtoFactoryDefault implements CommandDtoFactory {
val valueSpec = property.getElementType();
val valueType = valueSpec.getCorrespondingClass();
- val newValue = CommonDtoUtils.newValueWithTypeDto(
- valueType, UnwrapUtil.single(valueAdapter), dtoContext);
- propertyDto.setNewValue(newValue);
+ valueMarshaller.putValueInto(propertyDto, valueType, UnwrapUtil.single(valueAdapter));
}
// -- HELPER
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
index d74e376..69c6b5e 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/CommandExecutorServiceDefault.java
@@ -18,10 +18,19 @@
*/
package org.apache.isis.core.runtimeservices.command;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.log4j.Log4j2;
-import lombok.val;
+import java.sql.Timestamp;
+import java.util.List;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.bookmark.BookmarkService;
@@ -33,10 +42,10 @@ import org.apache.isis.applib.services.command.CommandOutcomeHandler;
import org.apache.isis.applib.services.iactn.Execution;
import org.apache.isis.applib.services.iactnlayer.InteractionLayerTracker;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.applib.services.sudo.SudoService;
import org.apache.isis.applib.services.xactn.TransactionService;
import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.functional.Result;
import org.apache.isis.commons.internal.base._NullSafe;
@@ -53,22 +62,20 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionMixedIn;
-import org.apache.isis.schema.cmd.v2.*;
+import org.apache.isis.schema.cmd.v2.ActionDto;
+import org.apache.isis.schema.cmd.v2.CommandDto;
+import org.apache.isis.schema.cmd.v2.MemberDto;
+import org.apache.isis.schema.cmd.v2.ParamDto;
+import org.apache.isis.schema.cmd.v2.ParamsDto;
+import org.apache.isis.schema.cmd.v2.PropertyDto;
import org.apache.isis.schema.common.v2.InteractionType;
import org.apache.isis.schema.common.v2.OidDto;
import org.apache.isis.schema.common.v2.OidsDto;
-import org.apache.isis.schema.common.v2.ValueWithTypeDto;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Service;
-import javax.annotation.Priority;
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.sql.Timestamp;
-import java.util.List;
-import java.util.Optional;
-import java.util.regex.Pattern;
-import java.util.stream.Stream;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.val;
+import lombok.extern.log4j.Log4j2;
@Service
@Named("isis.runtimeservices.CommandExecutorServiceDefault")
@@ -86,6 +93,7 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
@Inject final ClockService clockService;
@Inject final TransactionService transactionService;
@Inject final InteractionLayerTracker iInteractionLayerTracker;
+ @Inject final SchemaValueMarshaller valueMarshaller;
@Inject @Getter final InteractionService interactionService;
@Inject @Getter final SpecificationLoader specificationLoader;
@@ -234,7 +242,7 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
final OneToOneAssociation property = findOneToOneAssociation(targetAdapter, memberId);
- val newValueAdapter = newValueAdapterFor(propertyDto);
+ val newValueAdapter = recoverValueFrom(propertyDto);
property.set(targetAdapter, newValueAdapter, InteractionInitiatedBy.FRAMEWORK);
@@ -317,17 +325,23 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
return property;
}
- private static String localPartOf(String memberId) {
+ private static String localPartOf(final String memberId) {
val matcher = ID_PARSER.matcher(memberId);
return matcher.matches()
? matcher.group("localId")
: "";
}
- private ManagedObject newValueAdapterFor(final PropertyDto propertyDto) {
- final ValueWithTypeDto newValue = propertyDto.getNewValue();
- final Object arg = CommonDtoUtils.getValue(newValue);
- return adapterFor(arg);
+ private ManagedObject recoverValueFrom(final PropertyDto propertyDto) {
+ val newValue = valueMarshaller.recoverValueFrom(propertyDto);
+ return adapterFor(newValue);
+ }
+
+ private ManagedObject recoverValueFrom(
+ final ActionDto actionDto,
+ final ParamDto paramDto) {
+ val newValue = valueMarshaller.recoverValueFrom(actionDto.getLogicalMemberIdentifier(), paramDto);
+ return adapterFor(newValue);
}
private static ObjectAction findActionElseNull(
@@ -349,8 +363,7 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
private Can<ManagedObject> argAdaptersFor(final ActionDto actionDto) {
return streamParamDtosFrom(actionDto)
- .map(CommonDtoUtils::getValue)
- .map(this::adapterFor)
+ .map(paramDto->recoverValueFrom(actionDto, paramDto))
.collect(Can.toCan());
}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/DtoContextDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/DtoContextDefault.java
deleted file mode 100644
index af3dbdb..0000000
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/DtoContextDefault.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.apache.isis.core.runtimeservices.command;
-
-import javax.annotation.Priority;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.stereotype.Component;
-
-import org.apache.isis.applib.annotation.PriorityPrecedence;
-import org.apache.isis.applib.services.bookmark.BookmarkService;
-import org.apache.isis.applib.util.schema.DtoContext;
-import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-@Component
-@Named("isis.runtimeservices.DtoContextDefault")
-@Priority(PriorityPrecedence.MIDPOINT)
-@Qualifier("Default")
-@Getter(onMethod_ = {@Override})
-@RequiredArgsConstructor
-public class DtoContextDefault implements DtoContext {
-
- @Inject private BookmarkService bookmarkService;
- @Inject private ValueSemanticsResolver valueSemanticsResolver;
-
-}
diff --git a/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/SchemaValueMarshallerDefault.java
similarity index 52%
copy from api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
copy to core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/SchemaValueMarshallerDefault.java
index a4bd003..da6b5ea 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/util/schema/CommonDtoUtils.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/command/SchemaValueMarshallerDefault.java
@@ -1,22 +1,4 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.applib.util.schema;
+package org.apache.isis.core.runtimeservices.command;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -28,27 +10,33 @@ import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.lang.Nullable;
+import org.springframework.stereotype.Service;
+import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.applib.jaxb.JavaTimeXMLGregorianCalendarMarshalling;
import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.applib.value.Blob;
import org.apache.isis.applib.value.Clob;
+import org.apache.isis.applib.value.semantics.Converter;
+import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
+import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._NullSafe;
import org.apache.isis.commons.internal.base._Refs;
import org.apache.isis.commons.internal.base._Strings;
-import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.commons.internal.context._Context;
import org.apache.isis.commons.internal.exceptions._Exceptions;
-import org.apache.isis.schema.cmd.v2.MapDto;
import org.apache.isis.schema.cmd.v2.ParamDto;
+import org.apache.isis.schema.cmd.v2.PropertyDto;
import org.apache.isis.schema.common.v2.BlobDto;
import org.apache.isis.schema.common.v2.ClobDto;
import org.apache.isis.schema.common.v2.CollectionDto;
@@ -58,136 +46,182 @@ import org.apache.isis.schema.common.v2.TypedTupleDto;
import org.apache.isis.schema.common.v2.ValueDto;
import org.apache.isis.schema.common.v2.ValueType;
import org.apache.isis.schema.common.v2.ValueWithTypeDto;
-
-import static org.apache.isis.commons.internal.collections._Maps.entry;
+import org.apache.isis.schema.ixn.v2.ActionInvocationDto;
import lombok.NonNull;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import lombok.Value;
import lombok.val;
-/**
- * @since 1.x {@index}
- */
-public final class CommonDtoUtils {
-
- // -- PARAM_DTO_TO_NAME, PARAM_DTO_TO_TYPE
-
- public static final Function<ParamDto, String> PARAM_DTO_TO_NAME = ParamDto::getName;
- public static final Function<ParamDto, ValueType> PARAM_DTO_TO_TYPE = ParamDto::getType;
-
- // -- asValueType
- public static final Map<Class<?>, ValueType> valueTypeByClass =
- _Maps.unmodifiableEntries(
- entry(Void.class, ValueType.VOID),
- entry(String.class, ValueType.STRING),
- entry(byte.class, ValueType.BYTE),
- entry(Byte.class, ValueType.BYTE),
- entry(short.class, ValueType.SHORT),
- entry(Short.class, ValueType.SHORT),
- entry(int.class, ValueType.INT),
- entry(Integer.class, ValueType.INT),
- entry(long.class, ValueType.LONG),
- entry(Long.class, ValueType.LONG),
- entry(char.class, ValueType.CHAR),
- entry(Character.class, ValueType.CHAR),
- entry(boolean.class, ValueType.BOOLEAN),
- entry(Boolean.class, ValueType.BOOLEAN),
- entry(float.class, ValueType.FLOAT),
- entry(Float.class, ValueType.FLOAT),
- entry(double.class, ValueType.DOUBLE),
- entry(Double.class, ValueType.DOUBLE),
- entry(BigInteger.class, ValueType.BIG_INTEGER),
- entry(BigDecimal.class, ValueType.BIG_DECIMAL),
-
- // java.time
- entry(LocalDate.class, ValueType.LOCAL_DATE),
- entry(LocalDateTime.class, ValueType.LOCAL_DATE_TIME),
- entry(LocalTime.class, ValueType.LOCAL_TIME),
- entry(OffsetDateTime.class, ValueType.OFFSET_DATE_TIME),
- entry(OffsetTime.class, ValueType.OFFSET_TIME),
- entry(ZonedDateTime.class, ValueType.ZONED_DATE_TIME),
-
- entry(Blob.class, ValueType.BLOB),
- entry(Clob.class, ValueType.CLOB)
- );
-
- private static final Set<Class<?>> VALUE_TYPES = valueTypeByClass.keySet();
-
- public static ValueType asValueType(final @NonNull Class<?> type) {
- if(Iterable.class.isAssignableFrom(type)
- || type.isArray()) {
- return ValueType.COLLECTION;
- }
- final ValueType valueType = valueTypeByClass.get(type);
- if (valueType != null) {
- return valueType;
- }
- if (type.isEnum()) {
- return ValueType.ENUM;
- }
- // assume reference otherwise
- return ValueType.REFERENCE;
+@Service
+@Named("isis.runtimeservices.SchemaValueMarshallerDefault")
+@Priority(PriorityPrecedence.MIDPOINT)
+@Qualifier("Default")
+@RequiredArgsConstructor
+public class SchemaValueMarshallerDefault implements SchemaValueMarshaller {
+
+ @Inject private BookmarkService bookmarkService;
+ @Inject private ValueSemanticsResolver valueSemanticsResolver;
+
+ // -- RECOVER VALUES FROM DTO
+
+ @Override
+ public Object recoverValueFrom(final PropertyDto propertyDto) {
+ final ValueWithTypeDto valueWithTypeDto = propertyDto.getNewValue();
+ return recoverValue(valueWithTypeDto, this);
}
+ @Override
+ public Object recoverValueFrom(final String logicalMemberIdentifier, final ParamDto paramDto) {
+ return recoverValue(paramDto, this);
+ }
- // -- newValueDto, setValueOn
+ // -- PUT VALUES INTO DTO
+
+ @Override
+ public ActionInvocationDto putActionResult(
+ final ActionInvocationDto invocationDto,
+ final Class<?> returnType,
+ final Object result) {
+ final ValueTypeAndSemantics<?> valueTypeAndSemantics = resolve(this, returnType);
+ final ValueWithTypeDto returned = newValueWithTypeDto(valueTypeAndSemantics, result, this);
+ invocationDto.setReturned(returned);
+ return invocationDto;
+ }
- public static ValueDto newValueDto(
- final ValueType valueType,
- final Object value,
- final @NonNull DtoContext dtoContext) {
+ @Override
+ public PropertyDto putValueInto(
+ final PropertyDto propertyDto,
+ final Class<?> propertyType,
+ final Object valuePojo) {
+ final ValueTypeAndSemantics<?> valueTypeAndSemantics = resolve(this, propertyType);
+ final ValueWithTypeDto newValue = newValueWithTypeDto(valueTypeAndSemantics, valuePojo, this);
+ propertyDto.setNewValue(newValue);
+ return propertyDto;
+ }
- if(value == null) {
- return null;
- }
+ @Override
+ public ParamDto newParamDtoScalar(
+ final String parameterName,
+ final Class<?> paramType,
+ final Object valuePojo) {
+ val paramDto = new ParamDto();
+ paramDto.setName(parameterName);
+
+ final ValueTypeAndSemantics<?> valueTypeAndSemantics = resolve(this, paramType);
+
+// ValueType valueType = valueTypeAndSemantics.getValueType();
+//
+// // this hack preserves previous behaviour before we were able to serialize blobs and clobs into XML
+// // however, we also don't want this new behaviour for parameter arguments
+// // (else these large objects could end up being persisted).
+// if(valueType == ValueType.BLOB) valueType = ValueType.REFERENCE;
+// if(valueType == ValueType.CLOB) valueType = ValueType.REFERENCE;
+
+ paramDto.setType(valueTypeAndSemantics.getValueType());
+
+ putValueInto(paramDto, valueTypeAndSemantics, valuePojo, this);
- final ValueDto valueDto = new ValueDto();
- return setValueOn(valueDto, valueType, value, dtoContext);
+ return paramDto;
}
- public static <T extends ValueWithTypeDto> T setValueOn(
- final T valueWithTypeDto,
- final ValueType valueType,
- final Object value,
- final @NonNull DtoContext dtoContext) {
+ @Override
+ public ParamDto newParamDtoNonScalar(
+ final String parameterName,
+ final Class<?> paramElementType,
+ final Object valuePojo) {
+
+ val paramDto = new ParamDto();
+ paramDto.setName(parameterName);
+ paramDto.setType(ValueType.COLLECTION);
- valueWithTypeDto.setType(valueType);
+ ValueTypeAndSemantics<?> elementValueTypeAndSemantics = resolve(this, paramElementType);
- setValueOn((ValueDto)valueWithTypeDto, valueType, value, dtoContext);
- valueWithTypeDto.setNull(value == null);
+ setValueOnNonScalar(paramDto, elementValueTypeAndSemantics, valuePojo, this);
+
+ return paramDto;
- return valueWithTypeDto;
}
- public static <T extends ValueWithTypeDto> T setValueOnNonScalar(
- final T valueWithTypeDto,
- final ValueType elementValueType,
- final Object value,
- final @NonNull DtoContext dtoContext) {
+ // -- HELPER
- valueWithTypeDto.setType(ValueType.COLLECTION);
+ @Value(staticConstructor = "of")
+ private static class ValueTypeAndSemantics<T> {
+ final @NonNull ValueType valueType;
+ final @Nullable ValueSemanticsProvider<T> semantics;
- val collectionDto = asCollectionDto(value, elementValueType, dtoContext);
- valueWithTypeDto.setCollection(collectionDto);
- valueWithTypeDto.setNull(value == null);
+ private final static ValueTypeAndSemantics<Void> VOID = ValueTypeAndSemantics.of(ValueType.VOID, null);
+ public static ValueTypeAndSemantics<Void> empty() {
+ return VOID;
+ }
+
+ public Converter<T, ?> getConverter() {
+ return semantics!=null
+ ? semantics.getConverter()
+ : null;
+ }
+
+ }
+
+ private ValueTypeAndSemantics<?> resolve(
+ @NonNull final SchemaValueMarshaller valueMarshaller,
+ @NonNull final Class<?> type) {
+ return valueSemanticsResolver.selectValueSemantics(type)
+ .getFirst()
+ .map(valueSemantics->ValueTypeAndSemantics.of(valueSemantics.getSchemaValueType(), valueSemantics))
+ // assume reference otherwise
+ .orElseGet(()->ValueTypeAndSemantics.of(ValueType.REFERENCE, null));
+ }
+
+ private ValueTypeAndSemantics<?> resolve(
+ @NonNull final SchemaValueMarshaller valueMarshaller,
+ //@NonNull final Class<?> type,
+ final ParamDto paramDto) {
+ // TODO Auto-generated method stub
+
+ return ValueTypeAndSemantics.of(paramDto.getType(), null);
+ }
+
+ private ValueTypeAndSemantics<?> resolve(
+ @NonNull final SchemaValueMarshaller valueMarshaller,
+ //@NonNull final Class<?> type,
+ final ValueWithTypeDto valueWithTypeDto) {
+ // TODO Auto-generated method stub
+
+ return ValueTypeAndSemantics.of(valueWithTypeDto.getType(), null);
+ }
+
+ private ValueWithTypeDto newValueWithTypeDto(
+ final ValueTypeAndSemantics<?> valueTypeAndSemantics,
+ final Object valuePojo,
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
+
+ final ValueWithTypeDto valueWithTypeDto = new ValueWithTypeDto();
+ putValueInto(valueWithTypeDto, valueTypeAndSemantics, valuePojo, valueMarshaller);
return valueWithTypeDto;
}
- public static <T extends ValueDto> T setValueOn(
+ private <T extends ValueDto> T putValueInto(
final T valueDto,
- final ValueType valueType,
+ final ValueTypeAndSemantics<?> valueTypeAndSemantics,
final Object pojo,
- final @NonNull DtoContext dtoContext) {
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
+
+ val valueType = valueTypeAndSemantics.getValueType();
+ val semantics = valueTypeAndSemantics.getSemantics();
+ val converter = valueTypeAndSemantics.getConverter();
switch (valueType) {
case COLLECTION: {
final CollectionDto collectionDto = asCollectionDto(
- pojo, ValueType.VOID, dtoContext);
+ pojo, ValueTypeAndSemantics.empty(), valueMarshaller);
valueDto.setCollection(collectionDto);
return valueDto;
}
case COMPOSITE: {
- final TypedTupleDto typedTupleDto = asTypedTupleDto(pojo, dtoContext);
+ final TypedTupleDto typedTupleDto = asTypedTupleDto(pojo, valueMarshaller);
valueDto.setComposite(typedTupleDto);
return valueDto;
}
@@ -248,32 +282,34 @@ public final class CommonDtoUtils {
}
case LOCAL_DATE: {
final LocalDate argValue = (LocalDate) pojo;
- valueDto.setLocalDate(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
+ valueDto.setLocalDate(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(argValue));
return valueDto;
}
case LOCAL_TIME: {
final LocalTime argValue = (LocalTime) pojo;
- valueDto.setLocalTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
+ valueDto.setLocalTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(argValue));
return valueDto;
}
case LOCAL_DATE_TIME: {
- final LocalDateTime argValue = (LocalDateTime) pojo;
- valueDto.setLocalDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
+ final LocalDateTime argValue = converter!=null
+ ? (LocalDateTime) converter.toDelegateValue(_Casts.uncheckedCast(pojo))
+ : (LocalDateTime) pojo;
+ valueDto.setLocalDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(argValue));
return valueDto;
}
case OFFSET_DATE_TIME: {
final OffsetDateTime argValue = (OffsetDateTime) pojo;
- valueDto.setOffsetDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
+ valueDto.setOffsetDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(argValue));
return valueDto;
}
case OFFSET_TIME: {
final OffsetTime argValue = (OffsetTime) pojo;
- valueDto.setOffsetTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
+ valueDto.setOffsetTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(argValue));
return valueDto;
}
case ZONED_DATE_TIME: {
final ZonedDateTime argValue = (ZonedDateTime) pojo;
- valueDto.setZonedDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar2(argValue));
+ valueDto.setZonedDateTime(JavaTimeXMLGregorianCalendarMarshalling.toXMLGregorianCalendar(argValue));
return valueDto;
}
case ENUM: {
@@ -290,8 +326,8 @@ public final class CommonDtoUtils {
case REFERENCE: {
final Bookmark bookmark = pojo instanceof Bookmark
? (Bookmark) pojo
- : dtoContext.getBookmarkService()!=null
- ? dtoContext.getBookmarkService().bookmarkFor(pojo).orElse(null)
+ : bookmarkService!=null
+ ? bookmarkService.bookmarkFor(pojo).orElse(null)
: null;
if (bookmark != null) {
@@ -330,11 +366,28 @@ public final class CommonDtoUtils {
}
}
- private static CollectionDto asCollectionDto(
+ @Deprecated
+ private <T extends ValueWithTypeDto> T setValueOnNonScalar(
+ final T valueWithTypeDto,
+ final ValueTypeAndSemantics<?> elementValueTypeAndSemantics,
+ final Object value,
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
+
+ valueWithTypeDto.setType(ValueType.COLLECTION);
+
+ val collectionDto = asCollectionDto(value, elementValueTypeAndSemantics, valueMarshaller);
+ valueWithTypeDto.setCollection(collectionDto);
+ valueWithTypeDto.setNull(value == null);
+
+ return valueWithTypeDto;
+ }
+
+ private CollectionDto asCollectionDto(
final @Nullable Object iterableOrArray,
- final @NonNull ValueType commonElementValueType,
- final @NonNull DtoContext dtoContext) {
+ final @NonNull ValueTypeAndSemantics<?> commonElementValueTypeAndSemantics,
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
+ val commonElementValueType = commonElementValueTypeAndSemantics.getValueType();
val collectionDto = new CollectionDto();
collectionDto.setType(commonElementValueType);
@@ -346,13 +399,14 @@ public final class CommonDtoUtils {
.forEach(element->{
val valueDto = new ValueDto();
if(element==null) {
- setValueOn(valueDto, ValueType.VOID, element, dtoContext);
+ putValueInto(valueDto, ValueTypeAndSemantics.empty(), element, valueMarshaller);
} else {
- val elementValueType = asValueType(element.getClass());
- setValueOn(valueDto, elementValueType, element, dtoContext);
+ ValueTypeAndSemantics<?> elementValueTypeAndSemantics =
+ resolve(valueMarshaller, element.getClass());
+ putValueInto(valueDto, elementValueTypeAndSemantics, element, valueMarshaller);
if(needsCommonElementValueTypeAutodetect) {
- commonElementValueTypeRef.update(acc->reduce(acc, elementValueType));
+ commonElementValueTypeRef.update(acc->reduce(acc, elementValueTypeAndSemantics.getValueType()));
}
}
@@ -366,35 +420,52 @@ public final class CommonDtoUtils {
return collectionDto;
}
+ private static ValueType reduce(final ValueType acc, final ValueType next) {
+ if(acc==null) {
+ return next;
+ }
+ if(acc==next) {
+ return acc;
+ }
+ throw _Exceptions.unsupportedOperation("mixing types within a collection is not supported yet");
+ }
+
private static TypedTupleDto asTypedTupleDto(
final @Nullable Object composite,
- final @NonNull DtoContext dtoContext) {
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
val typedTupleDto = new TypedTupleDto();
//TODO implement
return typedTupleDto;
}
- // -- getValue (from valueDto)
+ // -- HELPER - RECOVERY
- private static ValueType reduce(final ValueType acc, final ValueType next) {
- if(acc==null) {
- return next;
- }
- if(acc==next) {
- return acc;
+ private <T> T recoverValue(
+ final ValueWithTypeDto valueWithTypeDto,
+ final @NonNull SchemaValueMarshaller valueMarshaller) {
+ if(valueWithTypeDto==null
+ || (valueWithTypeDto.isSetNull()
+ && valueWithTypeDto.isNull())) {
+ return null;
}
- throw _Exceptions.unsupportedOperation("mixing types within a collection is not supported yet");
+ return recoverValue(valueWithTypeDto, resolve(valueMarshaller, valueWithTypeDto));
}
- public static <T> T getValue(
+ private static <T> T recoverValue(
final ValueDto valueDto,
- final ValueType valueType) {
- return _Casts.uncheckedCast(getValueAsObject(valueDto, valueType));
+ final @NonNull ValueTypeAndSemantics<?> valueTypeAndSemantics) {
+ return _Casts.uncheckedCast(recoverValueAsObject(valueDto, valueTypeAndSemantics));
}
- private static Object getValueAsObject(
+ @SneakyThrows
+ private static Object recoverValueAsObject(
final ValueDto valueDto,
- final ValueType valueType) {
+ final ValueTypeAndSemantics<?> valueTypeAndSemantics) {
+
+ val valueType = valueTypeAndSemantics.getValueType();
+ //val semantics = valueTypeAndSemantics.getSemantics();
+ //val converter = valueTypeAndSemantics.getConverter();
+
switch(valueType) {
case STRING:
return valueDto.getString();
@@ -420,7 +491,6 @@ public final class CommonDtoUtils {
return valueDto.getBigDecimal();
case BIG_INTEGER:
return valueDto.getBigInteger();
- // JAVA TIME
case LOCAL_DATE:
return JavaTimeXMLGregorianCalendarMarshalling.toLocalDate(valueDto.getLocalDate());
case LOCAL_TIME:
@@ -433,13 +503,12 @@ public final class CommonDtoUtils {
return JavaTimeXMLGregorianCalendarMarshalling.toOffsetTime(valueDto.getOffsetTime());
case ZONED_DATE_TIME:
return JavaTimeXMLGregorianCalendarMarshalling.toZonedDateTime(valueDto.getZonedDateTime());
-// case JAVA_SQL_TIMESTAMP:
-// return JavaSqlXMLGregorianCalendarMarshalling.toTimestamp(valueDto.getTimestamp());
case ENUM:
final EnumDto enumDto = valueDto.getEnum();
final String enumType = enumDto.getEnumType();
@SuppressWarnings("rawtypes")
- final Class<? extends Enum> enumClass = loadClassElseThrow(enumType);
+ final Class<? extends Enum> enumClass =
+ _Casts.uncheckedCast(_Context.loadClassAndInitialize(enumType));
return Enum.valueOf(_Casts.uncheckedCast(enumClass), enumDto.getEnumName());
case REFERENCE:
return valueDto.getReference();
@@ -454,11 +523,12 @@ public final class CommonDtoUtils {
for(val elementValueDto : collectionDto.getValue()) {
- if(elementValueDto instanceof ValueWithTypeDto) {
- list.add(getValueAsObject(elementValueDto, ((ValueWithTypeDto)elementValueDto).getType()));
- } else {
- list.add(getValueAsObject(elementValueDto, elementValueType));
- }
+ //FIXME[ISIS-2877]
+// if(elementValueDto instanceof ValueWithTypeDto) {
+// list.add(getValueAsObject(elementValueDto, ((ValueWithTypeDto)elementValueDto).getType()));
+// } else {
+// list.add(getValueAsObject(elementValueDto, elementValueType));
+// }
}
return list;
@@ -475,140 +545,5 @@ public final class CommonDtoUtils {
}
}
- private static <T> Class<T> loadClassElseThrow(final String className) {
- try {
- return _Casts.uncheckedCast(_Context.loadClassAndInitialize(className));
- } catch (ClassNotFoundException e) {
-
- // [ahuber] fallback to pre 2.0.0 behavior, not sure if needed
- try {
- return _Casts.uncheckedCast(Class.forName(className));
- } catch (ClassNotFoundException e1) {
- throw new RuntimeException(e);
- }
- }
- }
-
-
-
- // -- newValueWithTypeDto
-
-
- public static ValueWithTypeDto newValueWithTypeDto(
- final Class<?> type,
- final Object val,
- final @NonNull DtoContext dtoContext) {
-
- final ValueWithTypeDto valueWithTypeDto = new ValueWithTypeDto();
-
- final ValueType valueType = asValueType(type);
- setValueOn(valueWithTypeDto, valueType, val, dtoContext);
-
- return valueWithTypeDto;
- }
-
-
-
- // -- getValue (from ValueWithTypeDto)
-
- public static <T> T getValue(final ValueWithTypeDto valueWithTypeDto) {
- if(valueWithTypeDto.isNull()) {
- return null;
- }
- final ValueType type = valueWithTypeDto.getType();
- return CommonDtoUtils.getValue(valueWithTypeDto, type);
- }
-
-
-
-
-
- // -- newParamDto
-
- public static ParamDto newParamDto(
- final String parameterName,
- final Class<?> parameterType,
- final Object arg,
- final @NonNull DtoContext dtoContext) {
-
- val paramDto = new ParamDto();
- paramDto.setName(parameterName);
-
- ValueType valueType = CommonDtoUtils.asValueType(parameterType);
- // this hack preserves previous behaviour before we were able to serialize blobs and clobs into XML
- // however, we also don't want this new behaviour for parameter arguments
- // (else these large objects could end up being persisted).
- if(valueType == ValueType.BLOB) valueType = ValueType.REFERENCE;
- if(valueType == ValueType.CLOB) valueType = ValueType.REFERENCE;
-
- paramDto.setType(valueType);
-
- CommonDtoUtils.setValueOn(paramDto, valueType, arg, dtoContext);
-
- return paramDto;
- }
-
- public static ParamDto newParamDtoNonScalar(
- final String parameterName,
- final Class<?> parameterElementType,
- final Object arg,
- final @NonNull DtoContext dtoContext) {
-
- val paramDto = new ParamDto();
- paramDto.setName(parameterName);
- paramDto.setType(ValueType.COLLECTION);
-
- val elementValueType = CommonDtoUtils.asValueType(parameterElementType);
- CommonDtoUtils.setValueOnNonScalar(paramDto, elementValueType, arg, dtoContext);
-
- return paramDto;
- }
-
-
- // -- getValue (from ParamDto)
-
- public static <T> T getValue(final ParamDto paramDto) {
- if(paramDto.isNull()) {
- return null;
- }
- final ValueType parameterType = paramDto.getType();
- return CommonDtoUtils.getValue(paramDto, parameterType);
- }
-
-
-
- public static String getMapValue(final MapDto mapDto, final String key) {
- if(mapDto == null) {
- return null;
- }
- final Optional<MapDto.Entry> entryIfAny = entryIfAnyFor(mapDto, key);
- return entryIfAny.map(MapDto.Entry::getValue).orElse(null);
- }
-
- public static void putMapKeyValue(final MapDto mapDto, final String key, final String value) {
- if(mapDto == null) {
- return;
- }
- final Optional<MapDto.Entry> entryIfAny = entryIfAnyFor(mapDto, key);
- if(entryIfAny.isPresent()) {
- entryIfAny.get().setValue(value);
- } else {
- val entry = new MapDto.Entry();
- entry.setKey(key);
- entry.setValue(value);
- mapDto.getEntry().add(entry);
- }
- }
-
- private static Optional<MapDto.Entry> entryIfAnyFor(final MapDto mapDto, final String key) {
- return mapDto.getEntry().stream()
- .filter(entry->Objects.equals(entry.getKey(), key))
- .findFirst();
- }
-
-
- public static boolean isValueType(final Class<?> type) {
- return VALUE_TYPES.contains(type);
- }
}
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/interaction/InteractionDtoFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/interaction/InteractionDtoFactoryDefault.java
index 9fd5bd2..b606025 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/interaction/InteractionDtoFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/interaction/InteractionDtoFactoryDefault.java
@@ -31,9 +31,9 @@ import org.apache.isis.applib.annotation.PriorityPrecedence;
import org.apache.isis.applib.services.bookmark.Bookmark;
import org.apache.isis.applib.services.iactn.Interaction;
import org.apache.isis.applib.services.iactn.InteractionProvider;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
import org.apache.isis.applib.services.user.UserService;
import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.applib.util.schema.DtoContext;
import org.apache.isis.applib.util.schema.InteractionDtoUtils;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.assertions._Assert;
@@ -68,7 +68,7 @@ import lombok.val;
public class InteractionDtoFactoryDefault implements InteractionDtoFactory {
@Inject private CommandDtoFactory commandDtoServiceInternal;
- @Inject private DtoContext dtoContext;
+ @Inject private SchemaValueMarshaller valueMarshaller;
@Inject private javax.inject.Provider<InteractionProvider> interactionProviderProvider;
@Inject private UserService userService;
@@ -114,7 +114,7 @@ public class InteractionDtoFactoryDefault implements InteractionDtoFactory {
final Class<?> returnType = returnSpec.getCorrespondingClass();
InteractionDtoUtils.addReturn(
- actionInvocationDto, returnType, resultPojo, dtoContext);
+ actionInvocationDto, returnType, resultPojo, valueMarshaller);
return actionInvocationDto;
}
diff --git a/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ResponseDigest.java b/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ResponseDigest.java
index bd7a671..5556294 100644
--- a/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ResponseDigest.java
+++ b/mappings/restclient/applib/src/main/java/org/apache/isis/extensions/restclient/ResponseDigest.java
@@ -28,7 +28,6 @@ import java.util.Optional;
import java.util.concurrent.Future;
import java.util.function.Function;
-import org.springframework.lang.Nullable;
import javax.ws.rs.core.GenericType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status.Family;
@@ -37,8 +36,9 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.lang.Nullable;
+
import org.apache.isis.applib.client.RepresentationTypeSimplifiedV2;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._Strings;
@@ -107,7 +107,7 @@ public class ResponseDigest<T> {
private Exception failureCause;
- protected ResponseDigest(Response response, Class<T> entityType, GenericType<List<T>> genericType) {
+ protected ResponseDigest(final Response response, final Class<T> entityType, final GenericType<List<T>> genericType) {
this.response = response;
this.entityType = entityType;
this.genericType = genericType;
@@ -152,7 +152,7 @@ public class ResponseDigest<T> {
* @param failureMapper - fallback, to calculate a result from given failure exception
* @return the result if cardinality is exactly ONE, otherwise the result of applying the failure to the {@code failureMapper}
*/
- public T singletonOrElseMapFailure(Function<Exception, T> failureMapper) {
+ public T singletonOrElseMapFailure(final Function<Exception, T> failureMapper) {
return isSuccess()
? getEntity().orElseGet(()->failureMapper.apply(new NoSuchElementException()))
: failureMapper.apply(getFailureCause());
@@ -162,10 +162,10 @@ public class ResponseDigest<T> {
* @param failureMapper - fallback, to calculate a result from given failure exception
* @return the result of any cardinality, otherwise the result of applying the failure to the {@code failureMapper}
*/
- public Can<T> multipleOrElseMapFailure(Function<Exception, Can<T>> failureMapper) {
+ public Can<T> multipleOrElseMapFailure(final Function<Exception, Can<T>> failureMapper) {
return isSuccess()
? getEntities()
- : failureMapper.apply(getFailureCause());
+ : failureMapper.apply(getFailureCause());
}
// -- HELPER
@@ -235,7 +235,7 @@ public class ResponseDigest<T> {
log.debug("readSingle({})", reprType);
if(reprType.isValue()
- || isValueType(entityType)) {
+ || reprType.isValues()) {
val mapper = new ObjectMapper();
val jsonInput = response.readEntity(String.class);
val scalarValueDto = mapper.readValue(jsonInput, ScalarValueDtoV2.class);
@@ -250,7 +250,7 @@ public class ResponseDigest<T> {
log.debug("readList({})", reprType);
if(reprType.isValues()
- || isValueType(entityType)) {
+ || reprType.isValue()) {
val mapper = new ObjectMapper();
val jsonInput = response.readEntity(String.class);
final List<ScalarValueDtoV2> scalarValueDtoList =
@@ -269,7 +269,7 @@ public class ResponseDigest<T> {
return response.readEntity(genericType);
}
- private ResponseDigest<T> digestAsyncFailure(boolean isCancelled, Exception failure) {
+ private ResponseDigest<T> digestAsyncFailure(final boolean isCancelled, final Exception failure) {
entities = Can.empty();
@@ -289,7 +289,7 @@ public class ResponseDigest<T> {
}
- private String defaultFailureMessage(Response response) {
+ private String defaultFailureMessage(final Response response) {
String failureMessage = "non-successful JAX-RS response: " +
String.format("%s (Http-Status-Code: %d)",
response.getStatusInfo().getReasonPhrase(),
@@ -309,11 +309,7 @@ public class ResponseDigest<T> {
// -- VALUE TYPE HANDLING
- private boolean isValueType(Class<T> entityType) {
- return CommonDtoUtils.isValueType(entityType);
- }
-
- private T extractValue(ScalarValueDtoV2 scalarValueDto)
+ private T extractValue(final ScalarValueDtoV2 scalarValueDto)
throws JsonParseException, JsonMappingException, IOException {
return _Casts.uncheckedCast(scalarValueDto.getValue());
}
diff --git a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
index 5b2e80d..9569b0b 100644
--- a/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
+++ b/regressiontests/stable-value/src/test/java/org/apache/isis/testdomain/value/ValueSemanticsTest.java
@@ -41,11 +41,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.isis.applib.annotation.Where;
import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.command.Command;
import org.apache.isis.applib.services.iactnlayer.InteractionContext;
import org.apache.isis.applib.services.iactnlayer.InteractionService;
import org.apache.isis.applib.services.inject.ServiceInjector;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
+import org.apache.isis.applib.services.schema.SchemaValueMarshaller;
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.ValueSemanticsProvider;
import org.apache.isis.applib.value.semantics.ValueSemanticsResolver;
import org.apache.isis.commons.internal.collections._Sets;
import org.apache.isis.core.config.presets.IsisPresets;
@@ -59,6 +64,7 @@ import org.apache.isis.testdomain.model.valuetypes.Configuration_usingValueTypes
import org.apache.isis.testdomain.model.valuetypes.ValueTypeExample;
import org.apache.isis.testdomain.model.valuetypes.ValueTypeExampleService;
import org.apache.isis.testdomain.model.valuetypes.ValueTypeExampleService.Scenario;
+import org.apache.isis.testdomain.value.ValueSemanticsTester.PropertyInteractionProbe;
import lombok.val;
@@ -77,6 +83,28 @@ import lombok.val;
@TestInstance(Lifecycle.PER_CLASS)
class ValueSemanticsTest {
+ @Test @Disabled
+ void fullTypeCoverage() {
+
+ valueSemanticsResolver.streamClassesWithValueSemantics()
+ .forEach(valueType->System.err.printf("%s%n", valueType.getName()));
+
+ final Set<Class<?>> valueTypesCovered = valueTypeExampleProvider.streamExamples()
+ .map(ValueTypeExample::getValueType)
+ .collect(Collectors.toSet());
+
+ final Set<Class<?>> valueTypesKnown = valueSemanticsResolver.streamClassesWithValueSemantics()
+ .collect(Collectors.toSet());
+
+ val valueTypesNotCovered = _Sets.minus(valueTypesKnown, valueTypesCovered);
+
+ assertTrue(valueTypesNotCovered.isEmpty(), ()->
+ String.format("value-types not covered by tests:\n\t%s",
+ valueTypesNotCovered.stream()
+ .map(Class::getName)
+ .collect(Collectors.joining("\n\t"))));
+ }
+
@ParameterizedTest(name = "{index} {0}")
@MethodSource("provideValueTypeExamples")
<T> void valueTypes(
@@ -91,122 +119,114 @@ class ValueSemanticsTest {
tester.propertyInteraction("value",
interactionContext(),
managedProp->example.getUpdateValue(),
- (context, composer)->{
-
- val valueMixin = composer.getValueMixin(example.getValue());
- if(valueMixin!=null) {
+ new PropertyInteractionProbe<T>() {
- val spec = specLoader.specForTypeElseFail(valueMixin.getClass());
- val interaction = ActionInteraction
- .start(ManagedObject.of(spec, valueMixin), "act", Where.ANYWHERE);
+ @Override
+ public void testEncoderDecoder(
+ final ValueSemanticsProvider.Context context,
+ final EncoderDecoder<T> composer) {
+ val valueMixin = composer.getValueMixin(example.getValue());
+ if(valueMixin!=null) {
- val pendingParams = interaction
- .startParameterNegotiation()
- .get();
+ val spec = specLoader.specForTypeElseFail(valueMixin.getClass());
+ val interaction = ActionInteraction
+ .start(ManagedObject.of(spec, valueMixin), "act", Where.ANYWHERE);
- val managedAction = interaction.getManagedActionElseFail();
- val typedTuple = pendingParams.getParamValues();
-
- val recoveredValue = managedAction
- .invoke(typedTuple, InteractionInitiatedBy.PASS_THROUGH)
- .leftIfAny()
- .getPojo();
-
- tester.assertValueEquals(
- example.getValue(),
- recoveredValue,
- "serialization roundtrip failed");
-
- return;
- }
+ val pendingParams = interaction
+ .startParameterNegotiation()
+ .get();
- // CoderDecoder round-trip test
- val serialized = composer.toEncodedString(example.getValue());
+ val managedAction = interaction.getManagedActionElseFail();
+ val typedTuple = pendingParams.getParamValues();
- tester.assertValueEquals(
- example.getValue(),
- composer.fromEncodedString(serialized),
- "serialization roundtrip failed");
+ val recoveredValue = managedAction
+ .invoke(typedTuple, InteractionInitiatedBy.PASS_THROUGH)
+ .leftIfAny()
+ .getPojo();
- },
- (context, parser)->{
+ tester.assertValueEquals(
+ example.getValue(),
+ recoveredValue,
+ "serialization roundtrip failed");
- // Parser round-trip test
- val stringified = parser.parseableTextRepresentation(context, example.getValue());
+ return;
+ }
- if(valueType.equals(Password.class)) {
- val recoveredValue = (Password)parser.parseTextRepresentation(context, stringified);
- assertTrue(recoveredValue.checkPassword("*"));
-
- } else {
-
- System.err.printf("using %s trying to parse '%s'%n", valueType.getName(), stringified);
+ // CoderDecoder round-trip test
+ val serialized = composer.toEncodedString(example.getValue());
tester.assertValueEquals(
example.getValue(),
- parser.parseTextRepresentation(context, stringified),
- "parser roundtrip failed");
+ composer.fromEncodedString(serialized),
+ "serialization roundtrip failed");
}
- },
- (context, renderer)->{
+ @Override
+ public void testParser(
+ final ValueSemanticsProvider.Context context,
+ final Parser<T> parser) {
+ // Parser round-trip test
+ val stringified = parser.parseableTextRepresentation(context, example.getValue());
- },
- (command, codec)->{
+ if(valueType.equals(Password.class)) {
+ val recoveredValue = (Password)parser.parseTextRepresentation(context, stringified);
+ assertTrue(recoveredValue.checkPassword("*"));
- val propertyDto = (PropertyDto)command.getCommandDto().getMember();
- val newValueRecordedDto = propertyDto.getNewValue();
+ } else {
- //TODO needs a codec to recover values that are not directly represented by the schema
- val newValueRecorded = CommonDtoUtils.getValue(newValueRecordedDto);
+ System.err.printf("using %s trying to parse '%s'%n", valueType.getName(), stringified);
- // TODO skip tests, because some value-types are not represented by the schema yet
- if(newValueRecorded==null
- || valueType.equals(Bookmark.class)) {
- System.err.printf("skipping command test on %s%n", valueType.getName());
- return;
+ tester.assertValueEquals(
+ example.getValue(),
+ parser.parseTextRepresentation(context, stringified),
+ "parser roundtrip failed");
+ }
}
+ @Override
+ public void testRenderer(
+ final ValueSemanticsProvider.Context context,
+ final Renderer<T> renderer) {
- assertEquals(valueType, newValueRecorded.getClass(), ()->
- String.format("command value parsing type mismatch '%s'",
- ValueSemanticsTester.valueDtoToXml(newValueRecordedDto)));
-
- tester.assertValueEquals(example.getUpdateValue(), newValueRecorded, "command failed");
-
-// //debug
-// System.err.printf("Value %s %s%n", name,
-// valueToXml(newValueRecordedDto));
-//
-// //debug
-// System.err.printf("CommandDto %s %s%n", name,
-// CommandDtoUtils.toXml(
-// command.getCommandDto()));
+ }
+ @Override
+ public void testCommand(
+ final ValueSemanticsProvider.Context context,
+ final Command command,
+ final EncoderDecoder<T> codec) {
+
+ val propertyDto = (PropertyDto)command.getCommandDto().getMember();
+ val newValueRecordedDto = propertyDto.getNewValue();
+
+ //TODO needs a codec to recover values that are not directly represented by the schema
+ val newValueRecorded = valueMarshaller.recoverValueFrom(propertyDto);
+ assertNotNull(newValueRecorded);
+
+ // TODO skip tests, because some value-types are not represented by the schema yet
+ if(newValueRecorded==null
+ || valueType.equals(Bookmark.class)) {
+ System.err.printf("skipping command test on %s%n", valueType.getName());
+ return;
+ }
+
+ assertEquals(valueType, newValueRecorded.getClass(), ()->
+ String.format("command value parsing type mismatch '%s'",
+ ValueSemanticsTester.valueDtoToXml(newValueRecordedDto)));
+
+ tester.assertValueEquals(example.getUpdateValue(), newValueRecorded, "command failed");
+
+// //debug
+// System.err.printf("Value %s %s%n", name,
+// valueToXml(newValueRecordedDto));
+ //
+// //debug
+// System.err.printf("CommandDto %s %s%n", name,
+// CommandDtoUtils.toXml(
+// command.getCommandDto()));
+ }
});
}
- @Test @Disabled
- void fullTypeCoverage() {
-
- valueSemanticsResolver.streamClassesWithValueSemantics()
- .forEach(valueType->System.err.printf("%s%n", valueType.getName()));
-
- final Set<Class<?>> valueTypesCovered = valueTypeExampleProvider.streamExamples()
- .map(ValueTypeExample::getValueType)
- .collect(Collectors.toSet());
-
- final Set<Class<?>> valueTypesKnown = valueSemanticsResolver.streamClassesWithValueSemantics()
- .collect(Collectors.toSet());
-
- val valueTypesNotCovered = _Sets.minus(valueTypesKnown, valueTypesCovered);
-
- assertTrue(valueTypesNotCovered.isEmpty(), ()->
- String.format("value-types not covered by tests:\n\t%s",
- valueTypesNotCovered.stream()
- .map(Class::getName)
- .collect(Collectors.joining("\n\t"))));
- }
-
// -- HELPER
private InteractionContext interactionContext() {
@@ -220,6 +240,7 @@ class ValueSemanticsTest {
@Inject InteractionService interactionService;
@Inject ServiceInjector serviceInjector;
@Inject ValueSemanticsResolver valueSemanticsResolver;
+ @Inject SchemaValueMarshaller valueMarshaller;
Stream<Arguments> provideValueTypeExamples() {
return valueTypeExampleProvider.streamScenarios()
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 f4b9770..a497efc 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
@@ -38,7 +38,6 @@ import org.apache.isis.applib.value.semantics.ValueSemanticsProvider;
import org.apache.isis.commons.internal.base._Casts;
import org.apache.isis.commons.internal.base._Refs;
import org.apache.isis.commons.internal.exceptions._Exceptions;
-import org.apache.isis.commons.internal.functions._Functions.CheckedBiConsumer;
import org.apache.isis.commons.internal.resources._Xml;
import org.apache.isis.commons.internal.resources._Xml.WriteOptions;
import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
@@ -73,15 +72,19 @@ public class ValueSemanticsTester<T> {
val act = objSpec.getActionElseFail(actionId);
}
+ public static interface PropertyInteractionProbe<T> {
+ void testEncoderDecoder(ValueSemanticsProvider.Context context, EncoderDecoder<T> codec);
+ void testParser(ValueSemanticsProvider.Context context, Parser<T> parser);
+ void testRenderer(ValueSemanticsProvider.Context context, Renderer<T> renderer);
+ void testCommand(ValueSemanticsProvider.Context context, Command command, EncoderDecoder<T> codec);
+ }
+
@SneakyThrows
public void propertyInteraction(
final @NonNull String propertyId,
final @NonNull InteractionContext interactionContext,
final @NonNull Function<ManagedProperty, Object> newProperyValueProvider,
- final @NonNull CheckedBiConsumer<ValueSemanticsProvider.Context, EncoderDecoder<T>> codecCallback,
- final @NonNull CheckedBiConsumer<ValueSemanticsProvider.Context, Parser<T>> parserCallback,
- final @NonNull CheckedBiConsumer<ValueSemanticsProvider.Context, Renderer<T>> renderCallback,
- final @NonNull CheckedBiConsumer<Command, EncoderDecoder<T>> commandCallback) {
+ final @NonNull PropertyInteractionProbe<T> probe) {
val objSpec = specLoader.specForTypeElseFail(domainObject.getClass());
val prop = objSpec.getPropertyElseFail(propertyId);
@@ -91,16 +94,16 @@ public class ValueSemanticsTester<T> {
val codec = codec(prop);
- codecCallback.accept(context, codec);
+ probe.testEncoderDecoder(context, codec);
val parserIfAny = parser(prop);
if(parserIfAny.isPresent()) {
- parserCallback.accept(context, parserIfAny.get());
+ probe.testParser(context, parserIfAny.get());
}
val rendererIfAny = renderer(prop);
if(rendererIfAny.isPresent()) {
- renderCallback.accept(context, rendererIfAny.get());
+ probe.testRenderer(context, rendererIfAny.get());
}
interactionService.run(interactionContext, ()->{
@@ -113,7 +116,7 @@ public class ValueSemanticsTester<T> {
propInteraction.modifyProperty(managedProp->
ManagedObject.of(managedProp.getElementType(), newProperyValueProvider.apply(managedProp)));
- commandCallback.accept(command, codec);
+ probe.testCommand(context, command, codec);
});
}
diff --git a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaDateTimeValueSemantics.java b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaDateTimeValueSemantics.java
index af50dfa..1152e6e 100644
--- a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaDateTimeValueSemantics.java
+++ b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaDateTimeValueSemantics.java
@@ -29,7 +29,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.ZonedDateTimeValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
import org.apache.isis.valuetypes.jodatime.applib.value.JodaTimeConverters;
@Component
@@ -45,11 +44,6 @@ extends TemporalSemanticsAdapter<org.joda.time.DateTime, ZonedDateTime> {
}
@Override
- public ValueType getSchemaValueType() {
- return ValueType.ZONED_DATE_TIME;
- }
-
- @Override
public ValueSemanticsAbstract<ZonedDateTime> getDelegate() {
return zonedDateTimeValueSemantics;
}
diff --git a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateTimeValueSemantics.java b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateTimeValueSemantics.java
index c019ca0..f97d789 100644
--- a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateTimeValueSemantics.java
+++ b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateTimeValueSemantics.java
@@ -26,7 +26,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateTimeValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
import org.apache.isis.valuetypes.jodatime.applib.value.JodaTimeConverters;
@Component
@@ -42,11 +41,6 @@ extends TemporalSemanticsAdapter<org.joda.time.LocalDateTime, java.time.LocalDat
}
@Override
- public ValueType getSchemaValueType() {
- return ValueType.LOCAL_DATE_TIME;
- }
-
- @Override
public ValueSemanticsAbstract<java.time.LocalDateTime> getDelegate() {
return localDateTimeValueSemantics;
}
diff --git a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateValueSemantics.java b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateValueSemantics.java
index c7f36c1..b37c6f9 100644
--- a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateValueSemantics.java
+++ b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalDateValueSemantics.java
@@ -26,7 +26,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalDateValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
import org.apache.isis.valuetypes.jodatime.applib.value.JodaTimeConverters;
@Component
@@ -42,11 +41,6 @@ extends TemporalSemanticsAdapter<org.joda.time.LocalDate, java.time.LocalDate>
}
@Override
- public ValueType getSchemaValueType() {
- return ValueType.LOCAL_DATE;
- }
-
- @Override
public ValueSemanticsAbstract<java.time.LocalDate> getDelegate() {
return localDateValueSemantics;
}
diff --git a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalTimeValueSemantics.java b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalTimeValueSemantics.java
index 84feff4..bc9b0d9 100644
--- a/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalTimeValueSemantics.java
+++ b/valuetypes/jodatime/integration/src/main/java/org/apache/isis/valuetypes/jodatime/integration/valuesemantics/JodaLocalTimeValueSemantics.java
@@ -26,7 +26,6 @@ import org.springframework.stereotype.Component;
import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract;
import org.apache.isis.core.metamodel.valuesemantics.temporal.LocalTimeValueSemantics;
import org.apache.isis.core.metamodel.valuetypes.TemporalSemanticsAdapter;
-import org.apache.isis.schema.common.v2.ValueType;
import org.apache.isis.valuetypes.jodatime.applib.value.JodaTimeConverters;
@Component
@@ -42,11 +41,6 @@ extends TemporalSemanticsAdapter<org.joda.time.LocalTime, java.time.LocalTime>
}
@Override
- public ValueType getSchemaValueType() {
- return ValueType.LOCAL_TIME;
- }
-
- @Override
public ValueSemanticsAbstract<java.time.LocalTime> getDelegate() {
return localTimeValueSemantics;
}