This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch v3
in repository https://gitbox.apache.org/repos/asf/causeway.git


The following commit(s) were added to refs/heads/v3 by this push:
     new c57ed24418e CAUSEWAY-2297: ditch PropertyMemento (instead make 
one2one-assoc serializable)
c57ed24418e is described below

commit c57ed24418e98e1d57a69ca45d1511f62262fca1
Author: Andi Huber <[email protected]>
AuthorDate: Sat Nov 23 19:05:36 2024 +0100

    CAUSEWAY-2297: ditch PropertyMemento (instead make one2one-assoc
    serializable)
---
 .../spec/feature/OneToOneAssociation.java          |  8 ---
 .../spec/feature/memento/PropertyMemento.java      | 81 ----------------------
 .../specimpl/OneToOneAssociationDefault.java       | 31 ++++++++-
 .../specimpl/OneToOneAssociationMixedIn.java       |  1 +
 .../domainmodel/DomainModelTest_serialization.java | 23 ++++++
 .../viewer/wicket/model/models/UiObjectWkt.java    | 23 +++---
 6 files changed, 65 insertions(+), 102 deletions(-)

diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/OneToOneAssociation.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/OneToOneAssociation.java
index 74a3b8b3e01..d34335dab85 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/OneToOneAssociation.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/OneToOneAssociation.java
@@ -22,7 +22,6 @@ import org.apache.causeway.core.metamodel.consent.Consent;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
 import 
org.apache.causeway.core.metamodel.facets.propcoll.memserexcl.SnapshotExcludeFacet;
 import org.apache.causeway.core.metamodel.object.ManagedObject;
-import org.apache.causeway.core.metamodel.spec.feature.memento.PropertyMemento;
 
 /**
  * Provides reflective access to a field on a domain object that is used to
@@ -74,11 +73,4 @@ extends
         return prefix + ownerObjectType + "-" + memberId;
     }
 
-    /**
-     * Returns a serializable representation of this property.
-     */
-    default PropertyMemento getMemento() {
-        return PropertyMemento.forProperty(this);
-    }
-
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/memento/PropertyMemento.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/memento/PropertyMemento.java
deleted file mode 100644
index ed7a713addd..00000000000
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/spec/feature/memento/PropertyMemento.java
+++ /dev/null
@@ -1,81 +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.causeway.core.metamodel.spec.feature.memento;
-
-import java.io.Serializable;
-import java.util.function.Supplier;
-
-import org.apache.causeway.applib.Identifier;
-import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.causeway.core.metamodel.specloader.SpecificationLoader;
-
-import lombok.AccessLevel;
-import lombok.AllArgsConstructor;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.Synchronized;
-
-/**
- * {@link Serializable} representation of an {@link OneToOneAssociation}
- *
- * @implNote thread-safe memoization
- *
- * @since 2.0 {index}
- */
-@EqualsAndHashCode
-@AllArgsConstructor(access = AccessLevel.PROTECTED)
-public class PropertyMemento implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @EqualsAndHashCode.Include
-    @Getter private final @NonNull Identifier identifier;
-
-    // -- FACTORY
-
-    public static PropertyMemento forProperty(final @NonNull 
OneToOneAssociation property) {
-        return new PropertyMemento(
-                property.getFeatureIdentifier(),
-                property);
-    }
-
-    // -- LOAD/UNMARSHAL
-
-    @EqualsAndHashCode.Exclude
-    private transient OneToOneAssociation property;
-
-    @Synchronized
-    public OneToOneAssociation getProperty(final @NonNull 
Supplier<SpecificationLoader> specLoader) {
-        if (property == null) {
-            property = specLoader.get()
-                    
.specForLogicalTypeElseFail(getIdentifier().getLogicalType())
-                    
.getPropertyElseFail(getIdentifier().getMemberLogicalName());
-        }
-        return property;
-    }
-
-    // -- OBJECT CONTRACT
-
-    @Override
-    public String toString() {
-        return getIdentifier().getLogicalTypeName() + "#" + 
getIdentifier().getMemberLogicalName();
-    }
-
-}
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
index f0e7b6c3ccb..b25cb3fb118 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
@@ -18,6 +18,10 @@
  */
 package org.apache.causeway.core.metamodel.specloader.specimpl;
 
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
 import org.apache.causeway.applib.Identifier;
 import org.apache.causeway.applib.annotation.Property;
 import org.apache.causeway.applib.annotation.PropertyLayout;
@@ -29,6 +33,7 @@ import 
org.apache.causeway.commons.internal.exceptions._Exceptions;
 import org.apache.causeway.core.metamodel.commons.ToString;
 import org.apache.causeway.core.metamodel.consent.Consent;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.causeway.core.metamodel.context.MetaModelContext;
 import org.apache.causeway.core.metamodel.facetapi.FeatureType;
 import org.apache.causeway.core.metamodel.facets.FacetedMethod;
 import 
