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 fc8ab413d0 ISIS-3167: move MM assertion utils into own class and implement compliance checks fc8ab413d0 is described below commit fc8ab413d0447ddc8b23228db07dee333b477997 Author: Andi Huber <ahu...@apache.org> AuthorDate: Tue Aug 30 07:53:02 2022 +0200 ISIS-3167: move MM assertion utils into own class and implement compliance checks --- .../managed/ParameterNegotiationModel.java | 3 +- .../managed/PropertyNegotiationModel.java | 3 +- .../isis/core/metamodel/object/ManagedObject.java | 12 +-- .../isis/core/metamodel/object/ManagedObjects.java | 36 +-------- .../core/metamodel/object/MmAssertionUtil.java | 86 ++++++++++++++++++++++ .../metamodel/object/_ManagedObjectSpecified.java | 32 ++++---- .../object/_ManagedObjectSpecifiedLegacy.java | 16 +--- .../object/_ManagedObjectUnspecified.java | 5 +- .../core/metamodel/object/_ManagedObjectValue.java | 5 +- .../object/_ManagedObjectWithEagerSpec.java | 3 +- 10 files changed, 125 insertions(+), 76 deletions(-) diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java index 48b556da16..9f1549aa01 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/ParameterNegotiationModel.java @@ -40,6 +40,7 @@ import org.apache.isis.core.metamodel.consent.InteractionResult; import org.apache.isis.core.metamodel.interactions.managed._BindingUtil.TargetFormat; import org.apache.isis.core.metamodel.object.ManagedObject; import org.apache.isis.core.metamodel.object.ManagedObjects; +import org.apache.isis.core.metamodel.object.MmAssertionUtil; import org.apache.isis.core.metamodel.object.MmEntityUtil; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter; @@ -296,7 +297,7 @@ public class ParameterNegotiationModel { bindableParamValueDirtyFlag = _Bindables.forBoolean(false); bindableParamValue.setValueRefiner(MmEntityUtil::refetch); - bindableParamValue.setValueGuard(ManagedObjects.assertInstanceOf(metaModel.getElementType())); + bindableParamValue.setValueGuard(MmAssertionUtil.assertInstanceOf(metaModel.getElementType())); bindableParamValue.addListener((event, oldValue, newValue)->{ if(newValue==null) { // lift null to empty ... diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java index 97afc730a4..13b5e99bad 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/managed/PropertyNegotiationModel.java @@ -33,6 +33,7 @@ import org.apache.isis.core.metamodel.interactions.managed._BindingUtil.TargetFo import org.apache.isis.core.metamodel.object.MmEntityUtil; import org.apache.isis.core.metamodel.object.ManagedObject; import org.apache.isis.core.metamodel.object.ManagedObjects; +import org.apache.isis.core.metamodel.object.MmAssertionUtil; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import lombok.NonNull; @@ -69,7 +70,7 @@ public class PropertyNegotiationModel implements ManagedValue { proposedValue = _Bindables.forValue(defaultValue); proposedValue.setValueRefiner(MmEntityUtil::refetch); - proposedValue.setValueGuard(ManagedObjects.assertInstanceOf(propMeta.getElementType())); + proposedValue.setValueGuard(MmAssertionUtil.assertInstanceOf(propMeta.getElementType())); proposedValue.addListener((e,o,n)->{ invalidateChoicesAndValidation(); }); 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 dc2659ac09..7851dd2569 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 @@ -348,8 +348,11 @@ public interface ManagedObject extends HasMetaModelContext { Supplier<ManagedObject> asSupplier(); - @Deprecated - void assertSpecIsInSyncWithPojo(); + /** + * Unary operator asserting that {@code pojo} and {@link #getSpecification()} are + * compliant with the policies from {@link #getSpecialization()}. + */ + <T> T assertCompliance(@NonNull T pojo); // -- TITLE @@ -583,12 +586,11 @@ public interface ManagedObject extends HasMetaModelContext { final @NonNull ObjectSpecification spec, final @Nullable Object pojo) { - ManagedObjects.assertPojoNotWrapped(pojo); + MmAssertionUtil.assertPojoNotWrapped(pojo); //ISIS-2430 Cannot assume Action Param Spec to be correct when eagerly loaded //actual type in use (during runtime) might be a sub-class of the above, so re-adapt with hinting spec val adapter = spec.getMetaModelContext().getObjectManager().adapt(pojo, spec); - adapter.assertSpecIsInSyncWithPojo(); return adapter; } @@ -613,7 +615,7 @@ public interface ManagedObject extends HasMetaModelContext { "pojo.toString() = %s", spec.getCorrespondingClass(), pojo.getClass(), pojo.toString()); } - ManagedObjects.assertPojoNotWrapped(pojo); + MmAssertionUtil.assertPojoNotWrapped(pojo); return _ManagedObjectWithEagerSpec.identified(spec, pojo, bookmark); } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObjects.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObjects.java index 977e275cba..ee6f7b2be3 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObjects.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/ManagedObjects.java @@ -23,7 +23,6 @@ import java.util.Comparator; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; -import java.util.function.UnaryOperator; import org.springframework.lang.Nullable; import org.springframework.util.ClassUtils; @@ -147,23 +146,6 @@ public final class ManagedObjects { return upperBound.isAssignableFrom(objectActualType); } - /** - * Guard against incompatible type. - */ - public static @NonNull UnaryOperator<ManagedObject> assertInstanceOf(final ObjectSpecification elementType) { - return object -> { - if(isInstanceOf(object, elementType)) { - return object; - } - val upperBound = ClassUtils.resolvePrimitiveIfNecessary(elementType.getCorrespondingClass()); - val objectActualType = ClassUtils.resolvePrimitiveIfNecessary(object.getSpecification().getCorrespondingClass()); - throw _Exceptions.illegalArgument("Object has incompatible type %s, " - + "must be an instance of %s.", - objectActualType.getName(), - upperBound.getName()); - }; - } - // -- IDENTIFICATION public static Optional<ObjectSpecification> spec(final @Nullable ManagedObject managedObject) { @@ -386,23 +368,7 @@ public final class ManagedObjects { .collect(Can.toCan()); } - /** - * eg. in order to prevent wrapping an object that is already wrapped - */ - public static void assertPojoNotWrapped(final @Nullable Object pojo) { - // can do this check only when the pojo is not null, otherwise is always considered valid - if(pojo==null) { - return; - } - - if(pojo instanceof ManagedObject) { - throw _Exceptions.illegalArgument( - "Cannot adapt a pojo of type ManagedObject, " + - "pojo.getClass() = %s, " + - "pojo.toString() = %s", - pojo.getClass(), pojo.toString()); - } - } + // -- IMPERATIVE TEXT UTILITY 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 new file mode 100644 index 0000000000..eee5b2f32f --- /dev/null +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmAssertionUtil.java @@ -0,0 +1,86 @@ +/* + * 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.object; + +import java.util.function.UnaryOperator; + +import org.springframework.lang.Nullable; +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.spec.ObjectSpecification; + +import lombok.NonNull; +import lombok.val; +import lombok.experimental.UtilityClass; + +@UtilityClass +public class MmAssertionUtil { + + public static void assertExactType( + final @Nullable ObjectSpecification requiredSpec, + final @Nullable Object pojo) { + if(pojo==null + || requiredSpec==null) { + return; + } + val actualSpec = requiredSpec.getSpecificationLoader().specForType(pojo.getClass()).orElse(null); + _Assert.assertEquals(requiredSpec, actualSpec, ()-> + String.format("pojo's actual ObjectSpecification %s " + + "does not exaclty match %s%n", actualSpec, requiredSpec)); + } + + /** + * Guard against incompatible type. + */ + public static @NonNull UnaryOperator<ManagedObject> assertInstanceOf( + final ObjectSpecification elementType) { + return object -> { + if(ManagedObjects.isInstanceOf(object, elementType)) { + return object; + } + val upperBound = ClassUtils.resolvePrimitiveIfNecessary(elementType.getCorrespondingClass()); + val objectActualType = ClassUtils.resolvePrimitiveIfNecessary(object.getSpecification().getCorrespondingClass()); + throw _Exceptions.illegalArgument("Object has incompatible type %s, " + + "must be an instance of %s.", + objectActualType.getName(), + upperBound.getName()); + }; + } + + /** + * eg. in order to prevent wrapping an object that is already wrapped + */ + public static void assertPojoNotWrapped(final @Nullable Object pojo) { + // can do this check only when the pojo is not null, otherwise is always considered valid + if(pojo==null) { + return; + } + + if(pojo instanceof ManagedObject) { + throw _Exceptions.illegalArgument( + "Cannot adapt a pojo of type ManagedObject, " + + "pojo.getClass() = %s, " + + "pojo.toString() = %s", + pojo.getClass(), pojo.toString()); + } + } + +} 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 5b351e01b0..2071aad5ce 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 @@ -29,11 +29,9 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification; import lombok.Getter; import lombok.NonNull; -import lombok.RequiredArgsConstructor; import lombok.val; import lombok.experimental.Accessors; -@RequiredArgsConstructor abstract class _ManagedObjectSpecified implements ManagedObject { @@ -43,6 +41,13 @@ 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(); @@ -53,20 +58,16 @@ implements ManagedObject { return ()->this; } - /** debug */ @Override - public final void assertSpecIsInSyncWithPojo() { -// val pojo = getPojo(); -// val spec = getSpecification(); -// if(pojo==null -// || spec==null) { -// return; -// } -// val actualSpec = spec.getSpecificationLoader().specForType(pojo.getClass()).orElse(null); -// if(!Objects.equals(spec, actualSpec)) { -// System.err.printf("spec mismatch %s %s%n", spec, actualSpec); -// } - //_Assert.assertEquals(spec, actualSpec); + public final <T> T assertCompliance(final @NonNull T pojo) { + MmAssertionUtil.assertPojoNotWrapped(pojo); + if(specification.isAbstract()) { + _Assert.assertFalse(specialization.getTypePolicy().isExactTypeRequired()); + } + if(specialization.getTypePolicy().isExactTypeRequired()) { + MmAssertionUtil.assertExactType(specification, pojo); + } + return pojo; } //XXX compares pojos by their 'equals' semantics - @@ -130,5 +131,4 @@ implements ManagedObject { return getBookmark().orElseThrow(_Exceptions::unexpectedCodeReach); } - } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java index b170889113..05e17541ca 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectSpecifiedLegacy.java @@ -23,6 +23,7 @@ import java.util.function.Supplier; import org.apache.isis.core.metamodel.context.MetaModelContext; import lombok.Getter; +import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; @@ -43,20 +44,9 @@ implements ManagedObject { return ()->this; } - /** debug */ @Override - public void assertSpecIsInSyncWithPojo() { -// val pojo = getPojo(); -// val spec = getSpecification(); -// if(pojo==null -// || spec==null) { -// return; -// } -// val actualSpec = spec.getSpecificationLoader().specForType(pojo.getClass()).orElse(null); -// if(!Objects.equals(spec, actualSpec)) { -// System.err.printf("spec mismatch %s %s%n", spec, actualSpec); -// } - //_Assert.assertEquals(spec, actualSpec); + public final <T> T assertCompliance(final @NonNull T pojo) { + return pojo; // legacy implementation - don't check } } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectUnspecified.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectUnspecified.java index e26f76eeff..b8ac3a0ac5 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectUnspecified.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectUnspecified.java @@ -29,6 +29,8 @@ 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.NonNull; + /** * (package private) specialization corresponding to {@link Specialization#UNSPECIFIED} * @see ManagedObject.Specialization#UNSPECIFIED @@ -85,7 +87,8 @@ implements ManagedObject { } @Override - public void assertSpecIsInSyncWithPojo() { + public <T> T assertCompliance(final @NonNull T pojo) { + return pojo; // no-op } @Override diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java index bbc9ea9c63..2a6e1be759 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectValue.java @@ -52,8 +52,7 @@ extends _ManagedObjectSpecified { final Object pojo) { super(ManagedObject.Specialization.VALUE, spec); _Assert.assertTrue(spec.isValue()); - _Assert.assertFalse(spec.isAbstract()); - this.pojo = pojo; + this.pojo = assertCompliance(pojo); } @Override @@ -83,6 +82,8 @@ extends _ManagedObjectSpecified { } private Bookmark createBookmark() { + //TODO if value semantics providers are enforced to provide an IdStringifier, + // we could use that instead (to generate the second argument)! return Bookmark.forLogicalTypeAndIdentifier( getSpecification().getLogicalType(), valueFacet().toEncodedString(Format.JSON, _Casts.uncheckedCast(getPojo()))); diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithEagerSpec.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithEagerSpec.java index d5aab332cf..7729755a90 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithEagerSpec.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithEagerSpec.java @@ -68,8 +68,7 @@ extends _ManagedObjectWithBookmark { @Override public void replacePojo(final UnaryOperator<Object> replacer) { - pojo = replacer.apply(pojo); - assertSpecIsInSyncWithPojo(); + pojo = assertCompliance(replacer.apply(pojo)); } } \ No newline at end of file