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 cefdf288ff ISIS-3167: purge _ManagedObjectWithLazySpec cefdf288ff is described below commit cefdf288ff58ce550c5db5dcd2529bb854b0779a Author: Andi Huber <ahu...@apache.org> AuthorDate: Mon Aug 29 11:26:50 2022 +0200 ISIS-3167: purge _ManagedObjectWithLazySpec --- .../isis/core/metamodel/object/ManagedObject.java | 22 ------ .../object/_ManagedObjectWithLazySpec.java | 79 ---------------------- ...entNegotiationServiceForRestfulObjectsV1_0.java | 11 ++- .../JsonValueEncoderServiceDefault.java | 75 +++++++++++++------- .../JsonValueEncoderTest_asAdapter.java | 31 +++++---- 5 files changed, 75 insertions(+), 143 deletions(-) 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 17eca64550..41f3dadbba 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 @@ -538,26 +538,4 @@ public interface ManagedObject extends HasMetaModelContext { return _ManagedObjectWithEagerSpec.identified(spec, pojo, bookmark); } - /** - * For cases, when the pojo's specification is not available and needs to be looked up. - * @param specLoader - * @param pojo - */ - @Deprecated - static ManagedObject lazy( - final SpecificationLoader specLoader, - final Object pojo) { - - if(pojo!=null) { - _Assert.assertFalse(_Collections.isCollectionOrArrayOrCanType(pojo.getClass())); - } - - ManagedObjects.assertPojoNotWrapped(pojo); - val adapter = new _ManagedObjectWithLazySpec(cls->specLoader.specForType(cls).orElse(null), pojo); - //ManagedObjects.warnIfAttachedEntity(adapter, "consider using ManagedObject.identified(...) for entity"); - return adapter; - } - - - } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithLazySpec.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithLazySpec.java deleted file mode 100644 index 0ca4c35c08..0000000000 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/_ManagedObjectWithLazySpec.java +++ /dev/null @@ -1,79 +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.object; - -import java.util.function.Function; -import java.util.function.UnaryOperator; - -import org.apache.isis.commons.internal.base._Lazy; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NonNull; - -@Deprecated -@EqualsAndHashCode(of = "pojo", callSuper = false) -final class _ManagedObjectWithLazySpec -extends _ManagedObjectWithBookmark { - - @NonNull private final Function<Class<?>, ObjectSpecification> specLoader; - - @Getter @NonNull private /*final*/ Object pojo; - - private final _Lazy<ObjectSpecification> specification = _Lazy.threadSafe(this::loadSpec); - - _ManagedObjectWithLazySpec( - final @NonNull Function<Class<?>, ObjectSpecification> specLoader, - final @NonNull Object pojo) { - super(ManagedObject.Specialization.UNSPECIFIED); // FIXME - this.specLoader = specLoader; - this.pojo = pojo; - } - - @Override - public ObjectSpecification getSpecification() { - return specification.get(); - } - - @Override //ISIS-2317 make sure toString() is without side-effects - public String toString() { - if(specification.isMemoized()) { - return String.format("ManagedObject[spec=%s, pojo=%s]", - ""+getSpecification(), - ""+getPojo()); - } - return String.format("ManagedObject[spec=%s, pojo=%s]", - "[lazy not loaded]", - ""+getPojo()); - } - - private ObjectSpecification loadSpec() { - return specLoader.apply(pojo.getClass()); - } - - @Override - public void replacePojo(final UnaryOperator<Object> replacer) { - pojo = replacer.apply(pojo); - if(specification.isMemoized()) { - assertSpecIsInSyncWithPojo(); - } - } - -} \ No newline at end of file diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java index 53fde969e6..0a4ffd3d0b 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java @@ -213,11 +213,16 @@ implements ContentNegotiationService { final ObjectSpecification actionOwnerSpec = actionOwnerSpecFrom(objectAndActionInvocation); final String actionId = actionIdFrom(objectAndActionInvocation); final String actionArguments = actionArgumentsFrom(objectAndActionInvocation); - final DomainObjectList list = domainObjectListFrom( + final DomainObjectList listAsViewmodel = domainObjectListFrom( collectionAdapters, elementSpec, actionOwnerSpec, actionId, actionArguments); - val listAdapter = ManagedObject.lazy( - resourceContext.getMetaModelContext().getSpecificationLoader(), list); + val domainObjectListSpec = resourceContext.getMetaModelContext().getSpecificationLoader() + .specForType(DomainObjectList.class) + .filter(ObjectSpecification::isViewModel) + .orElseThrow(()->_Exceptions.unrecoverable( + "framework bug: DomainObjectList should be recognized as viewmodel")); + + val listAdapter = ManagedObject.viewmodel(domainObjectListSpec, listAsViewmodel); return responseBuilder( buildResponse( resourceContext, diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java index 56d99bb1b4..65766b0270 100644 --- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java +++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/valuerender/JsonValueEncoderServiceDefault.java @@ -33,10 +33,12 @@ import org.springframework.stereotype.Service; import org.springframework.util.ClassUtils; import org.apache.isis.applib.annotation.PriorityPrecedence; -import org.apache.isis.applib.exceptions.recoverable.TextEntryParseException; import org.apache.isis.applib.value.semantics.ValueDecomposition; +import org.apache.isis.commons.functional.Try; import org.apache.isis.commons.internal.base._Casts; import org.apache.isis.commons.internal.collections._Maps; +import org.apache.isis.commons.internal.exceptions._Exceptions; +import org.apache.isis.core.metamodel.facets.object.value.ValueSerializer; 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.object.ManagedObjects; @@ -71,57 +73,80 @@ public class JsonValueEncoderServiceDefault implements JsonValueEncoderService { @Override public ManagedObject asAdapter( - final ObjectSpecification objectSpec, + final ObjectSpecification spec, final JsonRepresentation valueRepr, final JsonValueConverter.Context context) { if(valueRepr == null) { return null; } - if (objectSpec == null) { + if (spec == null) { throw new IllegalArgumentException("ObjectSpecification is required"); } if (!valueRepr.isValue()) { throw new IllegalArgumentException("Representation must be of a value"); } - val valueClass = objectSpec.getCorrespondingClass(); + val valueClass = spec.getCorrespondingClass(); val valueSerializer = - Facets.valueSerializerElseFail(objectSpec, valueClass); - - final JsonValueConverter jvc = converterByClass.get(ClassUtils.resolvePrimitiveIfNecessary(valueClass)); - if(jvc == null) { - // best effort - if (valueRepr.isString()) { - final String argStr = valueRepr.asString(); - return ManagedObject.of(objectSpec, - valueSerializer.fromEncodedString(Format.JSON, argStr)); - } - throw new IllegalArgumentException("Unable to parse value"); + Facets.valueSerializerElseFail(spec, valueClass); + + final JsonValueConverter jsonValueConverter = converterByClass + .get(ClassUtils.resolvePrimitiveIfNecessary(valueClass)); + if(jsonValueConverter == null) { + // best effort: try 'String' type + return asStringElseFail(valueRepr, valueSerializer) + .map(string->ManagedObject.value(spec, string)) + .orElseGet(()->ManagedObject.empty(spec)); } - val valueAsPojo = jvc.recoverValueAsPojo(valueRepr, context); + val valueAsPojo = jsonValueConverter.recoverValueAsPojo(valueRepr, context); if(valueAsPojo != null) { - return ManagedObject.lazy(specificationLoader, valueAsPojo); + return ManagedObject.value(spec, valueAsPojo); } // last attempt if (valueRepr.isString()) { - final String argStr = valueRepr.asString(); - try { - return ManagedObject.of(objectSpec, - valueSerializer.fromEncodedString(Format.JSON, argStr)); - } catch(TextEntryParseException ex) { - throw new IllegalArgumentException(ex.getMessage()); - } + return asStringElseFail(valueRepr, valueSerializer) + .map(string->ManagedObject.value(spec, string)) + .orElseGet(()->ManagedObject.empty(spec)); } throw new IllegalArgumentException("Could not parse value '" + valueRepr.asString() + "' as a " - + objectSpec.getFullIdentifier()); + + spec.getFullIdentifier()); + } + + /** + * Returns the recovered nullable String, wrapped as optional. + * @throws IllegalArgumentException if cannot be parsed as String + */ + private static Optional<String> asStringElseFail( + final JsonRepresentation valueRepr, + final ValueSerializer<?> valueSerializer) { + if (valueRepr.isString()) { + val recoveredValue = Try.call(()-> + valueSerializer.fromEncodedString(Format.JSON, valueRepr.asString())) + .mapFailure(ex->_Exceptions + .illegalArgument(ex, "Unable to parse value %s as String", valueRepr)) + .ifFailureFail() + .getValue().orElse(null); + ; + if(recoveredValue==null) { + return Optional.empty(); + } + val recoveredStringIfAny = _Casts.castTo(String.class, recoveredValue); + if(recoveredStringIfAny.isPresent()) { + return recoveredStringIfAny; + } + throw _Exceptions.illegalArgument("Unable to parse value %s as String", recoveredValue.getClass()); + } + throw _Exceptions.illegalArgument("Unable to parse value %s as String" + + " (using 'String' as a fallback attempt)", valueRepr); } + @Override public void appendValueAndFormat( final ManagedObject valueAdapter, 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 index 9f986c74b4..592aaa0e12 100644 --- 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 @@ -38,6 +38,11 @@ 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; @@ -51,11 +56,6 @@ 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 static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - import lombok.val; public class JsonValueEncoderTest_asAdapter { @@ -132,7 +132,7 @@ public class JsonValueEncoderTest_asAdapter { representation = new JsonRepresentation(BooleanNode.valueOf(value)); context.checking(new Expectations() { { - oneOf(specLoader).specForType(((Object)value).getClass()); + allowing(specLoader).specForType(((Object)value).getClass()); will(returnValue(Optional.of(mockObjectSpec))); } }); @@ -152,7 +152,7 @@ public class JsonValueEncoderTest_asAdapter { context.checking(new Expectations() { { - oneOf(mockValueFacet).fromEncodedString(Format.JSON, "aString"); + allowing(mockValueFacet).fromEncodedString(Format.JSON, "aString"); will(throwException(new TextEntryParseException("'aString' cannot be parsed as a boolean value"))); } }); @@ -179,7 +179,7 @@ public class JsonValueEncoderTest_asAdapter { representation = new JsonRepresentation(IntNode.valueOf(value)); context.checking(new Expectations() { { - oneOf(specLoader).specForType(((Object)value).getClass()); + allowing(specLoader).specForType(((Object)value).getClass()); will(returnValue(Optional.of(mockObjectSpec))); } }); @@ -221,7 +221,7 @@ public class JsonValueEncoderTest_asAdapter { representation = new JsonRepresentation(LongNode.valueOf(value)); context.checking(new Expectations() { { - oneOf(specLoader).specForType(((Object)value).getClass()); + allowing(specLoader).specForType(((Object)value).getClass()); will(returnValue(Optional.of(mockObjectSpec))); } }); @@ -241,7 +241,7 @@ public class JsonValueEncoderTest_asAdapter { context.checking(new Expectations() { { - oneOf(mockValueFacet).fromEncodedString(Format.JSON, "aString"); + allowing(mockValueFacet).fromEncodedString(Format.JSON, "aString"); will(throwException(new TextEntryParseException("'aString' cannot be parsed as a long value"))); } }); @@ -268,7 +268,7 @@ public class JsonValueEncoderTest_asAdapter { representation = new JsonRepresentation(DoubleNode.valueOf(value)); context.checking(new Expectations() { { - oneOf(specLoader).specForType(((Object)value).getClass()); + allowing(specLoader).specForType(((Object)value).getClass()); will(returnValue(Optional.of(mockObjectSpec))); } }); @@ -301,7 +301,7 @@ public class JsonValueEncoderTest_asAdapter { representation = new JsonRepresentation(BigIntegerNode.valueOf(value)); context.checking(new Expectations() { { - oneOf(specLoader).specForType(value.getClass()); + allowing(specLoader).specForType(value.getClass()); will(returnValue(Optional.of(mockObjectSpec))); } }); @@ -334,7 +334,7 @@ public class JsonValueEncoderTest_asAdapter { representation = new JsonRepresentation(DecimalNode.valueOf(value)); context.checking(new Expectations() { { - oneOf(specLoader).specForType(value.getClass()); + allowing(specLoader).specForType(value.getClass()); will(returnValue(Optional.of(mockObjectSpec))); } @@ -368,7 +368,7 @@ public class JsonValueEncoderTest_asAdapter { context.checking(new Expectations() { { - oneOf(specLoader).specForType(String.class); + allowing(specLoader).specForType(String.class); will(returnValue(Optional.of(mockObjectSpec))); } }); @@ -398,6 +398,9 @@ public class JsonValueEncoderTest_asAdapter { allowing(mockValueFacet).getValueClass(); will(returnValue(valueClass)); + allowing(mockObjectSpec).isNonScalar(); + will(returnValue(true)); + } }); }