org.apache.causeway.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
@@ -58,7 +63,8 @@ import lombok.Getter;
 
 public class OneToOneAssociationDefault
 extends ObjectAssociationAbstract
-implements OneToOneAssociation {
+implements OneToOneAssociation, Serializable {
+    private static final long serialVersionUID = 1L;
 
     // -- FACTORY
 
@@ -342,4 +348,27 @@ implements OneToOneAssociation {
                 || methodFacade.synthesize(PropertyLayout.class).isPresent();
     }
 
+    // -- SERIALIZATION PROXY
+
+    protected final Object writeReplace() {
+        return new SerializationProxy(this);
+    }
+
+    protected final void readObject(final ObjectInputStream stream) throws 
InvalidObjectException {
+        throw new InvalidObjectException("Proxy required");
+    }
+
+    protected record SerializationProxy(Identifier identifier) implements 
Serializable {
+        SerializationProxy(final OneToOneAssociationDefault property) {
+            this(property.getFeatureIdentifier());
+        }
+        private Object readResolve() {
+            return MetaModelContext.instanceElseFail()
+                .getSpecificationLoader()
+                .specForLogicalTypeElseFail(identifier.getLogicalType())
+                .getPropertyElseFail(
+                        identifier.getMemberLogicalName());
+        }
+    }
+
 }
diff --git 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
index b1b30ca7c9e..3ab7e884a85 100644
--- 
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
+++ 
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
@@ -43,6 +43,7 @@ import lombok.Getter;
 public class OneToOneAssociationMixedIn
 extends OneToOneAssociationDefault
 implements MixedInMember {
+    private static final long serialVersionUID = 1L;
 
     // -- FACTORIES
 
diff --git 
a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_serialization.java
 
b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_serialization.java
index 10d589633e1..9c9188b685e 100644
--- 
a/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_serialization.java
+++ 
b/regressiontests/domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/DomainModelTest_serialization.java
@@ -34,6 +34,8 @@ import 
org.apache.causeway.core.metamodel.specloader.specimpl.ObjectActionDefaul
 import 
org.apache.causeway.core.metamodel.specloader.specimpl.ObjectActionMixedIn;
 import 
org.apache.causeway.core.metamodel.specloader.specimpl.OneToManyAssociationDefault;
 import 
org.apache.causeway.core.metamodel.specloader.specimpl.OneToManyAssociationMixedIn;
+import 
org.apache.causeway.core.metamodel.specloader.specimpl.OneToOneAssociationDefault;
+import 
org.apache.causeway.core.metamodel.specloader.specimpl.OneToOneAssociationMixedIn;
 import org.apache.causeway.testdomain.conf.Configuration_headless;
 import 
org.apache.causeway.testdomain.model.good.Configuration_usingValidDomain;
 import org.apache.causeway.testdomain.model.good.ProperMemberSupport;
@@ -58,6 +60,8 @@ class DomainModelTest_serialization extends 
CausewayIntegrationTestAbstract {
 
     @Inject private SpecificationLoader specificationLoader;
 
+    // -- ACT
+
     @Test
     void objectActionDefault_shouldBe_Serializable() {
         var holderSpec = 
specificationLoader.specForTypeElseFail(ProperMemberSupport.class);
@@ -73,6 +77,25 @@ class DomainModelTest_serialization extends 
CausewayIntegrationTestAbstract {
         _SerializationTester.assertEqualsOnRoundtrip(act);
     }
 
+    // -- PROP
+
+    @Test
+    void oneToOneAssociationDefault_shouldBe_Serializable() {
+        var holderSpec = 
specificationLoader.specForTypeElseFail(ProperMemberSupport.class);
+        var prop = (OneToOneAssociationDefault) 
holderSpec.getPropertyElseFail("myProp");
+        assertEquals(OneToOneAssociationDefault.class, prop.getClass());
+        _SerializationTester.assertEqualsOnRoundtrip(prop);
+    }
+    @Test
+    void oneToOneAssociationMixedIn_shouldBe_Serializable() {
+        var holderSpec = 
specificationLoader.specForTypeElseFail(ProperMemberSupport.class);
+        var prop = (OneToOneAssociationMixedIn) 
holderSpec.getPropertyElseFail("property1");
+        assertEquals(OneToOneAssociationMixedIn.class, prop.getClass());
+        _SerializationTester.assertEqualsOnRoundtrip(prop);
+    }
+
+    // -- COLL
+
     @Test
     void oneToManyAssociationDefault_shouldBe_Serializable() {
         var holderSpec = 
specificationLoader.specForTypeElseFail(ProperMemberSupport.class);
diff --git 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
index d29b2605081..f039baafcea 100644
--- 
a/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
+++ 
b/viewers/wicket/model/src/main/java/org/apache/causeway/viewer/wicket/model/models/UiObjectWkt.java
@@ -18,6 +18,7 @@
  */
 package org.apache.causeway.viewer.wicket.model.models;
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 import java.util.stream.Stream;
@@ -28,6 +29,7 @@ import org.apache.wicket.request.resource.ResourceReference;
 
 import org.springframework.lang.Nullable;
 
+import org.apache.causeway.applib.Identifier;
 import 
org.apache.causeway.applib.exceptions.unrecoverable.ObjectNotFoundException;
 import org.apache.causeway.applib.fa.FontAwesomeLayers;
 import org.apache.causeway.applib.services.bookmark.Bookmark;
@@ -35,7 +37,6 @@ import org.apache.causeway.applib.services.hint.HintStore;
 import org.apache.causeway.commons.functional.Either;
 import org.apache.causeway.commons.internal.assertions._Assert;
 import org.apache.causeway.commons.internal.base._NullSafe;
-import org.apache.causeway.commons.internal.collections._Maps;
 import org.apache.causeway.core.metamodel.commons.ViewOrEditMode;
 import org.apache.causeway.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.causeway.core.metamodel.facets.object.icon.ObjectIcon;
@@ -43,7 +44,6 @@ import 
org.apache.causeway.core.metamodel.object.ManagedObject;
 import org.apache.causeway.core.metamodel.object.ManagedObjects;
 import org.apache.causeway.core.metamodel.spec.feature.MixedIn;
 import org.apache.causeway.core.metamodel.spec.feature.OneToOneAssociation;
-import org.apache.causeway.core.metamodel.spec.feature.memento.PropertyMemento;
 import org.apache.causeway.viewer.commons.model.hints.RenderingHint;
 import org.apache.causeway.viewer.commons.model.object.UiObject;
 import org.apache.causeway.viewer.wicket.model.hints.UiHintContainer;
@@ -200,10 +200,10 @@ implements
 
     // -- PROPERTY MODELS (CHILDREN)
 
-    private transient Map<PropertyMemento, ScalarPropertyModel> 
propertyScalarModels;
-    private Map<PropertyMemento, ScalarPropertyModel> propertyScalarModels() {
+    private transient Map<Identifier, ScalarPropertyModel> 
propertyScalarModels;
+    private Map<Identifier, ScalarPropertyModel> propertyScalarModels() {
         if(propertyScalarModels==null) {
-            propertyScalarModels = _Maps.<PropertyMemento, 
ScalarPropertyModel>newHashMap();
+            propertyScalarModels = new HashMap<>();
         }
         return propertyScalarModels;
     }
@@ -231,29 +231,29 @@ implements
                     bookmarkedObjectModel.getBookmark().getIdentifier());
         }
 
-        var pm = property.getMemento();
+        var propIdentifier = property.getFeatureIdentifier();
         var propertyScalarModels = propertyScalarModels();
-        final ScalarModel existingScalarModel = propertyScalarModels.get(pm);
+        final ScalarModel existingScalarModel = 
propertyScalarModels.get(propIdentifier);
         if (existingScalarModel != null) {
             return existingScalarModel;
         }
 
         var propertyInteractionModel = new PropertyInteractionWkt(
                 bookmarkedObjectModel,
-                pm.getIdentifier().getMemberLogicalName(),
+                propIdentifier.getMemberLogicalName(),
                 renderingHint.asWhere());
 
         final long modelsAdded = 
propertyInteractionModel.streamPropertyUiModels()
         .map(uiModel->ScalarPropertyModel.wrap(uiModel, viewOrEdit, 
renderingHint))
         .peek(scalarModel->log.debug("adding: {}", scalarModel))
-        .filter(scalarModel->propertyScalarModels.put(pm, scalarModel)==null)
+        .filter(scalarModel->propertyScalarModels.put(propIdentifier, 
scalarModel)==null)
         .count(); // consume the stream
 
         // future extensions might allow to add multiple UI models per single 
property model (typed tuple support)
         _Assert.assertEquals(1L, modelsAdded, ()->
             String.format("unexpected number of propertyScalarModels added 
%d", modelsAdded));
 
-        return propertyScalarModels.get(pm);
+        return propertyScalarModels.get(propIdentifier);
     }
 
     @Override
@@ -303,8 +303,7 @@ implements
     public boolean isContextAdapter(final ManagedObject other) {
         return contextBookmarkIfAny==null
                 ? false
-                : Objects.equals(contextBookmarkIfAny, 
other.getBookmark().orElse(null))
-                ;
+                : Objects.equals(contextBookmarkIfAny, 
other.getBookmark().orElse(null));
     }
 
     // -- HELPER

Reply via email to