You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/10/13 07:32:36 UTC

[isis] branch master updated: ISIS-3226: use InteractionInitiatedBy.PASS_THROUGH when accessing properties for serialization

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 e2c66398e0 ISIS-3226: use InteractionInitiatedBy.PASS_THROUGH when accessing properties for serialization
e2c66398e0 is described below

commit e2c66398e060dba2d3febe26f941405ec39a3105
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Oct 13 09:32:28 2022 +0200

    ISIS-3226: use InteractionInitiatedBy.PASS_THROUGH when accessing
    properties for serialization
---
 .../apache/isis/applib/annotation/Snapshot.java    |  3 ++
 .../ViewModelFacetForDomainObjectAnnotation.java   | 50 ++++++++++++----------
 .../PropertyOrCollectionAccessorFacet.java         |  2 +-
 ...tySetterOrClearFacetForDomainEventAbstract.java |  6 ++-
 .../core/metamodel/object/MmVisibilityUtil.java    |  2 +-
 .../spec/feature/OneToOneAssociation.java          | 10 ++++-
 .../specimpl/OneToOneAssociationDefault.java       |  9 ++--
 .../core/metamodel/util/snapshot/XmlSnapshot.java  |  4 +-
 .../specimpl/OneToOneAssociationAbstractTest.java  |  6 +--
 9 files changed, 58 insertions(+), 34 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/annotation/Snapshot.java b/api/applib/src/main/java/org/apache/isis/applib/annotation/Snapshot.java
