This is an automated email from the ASF dual-hosted git repository. ahuber pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push: new fd051ec11a ISIS-3167: activates ManagedObject for VALUE fd051ec11a is described below commit fd051ec11a2899f3d6fd46bb68df2482bab8c68e Author: Andi Huber <ahu...@apache.org> AuthorDate: Tue Aug 30 13:32:18 2022 +0200 ISIS-3167: activates ManagedObject for VALUE - purge ObjectSpecification mockery --- .../_testing/MetaModelContext_forTesting.java | 43 +- .../isis/core/metamodel/commons/ClassUtil.java | 4 +- ...ionOrAnyMatchingValueSemanticsFacetFactory.java | 48 ++- .../isis/core/metamodel/object/ManagedObject.java | 4 +- .../core/metamodel/object/MmAssertionUtil.java | 6 +- .../metamodel/object/_ManagedObjectSpecified.java | 15 +- .../classsubstitutor/ClassSubstitutor.java | 6 +- .../classsubstitutor/ClassSubstitutorRegistry.java | 3 +- .../core/metamodel/spec/ObjectSpecification.java | 22 +- .../specloader/SpecificationLoaderDefault.java | 17 +- .../specimpl/ObjectSpecificationAbstract.java | 9 - .../apache/isis/core/metamodel/util/Facets.java | 16 +- .../metamodel/facets/AbstractFacetFactoryTest.java | 16 - .../actions/ActionMethodsFacetFactoryTest.java | 21 +- ...nnotationFacetFactoryTest_ActionInvocation.java | 36 +- .../CollectionFieldMethodsFacetFactoryTest.java | 16 +- ...ollectionAnnotationFacetFactoryTest_typeOf.java | 22 - .../PropertyMethodsFacetFactoryTest.java | 11 +- .../testspec/ObjectSpecificationStub.java | 404 ------------------- .../testdomain/interact/NewParameterModelTest.java | 1 + .../domainobjects/JsonValueEncoderTest.java | 232 +++++++++++ .../JsonValueEncoderTestAbstract.java | 63 +++ .../JsonValueEncoderTest_asAdapter.java | 447 --------------------- .../JsonValueEncoderTest_asObject.java | 64 --- 24 files changed, 434 insertions(+), 1092 deletions(-) diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java index 08eca038d5..b8864ec3ff 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/MetaModelContext_forTesting.java @@ -19,7 +19,6 @@ package org.apache.isis.core.metamodel._testing; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -30,6 +29,7 @@ import java.util.stream.Stream; import static java.util.Objects.requireNonNull; import org.springframework.core.env.AbstractEnvironment; +import org.springframework.util.ClassUtils; import org.apache.isis.applib.services.factory.FactoryService; import org.apache.isis.applib.services.grid.GridLoaderService; @@ -53,7 +53,6 @@ import org.apache.isis.applib.value.semantics.ValueSemanticsAbstract; import org.apache.isis.applib.value.semantics.ValueSemanticsProvider; import org.apache.isis.applib.value.semantics.ValueSemanticsResolver; import org.apache.isis.commons.collections.Can; -import org.apache.isis.commons.internal.assertions._Assert; import org.apache.isis.commons.internal.base._Lazy; import org.apache.isis.commons.internal.base._NullSafe; import org.apache.isis.commons.internal.base._Strings; @@ -69,13 +68,11 @@ import org.apache.isis.core.config.beans.IsisBeanTypeRegistry; import org.apache.isis.core.config.beans.IsisBeanTypeRegistryDefault; import org.apache.isis.core.config.environment.IsisSystemEnvironment; import org.apache.isis.core.config.progmodel.ProgrammingModelConstants; +import org.apache.isis.core.metamodel.commons.ClassUtil; import org.apache.isis.core.metamodel.context.MetaModelContext; import org.apache.isis.core.metamodel.execution.MemberExecutorService; import org.apache.isis.core.metamodel.facets.object.icon.ObjectIconService; -import org.apache.isis.core.metamodel.facets.object.title.TitleFacet; -import org.apache.isis.core.metamodel.facets.object.title.parser.TitleFacetFromValueFacet; -import org.apache.isis.core.metamodel.facets.object.value.ValueFacet; -import org.apache.isis.core.metamodel.facets.object.value.vsp.ValueFacetUsingSemanticsProvider; +import org.apache.isis.core.metamodel.facets.object.value.annotcfg.ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory; import org.apache.isis.core.metamodel.object.ManagedObject; import org.apache.isis.core.metamodel.objectmanager.ObjectManager; import org.apache.isis.core.metamodel.objectmanager.ObjectManagerDefault; @@ -84,6 +81,8 @@ import org.apache.isis.core.metamodel.progmodel.ProgrammingModel; import org.apache.isis.core.metamodel.progmodel.ProgrammingModelAbstract; import org.apache.isis.core.metamodel.progmodel.ProgrammingModelInitFilterDefault; import org.apache.isis.core.metamodel.progmodels.dflt.ProgrammingModelFacetsJava11; +import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorDefault; +import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorForCollections; import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorRegistry; import org.apache.isis.core.metamodel.services.events.MetamodelEventService; import org.apache.isis.core.metamodel.services.grid.GridLoaderServiceDefault; @@ -95,7 +94,6 @@ import org.apache.isis.core.metamodel.services.message.MessageServiceNoop; import org.apache.isis.core.metamodel.services.title.TitleServiceDefault; import org.apache.isis.core.metamodel.specloader.SpecificationLoader; import org.apache.isis.core.metamodel.specloader.SpecificationLoaderDefault; -import org.apache.isis.core.metamodel.specloader.specimpl.ObjectSpecificationAbstract; import org.apache.isis.core.metamodel.valuesemantics.BigDecimalValueSemantics; import org.apache.isis.core.metamodel.valuesemantics.URLValueSemantics; import org.apache.isis.core.metamodel.valuesemantics.UUIDValueSemantics; @@ -134,7 +132,12 @@ implements MetaModelContext { private IsisConfiguration configuration = newIsisConfiguration(); @Builder.Default - private ClassSubstitutorRegistry classSubstitutorRegistry = new ClassSubstitutorRegistry(Collections.emptyList()); + private ClassSubstitutorRegistry classSubstitutorRegistry = + new ClassSubstitutorRegistry(List.of( + //new ClassSubstitutorForDomainObjects(), + new ClassSubstitutorForCollections(), + new ClassSubstitutorDefault() + )); private ObjectManager objectManager; @@ -353,6 +356,7 @@ implements MetaModelContext { val programmingModel = requireNonNull(getProgrammingModel()); val isisBeanTypeClassifier = requireNonNull(getIsisBeanTypeClassifier()); val isisBeanTypeRegistry = requireNonNull(getIsisBeanTypeRegistry()); + val classSubstitutorRegistry = requireNonNull(getClassSubstitutorRegistry()); specificationLoader = SpecificationLoaderDefault.getInstance( configuration, @@ -360,7 +364,8 @@ implements MetaModelContext { serviceRegistry, programmingModel, isisBeanTypeClassifier, - isisBeanTypeRegistry); + isisBeanTypeRegistry, + classSubstitutorRegistry); } return specificationLoader; @@ -535,18 +540,16 @@ implements MetaModelContext { public <T> MetaModelContext_forTesting withValueSemantics(final ValueSemanticsAbstract<T> valueSemantics) { val valueClass = valueSemantics.getCorrespondingClass(); val valueSpec = getSpecificationLoader().loadSpecification(valueClass); - final ValueFacet<T> valueFacet = ValueFacetUsingSemanticsProvider - .create(valueClass, Can.of(valueSemantics), valueSpec); - valueSpec.addFacet(valueFacet); - valueSpec.addFacet(TitleFacetFromValueFacet.create(valueFacet, valueSpec)); - - ((ObjectSpecificationAbstract)valueSpec).invalidateCachedFacets(); // optimization stuff - - _Assert.assertTrue(valueSpec.valueFacet().isPresent()); - _Assert.assertTrue(valueSpec.lookupNonFallbackFacet(TitleFacet.class).isPresent()); - + ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory + .installValueFacet(valueClass, Can.of(valueSemantics), valueSpec); + + if(ClassUtils.isPrimitiveWrapper(valueClass)) { + val primitiveType = ClassUtil.unboxPrimitiveIfNecessary(valueClass); + val primitiveTypeSpec = getSpecificationLoader().loadSpecification(primitiveType); + ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory + .installValueFacet(valueClass, Can.of(valueSemantics), primitiveTypeSpec); + } return this; } - } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassUtil.java index 65db6d0311..4a2bb3e9e2 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassUtil.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/commons/ClassUtil.java @@ -69,7 +69,7 @@ public final class ClassUtil { double.class, Double.class, void.class, Void.class); - final Map<Class<?>, Class<?>> primitiveByNameWrapper = Map.of( + final Map<Class<?>, Class<?>> primitiveByWrapper = Map.of( Boolean.class, boolean.class, Byte.class, byte.class, Character.class, char.class, @@ -93,7 +93,7 @@ public final class ClassUtil { val firstPass = clazz.isPrimitive() || !clazz.getPackageName().equals("java.lang") ? clazz - : primitiveByNameWrapper.get(clazz); + : primitiveByWrapper.get(clazz); //null-able return firstPass!=null ? firstPass : clazz; diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java index 8392da1ffd..21e7b7adb0 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/value/annotcfg/ValueFacetForValueAnnotationOrAnyMatchingValueSemanticsFacetFactory.java @@ -25,9 +25,11 @@ import org.apache.isis.applib.annotation.Value; import org.apache.isis.applib.id.LogicalType; import org.apache.isis.applib.value.semantics.ValueSemanticsProvider; import org.apache.isis.applib.value.semantics.ValueSemanticsResolver; +import org.apache.isis.commons.collections.Can; +import org.apache.isis.commons.internal.assertions._Assert; import org.apache.isis.commons.internal.base._Casts; import org.apache.isis.core.metamodel.context.MetaModelContext; -import org.apache.isis.core.metamodel.facetapi.FacetHolder; +import org.apache.isis.core.metamodel.facetapi.FacetUtil; import org.apache.isis.core.metamodel.facetapi.FeatureType; import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract; import org.apache.isis.core.metamodel.facets.object.defaults.DefaultedFacet; @@ -42,7 +44,9 @@ import org.apache.isis.core.metamodel.facets.object.value.MaxLengthFacetFromValu import org.apache.isis.core.metamodel.facets.object.value.TypicalLengthFacetFromValueFacet; import org.apache.isis.core.metamodel.facets.object.value.ValueFacet; import org.apache.isis.core.metamodel.facets.object.value.vsp.ValueFacetUsingSemanticsProvider; +import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.specloader.specimpl.ObjectSpecificationAbstract; +import org.apache.isis.core.metamodel.util.Facets; import lombok.AccessLevel; import lombok.Getter; @@ -89,11 +93,9 @@ extends FacetFactoryAbstract { val logicalType = LogicalType.infer(valueClass); val identifier = Identifier.classIdentifier(logicalType); - addAllFacetsForValueSemantics(identifier, valueClass, facetHolder, valueIfAny); - - // optimization - _Casts.castTo(ObjectSpecificationAbstract.class, facetHolder) - .ifPresent(ObjectSpecificationAbstract::invalidateCachedFacets); + _Casts.castTo(ObjectSpecification.class, facetHolder) + .ifPresent(valueSpec-> + addAllFacetsForValueSemantics(identifier, valueClass, valueSpec, valueIfAny)); } // -- HELPER @@ -101,7 +103,7 @@ extends FacetFactoryAbstract { private <T> Optional<ValueFacet<T>> addAllFacetsForValueSemantics( final Identifier identifier, final Class<T> valueClass, - final FacetHolder holder, + final ObjectSpecification valueSpec, final Optional<Value> valueIfAny) { val semanticsProviders = getValueSemanticsResolver().selectValueSemantics(identifier, valueClass); @@ -118,21 +120,35 @@ extends FacetFactoryAbstract { log.debug("found {} ValueSemanticsProvider(s) for value type {}", semanticsProviders.size(), valueClass); } - val valueFacet = ValueFacetUsingSemanticsProvider.create(valueClass, semanticsProviders, holder); + val valueFacet = installValueFacet(valueClass, semanticsProviders, valueSpec); + return Optional.of(valueFacet); + } + + // JUnit support + public static <T> ValueFacet<T> installValueFacet( + final Class<T> valueClass, + final Can<ValueSemanticsProvider<T>> valueSemanticsProviders, + final ObjectSpecification valueSpec) { - addFacet(valueFacet); - addFacet(new ImmutableFacetViaValueSemantics(holder)); - addFacet(TitleFacetFromValueFacet.create(valueFacet, holder)); + final ValueFacet<T> valueFacet = ValueFacetUsingSemanticsProvider + .create(valueClass, valueSemanticsProviders, valueSpec); - addFacetIfPresent(TypicalLengthFacetFromValueFacet.create(valueFacet, holder)); - addFacetIfPresent(MaxLengthFacetFromValueFacet.create(valueFacet, holder)); - addFacetIfPresent(DefaultedFacetFromValueFacet.create(valueFacet, holder)); + valueSpec.addFacet(valueFacet); + valueSpec.addFacet(new ImmutableFacetViaValueSemantics(valueSpec)); + valueSpec.addFacet(TitleFacetFromValueFacet.create(valueFacet, valueSpec)); - return Optional.of(valueFacet); - } + FacetUtil.addFacetIfPresent(TypicalLengthFacetFromValueFacet.create(valueFacet, valueSpec)); + FacetUtil.addFacetIfPresent(MaxLengthFacetFromValueFacet.create(valueFacet, valueSpec)); + FacetUtil.addFacetIfPresent(DefaultedFacetFromValueFacet.create(valueFacet, valueSpec)); + ((ObjectSpecificationAbstract)valueSpec).invalidateCachedFacets(); // optimization stuff + _Assert.assertTrue(valueSpec.valueFacet().isPresent()); + _Assert.assertTrue(valueSpec.lookupNonFallbackFacet(TitleFacet.class).isPresent()); + _Assert.assertNotNull(Facets.valueSerializerElseFail(valueSpec, valueSpec.getCorrespondingClass())); + return valueFacet; + } // -- DEPENDENCIES diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java index 7851dd2569..4ba7466d57 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObject.java @@ -434,8 +434,8 @@ public interface ManagedObject extends HasMetaModelContext { final @NonNull ObjectSpecification spec, final @Nullable Object pojo) { return pojo != null - ? new _ManagedObjectWithEagerSpec(spec, pojo) //FIXME - //new _ManagedObjectValue(spec, pojo) + //? new _ManagedObjectWithEagerSpec(spec, pojo) //FIXME + ? new _ManagedObjectValue(spec, pojo) : empty(spec); } /** diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmAssertionUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmAssertionUtil.java index eee5b2f32f..654b3c805b 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmAssertionUtil.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmAssertionUtil.java @@ -25,6 +25,7 @@ import org.springframework.util.ClassUtils; import org.apache.isis.commons.internal.assertions._Assert; import org.apache.isis.commons.internal.exceptions._Exceptions; +import org.apache.isis.core.metamodel.commons.ClassUtil; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import lombok.NonNull; @@ -41,7 +42,10 @@ public class MmAssertionUtil { || requiredSpec==null) { return; } - val actualSpec = requiredSpec.getSpecificationLoader().specForType(pojo.getClass()).orElse(null); + val actualType = requiredSpec.isPrimitive() + ? ClassUtil.unboxPrimitiveIfNecessary(pojo.getClass()) + : pojo.getClass(); + val actualSpec = requiredSpec.getSpecificationLoader().specForType(actualType).orElse(null); _Assert.assertEquals(requiredSpec, actualSpec, ()-> String.format("pojo's actual ObjectSpecification %s " + "does not exaclty match %s%n", actualSpec, requiredSpec)); diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java index 2071aad5ce..4894928b96 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecified.java @@ -27,11 +27,14 @@ import org.apache.isis.commons.internal.exceptions._Exceptions; import org.apache.isis.core.metamodel.context.MetaModelContext; import org.apache.isis.core.metamodel.spec.ObjectSpecification; +import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; +import lombok.RequiredArgsConstructor; import lombok.val; import lombok.experimental.Accessors; +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) abstract class _ManagedObjectSpecified implements ManagedObject { @@ -41,13 +44,6 @@ implements ManagedObject { @Getter(onMethod_ = {@Override}) @Accessors(makeFinal = true) private final @NonNull ObjectSpecification specification; - protected _ManagedObjectSpecified( - final @NonNull Specialization specialization, - final @NonNull ObjectSpecification specification) { - this.specialization = specialization; - this.specification = specification; - } - @Override public final MetaModelContext getMetaModelContext() { return getSpecification().getMetaModelContext(); @@ -62,7 +58,10 @@ implements ManagedObject { public final <T> T assertCompliance(final @NonNull T pojo) { MmAssertionUtil.assertPojoNotWrapped(pojo); if(specification.isAbstract()) { - _Assert.assertFalse(specialization.getTypePolicy().isExactTypeRequired()); + _Assert.assertFalse(specialization.getTypePolicy().isExactTypeRequired(), + ()->String.format("Specialization %s does not allow abstract type %s", + specialization, + specification)); } if(specialization.getTypePolicy().isExactTypeRequired()) { MmAssertionUtil.assertExactType(specification, pojo); diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java index 2257909ad2..3e557caa69 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutor.java @@ -79,7 +79,7 @@ public interface ClassSubstitutor { return NEVER_INTROSPECT_CLASS; } - public static Substitution replaceWith(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls) { + public static Substitution replaceWith(final @NonNull Class<?> cls) { return of(Type.REPLACE_WITH_OTHER_CLASS, cls); } @@ -116,7 +116,7 @@ public interface ClassSubstitutor { // -- OPERATOR @Override - public Class<?> apply(Class<?> cls) { + public Class<?> apply(final Class<?> cls) { if(isNeverIntrospect()) { return null; } @@ -132,7 +132,7 @@ public interface ClassSubstitutor { * @return (non-null) Substitution for given {@code cls} * @since 2.0 */ - Substitution getSubstitution(@lombok.NonNull @org.springframework.lang.NonNull Class<?> cls); + Substitution getSubstitution(@NonNull Class<?> cls); } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java index 3d0fd6e9c5..30465702f7 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/classsubstitutor/ClassSubstitutorRegistry.java @@ -46,14 +46,13 @@ import lombok.extern.log4j.Log4j2; public class ClassSubstitutorRegistry { private final List<ClassSubstitutor> classSubstitutors; + private final Map<Class<?>, Substitution> cache = _Maps.newConcurrentHashMap(); @Inject public ClassSubstitutorRegistry(final List<ClassSubstitutor> classSubstitutors) { this.classSubstitutors = classSubstitutors; } - private final Map<Class<?>, Substitution> cache = _Maps.newConcurrentHashMap(); - /** * @param originalClass * @return (non-null) the aggregated Substitution that applies to given originalClass diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java index 976b36f4b5..f0a755a073 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java @@ -412,8 +412,26 @@ extends return getBeanSort().isMixin(); } - //TODO this predicate can now be answered by getBeanSort().isAbstract(), we can retire any old logic - boolean isAbstract(); + /** + * Whether {@link #getCorrespondingClass()} is {@link Void} or void. + */ + default boolean isVoid() { + return getCorrespondingClass()==void.class + || getCorrespondingClass()==Void.class; + } + + /** + * Whether {@link #getCorrespondingClass()} is a primitive type, + * but not {@link Void} or void. + */ + default boolean isPrimitive() { + return !isVoid() + && getCorrespondingClass().isPrimitive(); + } + + default boolean isAbstract() { + return getBeanSort().isAbstract(); + } default boolean isEntity() { return getBeanSort().isEntity() diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java index 66afd57dfa..9ada3880b1 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java @@ -71,8 +71,6 @@ import org.apache.isis.core.metamodel.progmodel.ProgrammingModelService; import org.apache.isis.core.metamodel.progmodels.dflt.ProgrammingModelFacetsJava11; import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutor; import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutor.Substitution; -import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorDefault; -import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorForCollections; import org.apache.isis.core.metamodel.services.classsubstitutor.ClassSubstitutorRegistry; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.specloader.facetprocessor.FacetProcessor; @@ -184,17 +182,14 @@ public class SpecificationLoaderDefault implements SpecificationLoader { final ServiceRegistry serviceRegistry, final ProgrammingModel programmingModel, final IsisBeanTypeClassifier isisBeanTypeClassifier, - final IsisBeanTypeRegistry isisBeanTypeRegistry) { + final IsisBeanTypeRegistry isisBeanTypeRegistry, + final ClassSubstitutorRegistry classSubstitutorRegistry) { val instance = new SpecificationLoaderDefault( programmingModel, isisConfiguration, isisSystemEnvironment, serviceRegistry, isisBeanTypeClassifier, isisBeanTypeRegistry, ()->new ValueSemanticsResolverDefault(List.of(), null), - new ClassSubstitutorRegistry(List.of( - //new ClassSubstitutorForDomainObjects(), - new ClassSubstitutorForCollections(), - new ClassSubstitutorDefault() - ))); + classSubstitutorRegistry); instance.metaModelContext = serviceRegistry.lookupServiceElseFail(MetaModelContext.class); instance.facetProcessor = new FacetProcessor(programmingModel, instance.metaModelContext); @@ -243,11 +238,11 @@ public class SpecificationLoaderDefault implements SpecificationLoader { .concat( isisBeanTypeRegistry.getDiscoveredValueTypes().keySet().stream(), valueSemanticsResolver.get().streamClassesWithValueSemantics()) - .forEach(valueType -> { - val valueSpec = loadSpecification(valueType, IntrospectionState.NOT_INTROSPECTED); + .forEach(valueClass -> { + val valueSpec = loadSpecification(valueClass, IntrospectionState.NOT_INTROSPECTED); if(valueSpec!=null) { knownSpecs.add(valueSpec); - valueTypeSpecs.put(valueType, valueSpec); + valueTypeSpecs.put(valueClass, valueSpec); } }); diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java index c0fbc1d6f8..bc0767a990 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java @@ -47,7 +47,6 @@ import org.apache.isis.commons.internal.collections._Sets; import org.apache.isis.commons.internal.collections._Streams; import org.apache.isis.commons.internal.exceptions._Exceptions; import org.apache.isis.core.config.beans.IsisBeanTypeRegistry; -import org.apache.isis.core.metamodel.commons.ClassExtensions; import org.apache.isis.core.metamodel.consent.Consent; import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; import org.apache.isis.core.metamodel.consent.InteractionResult; @@ -176,7 +175,6 @@ implements ObjectSpecification { private final Class<?> correspondingClass; private final String fullName; private final String shortName; - private final boolean isAbstract; private final LogicalType logicalType; @@ -209,8 +207,6 @@ implements ObjectSpecification { this.shortName = shortName; this.beanSort = beanSort; - this.isAbstract = ClassExtensions.isAbstract(introspectedClass); - this.facetProcessor = facetProcessor; this.postProcessor = postProcessor; } @@ -617,11 +613,6 @@ implements ObjectSpecification { return directSubclasses.hasSubclasses(); } - @Override - public final boolean isAbstract() { - return isAbstract; - } - // -- ASSOCIATIONS @Override diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java index 3b2a7e4a3a..a11dae3ce3 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/Facets.java @@ -24,6 +24,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; import org.springframework.lang.Nullable; +import org.springframework.util.ClassUtils; import org.apache.isis.applib.annotation.BookmarkPolicy; import org.apache.isis.applib.annotation.DomainServiceLayout.MenuBar; @@ -404,7 +405,7 @@ public final class Facets { final ObjectSpecification objectSpec, final Class<X> requiredType) { return objectSpec.valueFacet() - .filter(valueFacet->requiredType.isAssignableFrom(valueFacet.getValueClass())) + .filter(typeGuard(requiredType)) .flatMap(ValueFacet::selectDefaultSemantics) .map(_Casts::uncheckedCast); } @@ -414,7 +415,7 @@ public final class Facets { final ObjectSpecification objectSpec, final Class<X> requiredType) { return objectSpec.valueFacet() - .filter(valueFacet->requiredType.isAssignableFrom(valueFacet.getValueClass())) + .filter(typeGuard(requiredType)) .map(valueFacet->(ValueSerializer<X>)valueFacet); } @@ -427,4 +428,15 @@ public final class Facets { objectSpec.getCorrespondingClass().getName())); } + // -- HELPER + + @SuppressWarnings("rawtypes") + private Predicate<? super ValueFacet> typeGuard( + final Class<?> requiredType) { + return valueFacet-> + ClassUtils.resolvePrimitiveIfNecessary(requiredType) + .isAssignableFrom( + ClassUtils.resolvePrimitiveIfNecessary(valueFacet.getValueClass())); + } + } diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryTest.java index b72301b44b..a18facd2be 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryTest.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/AbstractFacetFactoryTest.java @@ -41,8 +41,6 @@ import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext; import org.apache.isis.core.metamodel.facets.actions.layout.ActionLayoutFacetFactory; import org.apache.isis.core.metamodel.facets.collections.layout.CollectionLayoutFacetFactory; import org.apache.isis.core.metamodel.facets.properties.propertylayout.PropertyLayoutFacetFactory; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.specloader.SpecificationLoader; import org.apache.isis.core.security.authentication.InteractionContextFactory; import junit.framework.TestCase; @@ -68,7 +66,6 @@ public abstract class AbstractFacetFactoryTest extends TestCase { protected TranslationService mockTranslationService; protected InteractionProvider mockInteractionProvider; protected final InteractionContext iaContext = InteractionContextFactory.testing(); - protected SpecificationLoader mockSpecificationLoader; protected MethodRemover_forTesting methodRemover; protected FacetHolder facetHolder; @@ -88,10 +85,7 @@ public abstract class AbstractFacetFactoryTest extends TestCase { mockTranslationService = context.mock(TranslationService.class); - mockSpecificationLoader = context.mock(SpecificationLoader.class); - metaModelContext = MetaModelContext_forTesting.builder() - .specificationLoader(mockSpecificationLoader) .translationService(mockTranslationService) .interactionProvider(mockInteractionProvider) .build(); @@ -113,18 +107,8 @@ public abstract class AbstractFacetFactoryTest extends TestCase { ); } - - - protected void allowing_specificationLoader_loadSpecification_any_willReturn(final ObjectSpecification objectSpecification) { - context.checking(new Expectations() {{ - allowing(mockSpecificationLoader).loadSpecification(with(any(Class.class))); - will(returnValue(objectSpecification)); - }}); - } - @Override protected void tearDown() throws Exception { - mockSpecificationLoader = null; methodRemover = null; facetedMethod = null; super.tearDown(); diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/ActionMethodsFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/ActionMethodsFacetFactoryTest.java index 7816e0b4bb..25110b3047 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/ActionMethodsFacetFactoryTest.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/ActionMethodsFacetFactoryTest.java @@ -46,13 +46,13 @@ import org.apache.isis.core.metamodel.facets.param.defaults.ActionParameterDefau import org.apache.isis.core.metamodel.facets.param.defaults.methodnum.ActionParameterDefaultsFacetViaMethod; import org.apache.isis.core.metamodel.facets.param.defaults.methodnum.ActionParameterDefaultsFacetViaMethodFactory; import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.testspec.ObjectSpecificationStub; import lombok.val; public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { - private JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES); + private JUnitRuleMockery2 context = + JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES); private ObjectSpecification voidSpec; // private final ObjectSpecification stringSpec = new ObjectSpecificationStub("java.lang.String"); @@ -65,7 +65,8 @@ public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { super.setUp(); - voidSpec = new ObjectSpecificationStub(metaModelContext, void.class); + val specLoader = metaModelContext.getSpecificationLoader(); + voidSpec = specLoader.loadSpecification(void.class); context.checking(new Expectations() {{ @@ -103,9 +104,6 @@ public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { public void testInstallsValidateMethodNoArgsFacetAndRemovesMethod() { val facetFactory = new ActionValidationFacetViaMethodFactory(metaModelContext); - // mockSpecificationLoader.setLoadSpecificationStringReturn(voidSpec); - allowing_specificationLoader_loadSpecification_any_willReturn(this.voidSpec); - @SuppressWarnings("unused") class Customer { @@ -134,9 +132,6 @@ public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { public void testInstallsValidateMethodSomeArgsFacetAndRemovesMethod() { val facetFactory = new ActionValidationFacetViaMethodFactory(metaModelContext); - // mockSpecificationLoader.setLoadSpecificationStringReturn(voidSpec); - allowing_specificationLoader_loadSpecification_any_willReturn(this.voidSpec); - class Customer { @SuppressWarnings("unused") public void someAction(final int x, final int y) { @@ -165,8 +160,6 @@ public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { public void testInstallsParameterDefaultsMethodAndRemovesMethod() { val facetFactory = new ActionParameterDefaultsFacetViaMethodFactory(metaModelContext); - allowing_specificationLoader_loadSpecification_any_willReturn(this.voidSpec); - class Customer { @SuppressWarnings("unused") public void someAction(final int x, final long y) { @@ -214,9 +207,6 @@ public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { public void testInstallsParameterChoicesMethodAndRemovesMethod() { val facetFactory = new ActionParameterChoicesFacetViaMethodFactory(metaModelContext); - // mockSpecificationLoader.setLoadSpecificationStringReturn(voidSpec); - allowing_specificationLoader_loadSpecification_any_willReturn(this.voidSpec); - class Customer { @SuppressWarnings("unused") public void someAction(final int x, final long y, final long z) { @@ -279,9 +269,6 @@ public class ActionMethodsFacetFactoryTest extends AbstractFacetFactoryTest { public void testInstallsParameterAutoCompleteMethodAndRemovesMethod() { val facetFactory = new ActionParameterAutoCompleteFacetViaMethodFactory(metaModelContext); - // mockSpecificationLoader.setLoadSpecificationStringReturn(voidSpec); - allowing_specificationLoader_loadSpecification_any_willReturn(this.voidSpec); - class Customer { @SuppressWarnings("unused") public void someAction(final int x, final long y) { diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_ActionInvocation.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_ActionInvocation.java index 5c81339757..ea8495b228 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_ActionInvocation.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactoryTest_ActionInvocation.java @@ -35,7 +35,6 @@ import org.apache.isis.core.metamodel.facets.param.choices.ActionParameterChoice import org.apache.isis.core.metamodel.facets.param.choices.methodnum.ActionParameterChoicesFacetViaMethod; import org.apache.isis.core.metamodel.facets.param.choices.methodnum.ActionParameterChoicesFacetViaMethodFactory; import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.testspec.ObjectSpecificationStub; import lombok.val; @@ -60,15 +59,14 @@ extends AbstractFacetFactoryTest { super.setUp(); this.facetFactory = new ActionAnnotationFacetFactory(metaModelContext); - voidSpec = new ObjectSpecificationStub(metaModelContext, void.class); - stringSpec = new ObjectSpecificationStub(metaModelContext, java.lang.String.class); - customerSpec = new ObjectSpecificationStub(metaModelContext, Customer.class); + val specLoader = metaModelContext.getSpecificationLoader(); + voidSpec = specLoader.loadSpecification(void.class); + stringSpec = specLoader.loadSpecification(java.lang.String.class); + customerSpec = specLoader.loadSpecification(Customer.class); } public void testActionInvocationFacetIsInstalledAndMethodRemoved() { - allowing_specificationLoader_loadSpecification_any_willReturn(voidSpec); - class Customer { public void someAction() { } @@ -89,8 +87,6 @@ extends AbstractFacetFactoryTest { public void testActionReturnTypeWhenVoid() { - allowing_specificationLoader_loadSpecification_any_willReturn(voidSpec); - class Customer { public void someAction() { } @@ -107,8 +103,6 @@ extends AbstractFacetFactoryTest { public void testActionReturnTypeWhenNotVoid() { - allowing_specificationLoader_loadSpecification_any_willReturn(stringSpec); - class Customer { public String someAction() { return null; @@ -126,27 +120,29 @@ extends AbstractFacetFactoryTest { public void testActionOnType() { - allowing_specificationLoader_loadSpecification_any_willReturn(customerSpec); - - class Customer { + class LocalCustomer { public String someAction() { return null; } } - final Method actionMethod = findMethod(Customer.class, "someAction"); + + val customerSpec = metaModelContext.getSpecificationLoader().loadSpecification(LocalCustomer.class); + + final Method actionMethod = findMethod(LocalCustomer.class, "someAction"); processInvocation(facetFactory, ProcessMethodContext - .forTesting(Customer.class, null, actionMethod, methodRemover, facetedMethod)); + .forTesting(LocalCustomer.class, null, actionMethod, methodRemover, facetedMethod)); final Facet facet = facetedMethod.getFacet(ActionInvocationFacet.class); - final ActionInvocationFacetForDomainEventAbstract actionInvocationFacetViaMethod = (ActionInvocationFacetForDomainEventAbstract) facet; - assertEquals(customerSpec, actionInvocationFacetViaMethod.getDeclaringType()); + final ActionInvocationFacetForDomainEventAbstract actionInvocationFacetViaMethod = + (ActionInvocationFacetForDomainEventAbstract) facet; + assertEquals( + customerSpec, + actionInvocationFacetViaMethod.getDeclaringType()); } public void testActionsPickedUpFromSuperclass() { - allowing_specificationLoader_loadSpecification_any_willReturn(voidSpec); - class Customer { public void someAction(final int x, final long y) { } @@ -169,8 +165,6 @@ extends AbstractFacetFactoryTest { public void testActionsPickedUpFromSuperclassButHelpersFromSubClass() { - allowing_specificationLoader_loadSpecification_any_willReturn(voidSpec); - val facetFactoryForChoices = new ActionParameterChoicesFacetViaMethodFactory(metaModelContext); val facetFactoryForDisable = new DisableForContextFacetViaMethodFactory(metaModelContext); diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/CollectionFieldMethodsFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/CollectionFieldMethodsFacetFactoryTest.java index 8cef5dd85f..332aa6ede1 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/CollectionFieldMethodsFacetFactoryTest.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/CollectionFieldMethodsFacetFactoryTest.java @@ -23,33 +23,21 @@ import java.util.Collection; import java.util.List; import java.util.Set; -import org.junit.Rule; - -import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2; -import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2.Mode; import org.apache.isis.core.metamodel.facetapi.Facet; import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest; import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext; import org.apache.isis.core.metamodel.facets.collections.accessor.CollectionAccessorFacetViaAccessor; import org.apache.isis.core.metamodel.facets.collections.accessor.CollectionAccessorFacetViaAccessorFactory; import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; import lombok.val; -public class CollectionFieldMethodsFacetFactoryTest extends AbstractFacetFactoryTest { - - @Rule - public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES); - - private ObjectSpecification mockSpecification; +public class CollectionFieldMethodsFacetFactoryTest +extends AbstractFacetFactoryTest { @Override public void setUp() throws Exception { super.setUp(); - - // expecting - allowing_specificationLoader_loadSpecification_any_willReturn(mockSpecification); } public void testPropertyAccessorFacetIsInstalledForJavaUtilCollectionAndMethodRemoved() { diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactoryTest_typeOf.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactoryTest_typeOf.java index e7417f94b4..3eff6c4ad8 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactoryTest_typeOf.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactoryTest_typeOf.java @@ -21,16 +21,12 @@ package org.apache.isis.core.metamodel.facets.collections.collection; import java.lang.reflect.Method; import java.util.Collection; -import org.jmock.Expectations; -import org.jmock.auto.Mock; - import org.apache.isis.core.metamodel.facetapi.Facet; import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest; import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext; import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet; import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacetFromArray; import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacetFromGenerics; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; public class CollectionAnnotationFacetFactoryTest_typeOf extends AbstractFacetFactoryTest { @@ -61,11 +57,6 @@ extends AbstractFacetFactoryTest { } final Method actionMethod = findMethod(Customer.class, "someAction"); - context.checking(new Expectations() {{ - allowing(mockSpecificationLoader).loadSpecification(Customer.class); - will(returnValue(mockCustomerSpec)); - }}); - facetFactory.process(ProcessMethodContext .forTesting(Customer.class, null, actionMethod, methodRemover, facetedMethod)); @@ -87,11 +78,6 @@ extends AbstractFacetFactoryTest { } } - context.checking(new Expectations() {{ - allowing(mockSpecificationLoader).loadSpecification(Customer.class); - will(returnValue(mockCustomerSpec)); - }}); - final Method collectionAccessorMethod = findMethod(Customer.class, "getOrders"); facetFactory.process(ProcessMethodContext @@ -105,9 +91,6 @@ extends AbstractFacetFactoryTest { } - @Mock - ObjectSpecification mockCustomerSpec; - public void testTypeOfFacetIsInferredForCollectionFromOrderArray() { class Order { } @@ -119,11 +102,6 @@ extends AbstractFacetFactoryTest { } final Method collectionAccessorMethod = findMethod(Customer.class, "getOrders"); - context.checking(new Expectations() {{ - allowing(mockSpecificationLoader).loadSpecification(Customer.class); - will(returnValue(mockCustomerSpec)); - }}); - facetFactory.process(ProcessMethodContext .forTesting(Customer.class, null, collectionAccessorMethod, methodRemover, facetedMethod)); diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java index 51f8eece8e..e74edba3b2 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/properties/PropertyMethodsFacetFactoryTest.java @@ -20,8 +20,6 @@ package org.apache.isis.core.metamodel.facets.properties; import java.lang.reflect.Method; -import org.jmock.auto.Mock; - import org.apache.isis.core.metamodel.facetapi.Facet; import org.apache.isis.core.metamodel.facetapi.FeatureType; import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest; @@ -55,20 +53,15 @@ import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySe import org.apache.isis.core.metamodel.facets.properties.validating.PropertyValidateFacet; import org.apache.isis.core.metamodel.facets.properties.validating.method.PropertyValidateFacetViaMethod; import org.apache.isis.core.metamodel.facets.properties.validating.method.PropertyValidateFacetViaMethodFactory; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; import lombok.val; -public class PropertyMethodsFacetFactoryTest extends AbstractFacetFactoryTest { - - @Mock private ObjectSpecification mockSpecification; +public class PropertyMethodsFacetFactoryTest +extends AbstractFacetFactoryTest { @Override public void setUp() throws Exception { super.setUp(); - - // expecting - allowing_specificationLoader_loadSpecification_any_willReturn(mockSpecification); } public void testPropertyAccessorFacetIsInstalledAndMethodRemoved() { diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java deleted file mode 100644 index 82b71b2d85..0000000000 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * 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.core.metamodel.testspec; - -import java.lang.reflect.Method; -import java.util.List; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.stream.Stream; - -import org.apache.isis.applib.Identifier; -import org.apache.isis.applib.annotation.Where; -import org.apache.isis.applib.id.LogicalType; -import org.apache.isis.applib.services.metamodel.BeanSort; -import org.apache.isis.commons.collections.Can; -import org.apache.isis.commons.collections.ImmutableEnumSet; -import org.apache.isis.commons.internal.base._Casts; -import org.apache.isis.commons.internal.collections._Lists; -import org.apache.isis.core.metamodel.consent.Consent; -import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy; -import org.apache.isis.core.metamodel.consent.InteractionResult; -import org.apache.isis.core.metamodel.context.MetaModelContext; -import org.apache.isis.core.metamodel.facetapi.FacetHolder; -import org.apache.isis.core.metamodel.facetapi.FeatureType; -import org.apache.isis.core.metamodel.facets.WhereValueFacet; -import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet; -import org.apache.isis.core.metamodel.facets.members.cssclassfa.CssClassFaFactory; -import org.apache.isis.core.metamodel.facets.object.icon.ObjectIcon; -import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet; -import org.apache.isis.core.metamodel.facets.object.title.TitleRenderRequest; -import org.apache.isis.core.metamodel.facets.object.value.ValueFacet; -import org.apache.isis.core.metamodel.interactions.ObjectTitleContext; -import org.apache.isis.core.metamodel.interactions.ObjectValidityContext; -import org.apache.isis.core.metamodel.object.ManagedObject; -import org.apache.isis.core.metamodel.spec.ActionScope; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.spec.feature.MixedIn; -import org.apache.isis.core.metamodel.spec.feature.ObjectAction; -import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation; -import org.apache.isis.core.metamodel.spec.feature.ObjectMember; -import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation; -import org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState; - -import lombok.Getter; -import lombok.val; - -public class ObjectSpecificationStub -implements ObjectSpecification { - - private ObjectAction action; - public List<ObjectAssociation> fields = _Lists.newArrayList(); - private String title; - /** - * lazily derived, see {@link #getLogicalType()} - */ - private final LogicalType logicalType; - - private ObjectSpecification elementSpecification; - private final Class<?> correspondingClass; - private final String name; - - @Getter(onMethod_ = {@Override}) private FacetHolder facetHolder; - - @Override - public Optional<? extends ObjectMember> getMember(final String memberId) { - val objectAction = getAction(memberId); - if(objectAction.isPresent()) { - return objectAction; - } - val association = getAssociation(memberId); - if(association.isPresent()) { - return association; - } - return Optional.empty(); - } - - @Override - public boolean isInjectable() { - // XXX not implemented - return false; - } - - @Override - public Class<?> getCorrespondingClass() { - return correspondingClass; - } - - public ObjectSpecificationStub(final MetaModelContext mmc, final Class<?> correspondingClass) { - this.facetHolder = FacetHolder.simple(mmc, null); - this.correspondingClass = correspondingClass; - this.logicalType = LogicalType.infer(correspondingClass); - this.title = ""; - this.name = correspondingClass.getCanonicalName(); - } - - @Override - public FeatureType getFeatureType() { - return FeatureType.OBJECT; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - @Override - public boolean isAbstract() { - return false; - } - - @Override - public Optional<ObjectAssociation> getDeclaredAssociation(final String name, final MixedIn mixedIn) { - for (int i = 0; i < fields.size(); i++) { - if (fields.get(i).getId().equals(name)) { - return Optional.ofNullable(fields.get(i)); - } - } - return Optional.empty(); - } - - @Override - public Stream<ObjectAssociation> streamDeclaredAssociations(final MixedIn mixedIn) { - return fields.stream(); - } - - @Override - public String getFullIdentifier() { - return name; - } - - @Override - public LogicalType getLogicalType() { - return logicalType; - } - - @Override - public Can<LogicalType> getAliases() { - return Can.empty(); - } - - @Override - public String getIconName(final ManagedObject reference) { - return null; - } - - @Override - public ObjectIcon getIcon(final ManagedObject object) { - return null; - } - - @Override - public Object getNavigableParent(final Object object) { - return null; - } - - @Override - public String getCssClass(final ManagedObject reference) { - return null; - } - - private Optional<ObjectAction> lookupObjectAction(final String name) { - if (action != null && action.getId().equals(name)) { - return Optional.of(action); - } - return Optional.empty(); - } - - @Override - public Optional<ObjectAction> getDeclaredAction( - final String id, final ImmutableEnumSet<ActionScope> scopes, final MixedIn mixedIn) { - val nameParmsIdentityString = id.substring(0, id.indexOf('(')); - val action = lookupObjectAction(nameParmsIdentityString); - - if(scopes==null) { - return action; - } - - if (action.isPresent() - && scopes.contains(action.get().getScope())) { - return action; - } - return Optional.empty(); - - } - - @Override - public String getPluralName() { - return null; - } - - @Override - public String getShortIdentifier() { - return name.substring(name.lastIndexOf('.') + 1); - } - - @Override - public String getSingularName() { - return name + " (singular)"; - } - - @Override - public String getDescription() { - return getSingularName(); - } - - @Override - public String getHelp() { - return null; - } - - @Override - public String getTitle(final TitleRenderRequest titleRenderRequest) { - return title; - } - - @Override - public boolean hasSubclasses() { - return false; - } - - @Override - public Can<ObjectSpecification> interfaces() { - return Can.empty(); - } - - @Override - public boolean isOfType(final ObjectSpecification cls) { - return cls == this; - } - - @Override - public boolean isParented() { - return false; - } - - @Override - public Can<ObjectSpecification> subclasses(final Depth depth) { - return Can.empty(); - } - - @Override - public ObjectSpecification superclass() { - return null; - } - - @Override - public Consent isValid(final ManagedObject targetAdapter, final InteractionInitiatedBy interactionInitiatedBy) { - return null; - } - - @Override - public Identifier getFeatureIdentifier() { - return Identifier.classIdentifier(LogicalType.fqcn(correspondingClass)); - } - - @Override - public boolean isHidden() { - return false; - } - - @Override - public boolean isImmutable() { - return containsFacet(ImmutableFacet.class); - } - - @Override - public ObjectValidityContext createValidityInteractionContext( - final ManagedObject targetAdapter, final InteractionInitiatedBy interactionInitiatedBy) { - return null; - } - - @Override - public ObjectTitleContext createTitleInteractionContext( - final ManagedObject targetObjectAdapter, final InteractionInitiatedBy invocationMethod) { - return null; - } - - @Override - public InteractionResult isValidResult(final ManagedObject targetAdapter, final InteractionInitiatedBy interactionInitiatedBy) { - return null; - } - - - // ///////////////////////////////////////////////////////////// - // introspection - // ///////////////////////////////////////////////////////////// - - @Override - public Stream<ObjectAction> streamDeclaredActions(final MixedIn contributed) { - return null; - } - - @Override - public Stream<ObjectAction> streamDeclaredActions(final ImmutableEnumSet<ActionScope> types, final MixedIn contributed) { - return null; - } - - // ///////////////////////////////////////////////////////// - // view models and wizards - // ///////////////////////////////////////////////////////// - - @Override - public String toString() { - return getFullIdentifier(); - } - - @Override - public Optional<ObjectSpecification> getElementSpecification() { - return Optional.ofNullable(elementSpecification); - } - - @Override - public BeanSort getBeanSort() { - return BeanSort.UNKNOWN; // [2158] not implemented yet - } - - @Override - public void introspectUpTo(final IntrospectionState upTo) { - // [2158] not implemented yet - } - - @Override - public Optional<? extends ObjectMember> getMember(final Method method) { - return Optional.empty(); - } - - @Override - public Optional<ObjectAction> getAction( - final String id, final ImmutableEnumSet<ActionScope> scopes, final MixedIn mixedIn) { - // poorly implemented, inheritance not supported - return getDeclaredAction(id, scopes, mixedIn); - } - - @Override - public Stream<ObjectAction> streamActions( - final ImmutableEnumSet<ActionScope> types, - final MixedIn contributed, - final Consumer<ObjectAction> onActionOverloaded) { - // poorly implemented, inheritance not supported - return streamDeclaredActions(contributed); - } - - @Override - public Optional<ObjectAssociation> getAssociation(final String id, final MixedIn mixedIn) { - // poorly implemented, inheritance not supported - return getDeclaredAssociation(id, mixedIn); - } - - @Override - public Stream<ObjectAssociation> streamAssociations(final MixedIn contributed) { - // poorly implemented, inheritance not supported - return streamDeclaredAssociations(contributed); - } - - @Override - public Stream<ObjectAction> streamRuntimeActions(final MixedIn mixedIn) { - val actionScopes = ActionScope.forEnvironment(getMetaModelContext().getSystemEnvironment()); - return streamActions(actionScopes, mixedIn); - } - - @Override - public Optional<CssClassFaFactory> getCssClassFaFactory() { - return Optional.empty(); - } - - @Override - public Stream<OneToOneAssociation> streamPropertiesForColumnRendering( - final Identifier memberIdentifier, - final ManagedObject parentObject) { - - val whereContext = memberIdentifier.getType().isAction() - ? Where.STANDALONE_TABLES - : Where.PARENTED_TABLES; - - return streamProperties(MixedIn.INCLUDED) - .filter(property->property.streamFacets() - .filter(facet -> facet instanceof HiddenFacet) - .map(WhereValueFacet.class::cast) - .map(WhereValueFacet::where) - .noneMatch(where -> where.includes(whereContext))); - } - - @Override - public Optional<ValueFacet> valueFacet() { - return _Casts.uncheckedCast(lookupFacet(ValueFacet.class)); - } - -} diff --git a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/NewParameterModelTest.java b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/NewParameterModelTest.java index b78c22368f..a0790f446a 100644 --- a/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/NewParameterModelTest.java +++ b/regressiontests/stable-interact/src/test/java/org/apache/isis/testdomain/interact/NewParameterModelTest.java @@ -137,6 +137,7 @@ class NewParameterModelTest extends InteractionTestAbstract { pendingArgs.setParamValues(params); val resultOrVeto = actionInteraction.invokeWith(pendingArgs); + assertTrue(resultOrVeto.isSuccess()); assertEquals(5, (int)resultOrVeto.getSuccessElseFail().getPojo()); diff --git a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest.java b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest.java new file mode 100644 index 0000000000..b5b9cf3a8d --- /dev/null +++ b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.viewer.restfulobjects.rendering.domainobjects; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import com.fasterxml.jackson.databind.node.BigIntegerNode; +import com.fasterxml.jackson.databind.node.BooleanNode; +import com.fasterxml.jackson.databind.node.DecimalNode; +import com.fasterxml.jackson.databind.node.DoubleNode; +import com.fasterxml.jackson.databind.node.IntNode; +import com.fasterxml.jackson.databind.node.LongNode; +import com.fasterxml.jackson.databind.node.TextNode; + +import org.hamcrest.Matchers; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; + +import lombok.val; + +class JsonValueEncoderTest +extends JsonValueEncoderTestAbstract { + + @BeforeEach + void setup() { + super.setUp(); + } + + @Test + void whenManagedObjectIsNull() { + assertThrows(RuntimeException.class, ()->{ + jsonValueEncoder.asObject(null, null); + }); + } + + @Test + void whenSpecIsNull() throws Exception { + val representation = new JsonRepresentation(TextNode.valueOf("aString")); + assertThrows(IllegalArgumentException.class, ()->{ + jsonValueEncoder.asAdapter(null, representation, null); + }); + } + + @Test + void whenReprIsNull() throws Exception { + val spec = specFor(Object.class); + assertThat(jsonValueEncoder.asAdapter(spec, null, null), is(Matchers.nullValue())); + } + + @Test + void whenReprIsAnArray() throws Exception { + val spec = specFor(Integer.class); // arbitrary value class, pick any + assertThrows(IllegalArgumentException.class, ()->{ + jsonValueEncoder.asAdapter(spec, JsonRepresentation.newArray(), null); + }); + } + + @Test + void whenReprIsAMap() throws Exception { + val spec = specFor(Integer.class); // arbitrary value class, pick any + assertThrows(IllegalArgumentException.class, ()->{ + assertNull(jsonValueEncoder.asAdapter(spec, JsonRepresentation.newMap(), null)); + }); + } + + @Test + void whenSpecDoesNotHaveAnEncodableFacet() throws Exception { + val representation = new JsonRepresentation(TextNode.valueOf("aString")); + val spec = specFor(Object.class); // arbitrary non-value class, pick any + assertThrows(IllegalArgumentException.class, ()->{ + assertNull(jsonValueEncoder.asAdapter(spec, representation, null)); + }); + } + + @ParameterizedTest + @ValueSource(classes = { + boolean.class, Boolean.class, + long.class, Long.class, + int.class, Integer.class, + short.class, Short.class, + byte.class, Byte.class, + char.class, Character.class, + double.class, Double.class, + float.class, Float.class, + BigInteger.class, BigDecimal.class,}) + void whenObjectSpecIsIncompatibleWithRepr(final Class<?> correspondingClass) { + // given + val spec = specFor(correspondingClass); + + // when repr is 'string' + assertThrows(IllegalArgumentException.class, ()->{ + val representation = new JsonRepresentation(TextNode.valueOf("aString")); + jsonValueEncoder.asAdapter(spec, representation, null); + }); + + // when repr is 'map' + assertThrows(IllegalArgumentException.class, ()->{ + val representation = JsonRepresentation.newMap("foo", "bar"); + jsonValueEncoder.asAdapter(spec, representation, null); + }); + } + + @ParameterizedTest + @ValueSource(classes = {boolean.class, Boolean.class}) + void whenReprIsBoolean(final Class<?> correspondingClass) { + // given + final boolean value = true; + val representation = new JsonRepresentation(BooleanNode.valueOf(value)); + val spec = specFor(boolean.class); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + + @ParameterizedTest + @ValueSource(classes = {int.class, Integer.class}) + void whenReprIsInteger(final Class<?> correspondingClass) { + // given + val spec = specFor(correspondingClass); + final int value = 123; + val representation = new JsonRepresentation(IntNode.valueOf(value)); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + + @ParameterizedTest + @ValueSource(classes = {long.class, Long.class}) + void whenReprIsLong(final Class<?> correspondingClass) { + // given + val spec = specFor(correspondingClass); + final long value = 1234567890L; + val representation = new JsonRepresentation(LongNode.valueOf(value)); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + + @ParameterizedTest + @ValueSource(classes = {double.class, Double.class}) + void whenReprIsDouble(final Class<?> correspondingClass) { + // given + val spec = specFor(correspondingClass); + final double value = 123.45; + val representation = new JsonRepresentation(DoubleNode.valueOf(value)); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + + @Test + void whenReprIsBigInteger() throws Exception { + // given + val spec = specFor(BigInteger.class); + final BigInteger value = BigInteger.valueOf(123); + val representation = new JsonRepresentation(BigIntegerNode.valueOf(value)); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + + @Test + void whenReprIsBigDecimal() throws Exception { + // given + val spec = specFor(BigDecimal.class); + final BigDecimal value = new BigDecimal("123234234.45612312343535"); + val representation = new JsonRepresentation(DecimalNode.valueOf(value)); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + + + @Test + void whenReprIsString() throws Exception { + // given + val spec = specFor(String.class); + val representation = new JsonRepresentation(TextNode.valueOf("aString")); + + // when + val adapter = jsonValueEncoder.asAdapter(spec, representation, null); + + // then + assertSame(spec, adapter.getSpecification()); + } + +} diff --git a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTestAbstract.java b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTestAbstract.java new file mode 100644 index 0000000000..55c36078f8 --- /dev/null +++ b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTestAbstract.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.isis.viewer.restfulobjects.rendering.domainobjects; + +import org.apache.isis.core.metamodel._testing.MetaModelContext_forTesting; +import org.apache.isis.core.metamodel.context.MetaModelContext; +import org.apache.isis.core.metamodel.spec.ObjectSpecification; +import org.apache.isis.core.metamodel.valuesemantics.BigDecimalValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.BigIntegerValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.BooleanValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.ByteValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.DoubleValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.FloatValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.IntValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.LongValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.ShortValueSemantics; +import org.apache.isis.core.metamodel.valuesemantics.StringValueSemantics; +import org.apache.isis.viewer.restfulobjects.rendering.service.valuerender.JsonValueEncoderServiceDefault; + +abstract class JsonValueEncoderTestAbstract { + + protected MetaModelContext mmc; + protected JsonValueEncoderServiceDefault jsonValueEncoder; + + protected void setUp() { + mmc = MetaModelContext_forTesting.builder() + .build() + .withValueSemantics(new StringValueSemantics()) + .withValueSemantics(new BooleanValueSemantics()) + .withValueSemantics(new BigDecimalValueSemantics()) + .withValueSemantics(new BigIntegerValueSemantics()) + .withValueSemantics(new LongValueSemantics()) + .withValueSemantics(new IntValueSemantics()) + .withValueSemantics(new ShortValueSemantics()) + .withValueSemantics(new ByteValueSemantics()) + .withValueSemantics(new DoubleValueSemantics()) + .withValueSemantics(new FloatValueSemantics()) + ; + + jsonValueEncoder = JsonValueEncoderServiceDefault.forTesting(mmc.getSpecificationLoader()); + } + + protected ObjectSpecification specFor(final Class<?> cls) { + return mmc.getSpecificationLoader().specForTypeElseFail(cls); + } + +} diff --git a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_asAdapter.java b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_asAdapter.java deleted file mode 100644 index 6606a23eab..0000000000 --- a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_asAdapter.java +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.isis.viewer.restfulobjects.rendering.domainobjects; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Optional; - -import com.fasterxml.jackson.databind.node.BigIntegerNode; -import com.fasterxml.jackson.databind.node.BooleanNode; -import com.fasterxml.jackson.databind.node.DecimalNode; -import com.fasterxml.jackson.databind.node.DoubleNode; -import com.fasterxml.jackson.databind.node.IntNode; -import com.fasterxml.jackson.databind.node.LongNode; -import com.fasterxml.jackson.databind.node.TextNode; - -import org.hamcrest.Matchers; -import org.jmock.Expectations; -import org.jmock.auto.Mock; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException; -import org.apache.isis.applib.id.LogicalType; -import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2; -import org.apache.isis.core.metamodel.facetapi.Facet; -import org.apache.isis.core.metamodel.facets.object.value.ValueFacet; -import org.apache.isis.core.metamodel.facets.object.value.ValueSerializer.Format; -import org.apache.isis.core.metamodel.object.ManagedObject; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.specloader.SpecificationLoader; -import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation; -import org.apache.isis.viewer.restfulobjects.rendering.service.valuerender.JsonValueEncoderService; -import org.apache.isis.viewer.restfulobjects.rendering.service.valuerender.JsonValueEncoderServiceDefault; - -import lombok.val; - -public class JsonValueEncoderTest_asAdapter { - - @Rule public JUnitRuleMockery2 context = - JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES); - - @Mock private ObjectSpecification mockObjectSpec; - @Mock private ValueFacet mockValueFacet; - @Mock private ManagedObject mockObjectAdapter; - @Mock private SpecificationLoader specLoader; - - private JsonRepresentation representation; - private JsonValueEncoderService jsonValueEncoder; - - @Before - public void setUp() throws Exception { - - jsonValueEncoder = JsonValueEncoderServiceDefault.forTesting(specLoader); - - representation = new JsonRepresentation(TextNode.valueOf("aString")); - } - - @After - public void tearDown() throws Exception { - - } - - - @Test(expected = IllegalArgumentException.class) - public void whenSpecIsNull() throws Exception { - jsonValueEncoder.asAdapter(null, representation, null); - } - - @Test - public void whenReprIsNull() throws Exception { - assertThat(jsonValueEncoder.asAdapter(mockObjectSpec, null, null), is(Matchers.nullValue())); - } - - @Test(expected = IllegalArgumentException.class) - public void whenReprIsAnArray() throws Exception { - allowingObjectSpecHas(ValueFacet.class, mockValueFacet); - jsonValueEncoder.asAdapter(mockObjectSpec, JsonRepresentation.newArray(), null); - } - - @Test(expected = IllegalArgumentException.class) - public void whenReprIsAMap() throws Exception { - allowingObjectSpecHas(ValueFacet.class, mockValueFacet); - assertNull(jsonValueEncoder.asAdapter(mockObjectSpec, JsonRepresentation.newMap(), null)); - } - - @Test(expected = IllegalArgumentException.class) - public void whenSpecDoesNotHaveAnEncodableFacet() throws Exception { - allowingObjectSpecHas(ValueFacet.class, null); - - assertNull(jsonValueEncoder.asAdapter(mockObjectSpec, representation, null)); - } - - @Test - public void whenReprIsBooleanPrimitive() throws Exception { - whenReprIsBoolean(boolean.class); - } - - @Test - public void whenReprIsBooleanWrapper() throws Exception { - whenReprIsBoolean(Boolean.class); - } - - private void whenReprIsBoolean(final Class<?> correspondingClass) { - // given - allowingObjectSpecHasValue(correspondingClass); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(correspondingClass); - final boolean value = true; - representation = new JsonRepresentation(BooleanNode.valueOf(value)); - context.checking(new Expectations() { - { - allowing(specLoader).specForType(((Object)value).getClass()); - will(returnValue(Optional.of(mockObjectSpec))); - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenObjectSpecIsBooleanButReprIsNot() throws Exception { - // given - allowingObjectSpecHasValue(boolean.class); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(boolean.class); - - context.checking(new Expectations() { - { - allowing(mockValueFacet).fromEncodedString(Format.JSON, "aString"); - will(throwException(new TextEntryParseException("'aString' cannot be parsed as a boolean value"))); - } - }); - - // when - jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - } - - @Test - public void whenReprIsIntegerPrimitive() throws Exception { - whenReprIsInteger(int.class); - } - - @Test - public void whenReprIsIntegerWrapper() throws Exception { - whenReprIsInteger(Integer.class); - } - - private void whenReprIsInteger(final Class<?> correspondingClass) { - // given - allowingObjectSpecHasValue(correspondingClass); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(correspondingClass); - final int value = 123; - representation = new JsonRepresentation(IntNode.valueOf(value)); - context.checking(new Expectations() { - { - allowing(specLoader).specForType(((Object)value).getClass()); - will(returnValue(Optional.of(mockObjectSpec))); - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenObjectSpecIsIntegerButReprIsNot() throws Exception { - // given - allowingObjectSpecHas(ValueFacet.class, mockValueFacet); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(int.class); - - representation = JsonRepresentation.newMap("foo", "bar"); - - // when - jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - } - - @Test - public void whenReprIsLongPrimitive() throws Exception { - whenReprIsLong(long.class); - } - - @Test - public void whenReprIsLongWrapper() throws Exception { - whenReprIsLong(Long.class); - } - - private void whenReprIsLong(final Class<?> correspondingClass) { - // given - allowingObjectSpecHasValue(correspondingClass); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(correspondingClass); - final long value = 1234567890L; - representation = new JsonRepresentation(LongNode.valueOf(value)); - context.checking(new Expectations() { - { - allowing(specLoader).specForType(((Object)value).getClass()); - will(returnValue(Optional.of(mockObjectSpec))); - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenObjectSpecIsLongButReprIsNot() throws Exception { - // given - allowingObjectSpecHasValue(long.class); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(long.class); - - context.checking(new Expectations() { - { - allowing(mockValueFacet).fromEncodedString(Format.JSON, "aString"); - will(throwException(new TextEntryParseException("'aString' cannot be parsed as a long value"))); - } - }); - - // when - jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - } - - @Test - public void whenReprIsDoublePrimitive() throws Exception { - whenReprIsDouble(double.class); - } - - @Test - public void whenReprIsDoubleWrapper() throws Exception { - whenReprIsDouble(Double.class); - } - - private void whenReprIsDouble(final Class<?> correspondingClass) { - // given - allowingObjectSpecHasValue(correspondingClass); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(correspondingClass); - final double value = 123.45; - representation = new JsonRepresentation(DoubleNode.valueOf(value)); - context.checking(new Expectations() { - { - allowing(specLoader).specForType(((Object)value).getClass()); - will(returnValue(Optional.of(mockObjectSpec))); - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenObjectSpecIsDoubleButReprIsNot() throws Exception { - // given - allowingObjectSpecHas(ValueFacet.class, mockValueFacet); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(double.class); - - representation = JsonRepresentation.newMap("foo", "bar"); - - // when - jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - } - - @Test - public void whenReprIsBigInteger() throws Exception { - // given - allowingObjectSpecHasValue(BigInteger.class); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(BigInteger.class); - final BigInteger value = BigInteger.valueOf(123); - representation = new JsonRepresentation(BigIntegerNode.valueOf(value)); - context.checking(new Expectations() { - { - allowing(specLoader).specForType(value.getClass()); - will(returnValue(Optional.of(mockObjectSpec))); - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenObjectSpecIsBigIntegerButReprIsNot() throws Exception { - // given - allowingObjectSpecHas(ValueFacet.class, mockValueFacet); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(BigInteger.class); - - representation = JsonRepresentation.newMap("foo", "bar"); - - // when - jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - } - - @Test - public void whenReprIsBigDecimal() throws Exception { - // given - allowingObjectSpecHasValue(BigDecimal.class); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(BigDecimal.class); - final BigDecimal value = new BigDecimal("123234234.45612312343535"); - representation = new JsonRepresentation(DecimalNode.valueOf(value)); - context.checking(new Expectations() { - { - allowing(specLoader).specForType(value.getClass()); - will(returnValue(Optional.of(mockObjectSpec))); - - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - @Test(expected = IllegalArgumentException.class) - public void whenObjectSpecIsBigDecimalButReprIsNot() throws Exception { - // given - allowingObjectSpecHas(ValueFacet.class, mockValueFacet); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(BigDecimal.class); - - representation = JsonRepresentation.newMap("foo", "bar"); - - // when - jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - } - - @Test - public void whenReprIsString() throws Exception { - // given - allowingObjectSpecHasValue(String.class); - allowingObjectSpecCorrespondingClassAndObjectTypeIs(String.class); - representation = new JsonRepresentation(TextNode.valueOf("aString")); - - context.checking(new Expectations() { - { - allowing(specLoader).specForType(String.class); - will(returnValue(Optional.of(mockObjectSpec))); - } - }); - - // when - val adapter = jsonValueEncoder.asAdapter(mockObjectSpec, representation, null); - - // then - assertSame(mockObjectSpec, adapter.getSpecification()); - } - - - - private void allowingObjectSpecHasValue(final Class<?> valueClass) { - context.checking(new Expectations() { - { - - allowing(mockObjectSpec).isValue(); - will(returnValue(true)); - - allowing(mockObjectSpec).isAbstract(); - will(returnValue(false)); - - allowing(mockObjectSpec).valueFacet(); - will(returnValue(Optional.of(mockValueFacet))); - - allowing(mockObjectSpec).getFacet(ValueFacet.class); - will(returnValue(mockValueFacet)); - - allowing(mockObjectSpec).lookupFacet(ValueFacet.class); - will(returnValue(Optional.of(mockValueFacet))); - - allowing(mockValueFacet).getValueClass(); - will(returnValue(valueClass)); - - allowing(mockObjectSpec).isNonScalar(); - will(returnValue(true)); - - } - }); - } - - private <T extends Facet> void allowingObjectSpecHas(final Class<T> facetClass, final T facet) { - context.checking(new Expectations() { - { - - allowing(mockObjectSpec).valueFacet(); - will(returnValue(Optional.ofNullable(facet))); - - allowing(mockObjectSpec).getFacet(facetClass); - will(returnValue(facet)); - - allowing(mockObjectSpec).lookupFacet(facetClass); - will(returnValue(Optional.ofNullable(facet))); - - allowing(mockObjectSpec).getCorrespondingClass(); - will(returnValue(mockObjectSpec.getClass())); // used only for illegal argument exception message - - } - }); - } - - private void allowingObjectSpecCorrespondingClassAndObjectTypeIs(final Class<?> result) { - context.checking(new Expectations() { - { - allowing(mockObjectSpec).getCorrespondingClass(); - will(returnValue(result)); - - allowing(mockObjectSpec).getLogicalType(); - will(returnValue(LogicalType.fqcn(result))); - - } - }); - } - -} diff --git a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_asObject.java b/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_asObject.java deleted file mode 100644 index 3f7b6b5434..0000000000 --- a/viewers/restfulobjects/rendering/src/test/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/JsonValueEncoderTest_asObject.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.isis.viewer.restfulobjects.rendering.domainobjects; - -import org.jmock.Expectations; -import org.jmock.auto.Mock; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2; -import org.apache.isis.core.metamodel.object.ManagedObject; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.specloader.SpecificationLoader; -import org.apache.isis.viewer.restfulobjects.rendering.service.valuerender.JsonValueEncoderService; -import org.apache.isis.viewer.restfulobjects.rendering.service.valuerender.JsonValueEncoderServiceDefault; - -public class JsonValueEncoderTest_asObject { - - @Rule public JUnitRuleMockery2 context = - JUnitRuleMockery2.createFor(JUnitRuleMockery2.Mode.INTERFACES_AND_CLASSES); - - @Mock private ObjectSpecification mockObjectSpec; - @Mock private ManagedObject mockObjectAdapter; - @Mock private SpecificationLoader specLoader; - - private JsonValueEncoderService jsonValueEncoder; - - @Before - public void setUp() throws Exception { - - context.checking(new Expectations() { - { - allowing(mockObjectAdapter).getSpecification(); - will(returnValue(mockObjectSpec)); - } - }); - - jsonValueEncoder = JsonValueEncoderServiceDefault.forTesting(specLoader); - - } - - @Test(expected = Exception.class) - public void whenAdapterIsNull() throws Exception { - jsonValueEncoder.asObject(null, null); - } - -}