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

commit be37a5767835216f0574bc26ba30d0ef672ae197
Author: Andi Huber <ahu...@apache.org>
AuthorDate: Mon Aug 29 09:29:13 2022 +0200

    ISIS-3167: properly implement common spec finder
---
 .../isis/core/metamodel/object/ManagedObject.java  |  1 +
 .../isis/core/metamodel/object/ManagedObjects.java | 29 +++++-----------------
 .../core/metamodel/spec/ObjectSpecification.java   | 25 +++++++++++++++++++
 .../runtimeservices/memento/_ObjectMemento.java    | 23 ++++++++++-------
 .../xmlsnapshot/XmlSnapshotServiceDefault.java     |  8 +++---
 .../wkt/viewer/EventProviderAbstract.java          |  2 +-
 .../components/tree/IsisToWicketTreeAdapter.java   |  2 +-
 .../viewer/services/DeepLinkServiceWicket.java     |  2 +-
 8 files changed, 53 insertions(+), 39 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 71cc7e5872..17eca64550 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
@@ -191,6 +191,7 @@ public interface ManagedObject extends HasMetaModelContext {
          * @see PojoPolicy#NO_POJO
          */
         public boolean isUnspecified() { return this == UNSPECIFIED; }
+        public boolean isSpecified() { return this != UNSPECIFIED; }
         /**
          * EMPTY
          * @see TypePolicy#ABSTRACT_TYPE_ALLOWED
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 af9fed768f..8623d56a1e 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
@@ -341,10 +341,8 @@ public final class ManagedObjects {
     // -- COMMON SUPER TYPE FINDER
 
     /**
-     * Find an ObjectSpecification that is common to all provided {@code 
objects}
-     * @param objects
-     * @return optionally the common ObjectSpecification based on whether 
provided {@code objects}
-     * are not empty
+     * Optionally the common {@link ObjectSpecification} based on whether 
provided {@code objects}
+     * have any at all.
      */
     public static Optional<ObjectSpecification> commonSpecification(
             final @Nullable Can<ManagedObject> objects) {
@@ -352,26 +350,11 @@ public final class ManagedObjects {
         if (_NullSafe.isEmpty(objects)) {
             return Optional.empty();
         }
-        val firstElement = objects.getFirstOrFail();
-        val firstElementSpec = firstElement.getSpecification();
 
-        if(objects.getCardinality().isOne()) {
-            return Optional.of(firstElementSpec);
-        }
-
-        val commonSuperClassFinder = new 
ClassExtensions.CommonSuperclassFinder();
-        objects.stream()
-        .map(ManagedObject::getPojo)
-        .filter(_NullSafe::isPresent)
-        .forEach(commonSuperClassFinder::collect);
-
-        val commonSuperClass = 
commonSuperClassFinder.getCommonSuperclass().orElse(null);
-        if(commonSuperClass!=null && 
commonSuperClass!=firstElement.getSpecification().getCorrespondingClass()) {
-            val specificationLoader = 
firstElementSpec.getMetaModelContext().getSpecificationLoader();
-            return specificationLoader.specForType(commonSuperClass);
-        }
-
-        return Optional.of(firstElementSpec);
+        return objects.stream()
+        .filter(obj->obj.getSpecialization().isSpecified())
+        .map(ManagedObject::getSpecification)
+        .reduce(ObjectSpecification::commonSuperType);
     }
 
     // -- ADABT UTILITIES
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 7bc9d9ae9d..976b36f4b5 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
@@ -36,6 +36,7 @@ import org.apache.isis.applib.id.HasLogicalType;
 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.internal.assertions._Assert;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Streams;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
@@ -577,6 +578,30 @@ extends
                 : Stream.of(this);
     }
 
+    // -- COMMON SUPER TYPE FINDER
+
+    /**
+     * Lowest common ancestor search within the combined type hierarchy.
+     */
+    public static ObjectSpecification commonSuperType(
+            final @NonNull ObjectSpecification a,
+            final @NonNull ObjectSpecification b) {
+
+        val cls_a = a.getCorrespondingClass();
+        val cls_b = b.getCorrespondingClass();
+        if(cls_a.isAssignableFrom(cls_b)) {
+            return a;
+        }
+        if(cls_b.isAssignableFrom(cls_a)) {
+            return b;
+        }
+        // assuming the algorithm is correct: if non of the above is true,
+        // we must be able to walk up the tree on both branches
+        _Assert.assertNotNull(a.superclass());
+        _Assert.assertNotNull(b.superclass());
+        return commonSuperType(a.superclass(), b.superclass());
+    }
+
     // -- VALUE SEMANTICS SUPPORT
 
     /** introduced for lookup optimization / allow memoization */
diff --git 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/_ObjectMemento.java
 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/_ObjectMemento.java
index 3aa85515e4..bc151d117c 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/_ObjectMemento.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/memento/_ObjectMemento.java
@@ -21,7 +21,6 @@ package org.apache.isis.core.runtimeservices.memento;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.Objects;
 import java.util.function.Function;
 
@@ -32,9 +31,9 @@ import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.Oid;
 import org.apache.isis.applib.services.hint.HintIdProvider;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
@@ -124,9 +123,15 @@ final class _ObjectMemento implements HasLogicalType, 
Serializable {
                     final _ObjectMemento memento,
                     final MetaModelContext mmc) {
 
-                final List<Object> listOfPojos =
-                        _Lists.map(memento.list, Functions.toPojo(mmc));
-                return ManagedObject.lazy(mmc.getSpecificationLoader(), 
listOfPojos);
+                final Can<ManagedObject> managedObjects =
+                        _NullSafe.stream(memento.list)
+                        .map(Functions.toManagedObject(mmc))
+                        .collect(Can.toCan());
+
+                val commonSpec = 
ManagedObjects.commonSpecification(managedObjects)
+                        
.orElseGet(()->mmc.getSpecificationLoader().loadSpecification(Object.class));
+
+                return ManagedObject.packed(commonSpec, managedObjects);
             }
 
             @Override
@@ -576,19 +581,19 @@ final class _ObjectMemento implements HasLogicalType, 
Serializable {
     @NoArgsConstructor(access = AccessLevel.PRIVATE)
     private static final class Functions {
 
-        private static Function<_ObjectMemento, Object> toPojo(
+        private static Function<_ObjectMemento, ManagedObject> toManagedObject(
                 final MetaModelContext mmc) {
 
             return memento->{
                 if(memento == null) {
-                    return null;
+                    return ManagedObject.unspecified();
                 }
                 val objectAdapter = memento
                         .reconstructObject(mmc);
                 if(objectAdapter == null) {
-                    return null;
+                    return ManagedObject.unspecified();
                 }
-                return objectAdapter.getPojo();
+                return objectAdapter;
             };
         }
 
diff --git 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xmlsnapshot/XmlSnapshotServiceDefault.java
 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xmlsnapshot/XmlSnapshotServiceDefault.java
index 4d56ca8ce2..669b1ae402 100644
--- 
a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xmlsnapshot/XmlSnapshotServiceDefault.java
+++ 
b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/xmlsnapshot/XmlSnapshotServiceDefault.java
@@ -60,17 +60,17 @@ public class XmlSnapshotServiceDefault implements 
XmlSnapshotService {
     static class XmlSnapshotServiceDefaultBuilder implements 
XmlSnapshotService.Snapshot.Builder{
 
         private final XmlSnapshotBuilder builder;
-        public XmlSnapshotServiceDefaultBuilder(SpecificationLoader 
specificationLoader, Object domainObject) {
+        public XmlSnapshotServiceDefaultBuilder(final SpecificationLoader 
specificationLoader, final Object domainObject) {
             builder = new XmlSnapshotBuilder(specificationLoader, 
domainObject);
         }
 
         @Override
-        public void includePath(String path) {
+        public void includePath(final String path) {
             builder.includePath(path);
         }
 
         @Override
-        public void includePathAndAnnotation(String path, String annotation) {
+        public void includePathAndAnnotation(final String path, final String 
annotation) {
             builder.includePathAndAnnotation(path, annotation);
         }
 
@@ -86,7 +86,7 @@ public class XmlSnapshotServiceDefault implements 
XmlSnapshotService {
      */
     @Override
     public XmlSnapshotService.Snapshot snapshotFor(final Object domainObject) {
-        final ManagedObject adapter = ManagedObject.lazy(specificationLoader, 
domainObject);
+        final ManagedObject adapter = 
ManagedObject.wrapScalar(specificationLoader, domainObject);
         return new XmlSnapshot(adapter);
     }
 
diff --git 
a/extensions/vw/fullcalendar/wicket/ui/src/main/java/org/apache/isis/extensions/fullcalendar/wkt/viewer/EventProviderAbstract.java
 
b/extensions/vw/fullcalendar/wicket/ui/src/main/java/org/apache/isis/extensions/fullcalendar/wkt/viewer/EventProviderAbstract.java
index c9c7590451..012cacff38 100644
--- 
a/extensions/vw/fullcalendar/wicket/ui/src/main/java/org/apache/isis/extensions/fullcalendar/wkt/viewer/EventProviderAbstract.java
+++ 
b/extensions/vw/fullcalendar/wicket/ui/src/main/java/org/apache/isis/extensions/fullcalendar/wkt/viewer/EventProviderAbstract.java
@@ -121,7 +121,7 @@ public abstract class EventProviderAbstract implements 
EventProvider {
             final Object dereferencedObject = dereference(commonContext, 
domainObjectPojo);
 
             val dereferencedManagedObject =
-                    ManagedObject.lazy(commonContext.getSpecificationLoader(), 
dereferencedObject);
+                    
ManagedObject.wrapScalar(commonContext.getSpecificationLoader(), 
dereferencedObject);
 
             val oid = 
ManagedObjects.bookmark(dereferencedManagedObject).orElse(null);
             if(oid!=null) {
diff --git 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
index e2467c8a9d..621dfb6fcb 100644
--- 
a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
+++ 
b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/tree/IsisToWicketTreeAdapter.java
@@ -259,7 +259,7 @@ class IsisToWicketTreeAdapter {
             this.commonContext = commonContext;
             this.factoryService = 
commonContext.lookupServiceElseFail(FactoryService.class);
             this.pojoToAdapter = pojo ->
-                ManagedObject.lazy(commonContext.getSpecificationLoader(), 
pojo);
+                
ManagedObject.wrapScalar(commonContext.getSpecificationLoader(), pojo);
         }
 
         private TreeAdapter wrappedTreeAdapter() {
diff --git 
a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/DeepLinkServiceWicket.java
 
b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/DeepLinkServiceWicket.java
index cc3f891315..bbfdde5944 100644
--- 
a/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/DeepLinkServiceWicket.java
+++ 
b/viewers/wicket/viewer/src/main/java/org/apache/isis/viewer/wicket/viewer/services/DeepLinkServiceWicket.java
@@ -58,7 +58,7 @@ public class DeepLinkServiceWicket implements DeepLinkService 
{
     @Override
     public URI deepLinkFor(final Object domainObject) {
 
-        final ManagedObject objectAdapter = 
ManagedObject.lazy(specificationLoader, domainObject);
+        final ManagedObject objectAdapter = 
ManagedObject.wrapScalar(specificationLoader, domainObject);
 
         final PageParameters pageParameters = 
PageParameterUtils.createPageParametersForObject(objectAdapter);
 

Reply via email to