index 145951e83d..bfb1185195 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/annotation/Snapshot.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/annotation/Snapshot.java
@@ -21,6 +21,9 @@ package org.apache.isis.applib.annotation;
 /**
  * Whether the property is included if the domain object graph is serialized
  * into a snapshot.
+ * <p>
+ * This also affects viewmodel serialization, when using the 'fallback' serialization strategy.
+ *
  * @since 2.x {@index}
  */
 public enum Snapshot {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForDomainObjectAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForDomainObjectAnnotation.java
index 2c06c82e8b..30a0fc2bfb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForDomainObjectAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForDomainObjectAnnotation.java
@@ -20,6 +20,7 @@ package org.apache.isis.core.metamodel.facets.object.viewmodel;
 
 import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.services.bookmark.Bookmark;
@@ -35,6 +36,7 @@ import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySe
 import org.apache.isis.core.metamodel.object.ManagedObject;
 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.OneToOneAssociation;
 
 import lombok.NonNull;
 import lombok.val;
@@ -106,17 +108,21 @@ extends ViewModelFacetAbstract {
 
         val objectManager = super.getObjectManager();
 
-        viewmodelSpec.streamProperties(MixedIn.EXCLUDED)
-        .filter(property->mementoKeys.contains(property.getId()))
+        streamPersistableProperties(viewmodelSpec)
         .forEach(property->{
 
+            // we also explicitly set 'nulled' properties
+
             val propertyId = property.getId();
-            val propertyType = property.getElementType().getCorrespondingClass();
-            val propertyValue = memento.get(propertyId, propertyType);
+            val propertySpec = property.getElementType();
+            val propertyType = propertySpec.getCorrespondingClass();
+            val propertyPojo = memento.get(propertyId, propertyType);
+            final ManagedObject propertyValue = propertyPojo!=null
+                    ? objectManager.adapt(propertyPojo)
+                    : ManagedObject.empty(propertySpec);
+
+            property.set(viewmodel, propertyValue, InteractionInitiatedBy.PASS_THROUGH);
 
-            if(propertyValue != null) {
-                property.set(viewmodel, objectManager.adapt(propertyValue), InteractionInitiatedBy.FRAMEWORK);
-            }
         });
 
         return viewmodel;
@@ -127,23 +133,14 @@ extends ViewModelFacetAbstract {
 
         final _Mementos.Memento memento = newMemento();
 
-        /*
-         * ManagedObject that holds the ObjectSpecification used for
-         * interrogating the domain object's metadata.
-         *
-         * Does _not_ perform dependency injection on the domain object. Also bypasses
-         * caching (if any), that is each call to this method creates a new instance.
-         */
-        val spec = viewModel.getSpecification();
-
-        spec.streamProperties(MixedIn.EXCLUDED)
-        // ignore read-only
-        .filter(property->property.containsNonFallbackFacet(PropertySetterFacet.class))
-        // ignore those explicitly annotated as @NotPersisted
-        .filter(property->!property.isNotPersisted())
+        val viewmodelSpec = viewModel.getSpecification();
+
+        streamPersistableProperties(viewmodelSpec)
         .forEach(property->{
+
             final ManagedObject propertyValue =
-                    property.get(viewModel, InteractionInitiatedBy.FRAMEWORK);
+                    property.get(viewModel, InteractionInitiatedBy.PASS_THROUGH);
+
             if(propertyValue != null
                     && propertyValue.getPojo()!=null) {
                 memento.put(property.getId(), propertyValue.getPojo());
@@ -155,6 +152,15 @@ extends ViewModelFacetAbstract {
 
     // -- HELPER
 
+    private Stream<OneToOneAssociation> streamPersistableProperties(
+            final @NonNull ObjectSpecification viewmodelSpec) {
+        return viewmodelSpec.streamProperties(MixedIn.EXCLUDED)
+                // ignore read-only
+                .filter(property->property.containsNonFallbackFacet(PropertySetterFacet.class))
+                // ignore those explicitly annotated as @Property(snapshot = Snapshot.EXCLUDED)
+                .filter(property->property.isIncludedWithSnapshots());
+    }
+
     private void initDependencies() {
         val serviceRegistry = getServiceRegistry();
         this.codec = serviceRegistry.lookupServiceElseFail(UrlEncodingService.class);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/propcoll/accessor/PropertyOrCollectionAccessorFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/propcoll/accessor/PropertyOrCollectionAccessorFacet.java
index 3f8d499079..b32a100cb7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/propcoll/accessor/PropertyOrCollectionAccessorFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/propcoll/accessor/PropertyOrCollectionAccessorFacet.java
@@ -44,7 +44,7 @@ public interface PropertyOrCollectionAccessorFacet extends Facet {
      * @param inObject
      * @param interactionInitiatedBy
      */
-    public Object getProperty(
+    Object getProperty(
             final ManagedObject inObject,
             final InteractionInitiatedBy interactionInitiatedBy);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
index b2ceca7743..42a5369b9c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/modify/PropertySetterOrClearFacetForDomainEventAbstract.java
@@ -59,7 +59,7 @@ implements
     private final PropertySetterFacet setterFacet;
     private final PropertyClearFacet clearFacet;
 
-    public PropertySetterOrClearFacetForDomainEventAbstract(
+    protected PropertySetterOrClearFacetForDomainEventAbstract(
             final Class<? extends Facet> facetType,
             final Class<? extends PropertyDomainEvent<?, ?>> eventType,
                     final PropertyOrCollectionAccessorFacet getterFacet,
@@ -259,6 +259,10 @@ implements
             return head.getTarget();
         }
 
+        if(interactionInitiatedBy.isPassThrough()) {
+
+        }
+
         return getMemberExecutor().setOrClearProperty(
                 owningProperty,
                 head,
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmVisibilityUtil.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmVisibilityUtil.java
index fb1a33dbe2..3a078e70d0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmVisibilityUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/object/MmVisibilityUtil.java
@@ -103,7 +103,7 @@ public final class MmVisibilityUtil {
                 return false;
             }
         }
-        if(interactionInitiatedBy == InteractionInitiatedBy.FRAMEWORK) {
+        if(!interactionInitiatedBy.isUser()) {
             return true;
         }
         val visibilityContext = createVisibleInteractionContext(
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java
index 5de9c8dd68..fff734c682 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/OneToOneAssociation.java
@@ -55,11 +55,19 @@ extends
     /**
      * Returns true if calculated from other data in the object, that is, should
      * not be persisted.
+     * Corresponds to {@code @Property(snapshot = Snapshot.EXCLUDED)}
      */
-    default boolean isNotPersisted() {
+    default boolean isExcludedFromSnapshots() {
         return containsFacet(SnapshotExcludeFacet.class);
     }
 
+    /**
+     * Counterpart to {@link #isExcludedFromSnapshots()}.
+     */
+    default boolean isIncludedWithSnapshots() {
+        return !isExcludedFromSnapshots();
+    }
+
     default String getCssClass(final String prefix) {
         final String ownerObjectType = getDeclaringType().getLogicalTypeName().replace(".", "-");
         final String memberId = getFeatureIdentifier().getMemberLogicalName();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
index 10d7f08c1f..07d2445363 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
@@ -174,7 +174,7 @@ implements OneToOneAssociation {
      * ({@link PropertySetterFacet} or {@link PropertyClearFacet}).
      */
     @Override
-    public ManagedObject set(
+    public final ManagedObject set(
             final ManagedObject ownerAdapter,
             final ManagedObject _newValue,
             final InteractionInitiatedBy interactionInitiatedBy) {
@@ -184,7 +184,10 @@ implements OneToOneAssociation {
                 ? ManagedObject.empty(getElementType())
                 : _newValue;
 
-        setupCommand(InteractionHead.regular(ownerAdapter), newValue);
+        // don't setup a command DTO, eg. when called in the context of serialization
+        if(!interactionInitiatedBy.isPassThrough()) {
+            setupCommand(InteractionHead.regular(ownerAdapter), newValue);
+        }
 
         if (ManagedObjects.isNullOrUnspecifiedOrEmpty(newValue)) {
             return clearValue(ownerAdapter, interactionInitiatedBy);
@@ -325,7 +328,7 @@ implements OneToOneAssociation {
         final ToString str = new ToString(this);
         str.append(super.toString());
         str.setAddComma();
-        str.append("persisted", !isNotPersisted());
+        str.append("persisted", isIncludedWithSnapshots());
         str.append("type", getElementType().getShortIdentifier());
         return str.toString();
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
index 15f5876e44..109eacd7b5 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/util/snapshot/XmlSnapshot.java
@@ -495,7 +495,7 @@ public class XmlSnapshot implements Snapshot {
 
             final OneToOneAssociation oneToOneAssociation = ((OneToOneAssociation) field);
 
-            if(oneToOneAssociation.isNotPersisted()) {
+            if(oneToOneAssociation.isExcludedFromSnapshots()) {
                 return false;
             }
             final ManagedObject referencedObject = oneToOneAssociation.get(fieldPlace.getObject(),
@@ -693,7 +693,7 @@ public class XmlSnapshot implements Snapshot {
                 }
 
                 final OneToOneAssociation valueAssociation = ((OneToOneAssociation) field);
-                if(valueAssociation.isNotPersisted()) {
+                if(valueAssociation.isExcludedFromSnapshots()) {
                     continue eachField;
                 }
                 final Element xmlValueElement = xmlFieldElement; // more meaningful locally scoped name
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationAbstractTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationAbstractTest.java
index efa910db97..9591199de5 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationAbstractTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToOneAssociationAbstractTest.java
@@ -146,19 +146,19 @@ class OneToOneAssociationAbstractTest {
     public void notPersistedWhenDerived() throws Exception {
         final SnapshotExcludeFacet mockFacet = mockFacetIgnoring(SnapshotExcludeFacet.class, Precedence.DEFAULT);
         facetedMethod.addFacet(mockFacet);
-        assertTrue(objectAssociation.isNotPersisted());
+        assertTrue(objectAssociation.isExcludedFromSnapshots());
     }
 
     @Test
     public void notPersistedWhenFlaggedAsNotPersisted() throws Exception {
         final SnapshotExcludeFacet mockFacet = mockFacetIgnoring(SnapshotExcludeFacet.class, Precedence.DEFAULT);
         facetedMethod.addFacet(mockFacet);
-        assertTrue(objectAssociation.isNotPersisted());
+        assertTrue(objectAssociation.isExcludedFromSnapshots());
     }
 
     @Test
     public void persisted() throws Exception {
-        assertFalse(objectAssociation.isNotPersisted());
+        assertFalse(objectAssociation.isExcludedFromSnapshots());
     }
 
     private <T extends Facet> T mockFacetIgnoring(final Class<T> typeToMock, final Precedence precedence) {