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/08/29 07:29:22 UTC

[isis] branch master updated (da099afcc6 -> be37a57678)

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

ahuber pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


    from da099afcc6 ISIS-3167: ManagedObject:  equals/hashCode/toString side-effect-free
     new e93d8d7542 ISIS-3167: prepare removal of _ManagedObjectWithLazySpec
     new be37a57678 ISIS-3167: properly implement common spec finder

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../isis/core/metamodel/object/ManagedObject.java  | 117 +++++++++++++++------
 .../isis/core/metamodel/object/ManagedObjects.java |  29 ++---
 .../object/_ManagedObjectWithEagerSpec.java        |   1 +
 .../object/_ManagedObjectWithLazySpec.java         |   1 +
 .../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 +-
 10 files changed, 140 insertions(+), 70 deletions(-)


[isis] 02/02: ISIS-3167: properly implement common spec finder

Posted by ah...@apache.org.
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 <ah...@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);
 


[isis] 01/02: ISIS-3167: prepare removal of _ManagedObjectWithLazySpec

Posted by ah...@apache.org.
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 e93d8d7542bce535bb18ddddc86a671f4cd9ea72
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Aug 29 08:28:38 2022 +0200

    ISIS-3167: prepare removal of _ManagedObjectWithLazySpec
---
 .../isis/core/metamodel/object/ManagedObject.java  | 116 +++++++++++++++------
 .../object/_ManagedObjectWithEagerSpec.java        |   1 +
 .../object/_ManagedObjectWithLazySpec.java         |   1 +
 3 files changed, 87 insertions(+), 31 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 3d965b3416..71cc7e5872 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
@@ -32,7 +32,6 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.context.HasMetaModelContext;
 import org.apache.isis.core.metamodel.facets.object.icon.ObjectIcon;
 import org.apache.isis.core.metamodel.facets.object.title.TitleRenderRequest;
-import org.apache.isis.core.metamodel.object.ManagedObject.Specialization;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
@@ -365,63 +364,79 @@ public interface ManagedObject extends HasMetaModelContext {
 
     /**
      * Factory for Specialization#UNSPECIFIED.
-     * @see Specialization.TypePolicy#NO_TYPE
-     * @see Specialization.BookmarkPolicy#NO_BOOKMARK
-     * @see Specialization.PojoPolicy#NO_POJO
+     * @see ManagedObject.Specialization.TypePolicy#NO_TYPE
+     * @see ManagedObject.Specialization.BookmarkPolicy#NO_BOOKMARK
+     * @see ManagedObject.Specialization.PojoPolicy#NO_POJO
      */
     static ManagedObject unspecified() {
         return _ManagedObjectUnspecified.INSTANCE;
     }
     /**
      * EMPTY
-     * @see Specialization.TypePolicy#ABSTRACT_TYPE_ALLOWED
-     * @see Specialization.BookmarkPolicy#NO_BOOKMARK
-     * @see Specialization.PojoPolicy#NO_POJO
+     * @see ManagedObject.Specialization.TypePolicy#ABSTRACT_TYPE_ALLOWED
+     * @see ManagedObject.Specialization.BookmarkPolicy#NO_BOOKMARK
+     * @see ManagedObject.Specialization.PojoPolicy#NO_POJO
      */
     static ManagedObject empty(final @NonNull ObjectSpecification spec) {
-        return new _ManagedObjectWithEagerSpec(spec, null);
+        return new _ManagedObjectEmpty(spec);
     }
     /**
      * VALUE
-     * @see Specialization.TypePolicy#EXACT_TYPE_REQUIRED
-     * @see Specialization.BookmarkPolicy#IMMUTABLE
-     * @see Specialization.PojoPolicy#IMMUTABLE
+     * @param pojo
+     * @param spec
+     * @see ManagedObject.Specialization.TypePolicy#EXACT_TYPE_REQUIRED
+     * @see ManagedObject.Specialization.BookmarkPolicy#IMMUTABLE
+     * @see ManagedObject.Specialization.PojoPolicy#IMMUTABLE
      */
-    static ManagedObject value() {
-        return null; //FIXME
+    static ManagedObject value(
+            final @NonNull ObjectSpecification spec,
+            final @NonNull Object pojo) {
+        return new _ManagedObjectWithEagerSpec(spec, pojo); //FIXME
     }
     /**
      * SERVICE
-     * @see Specialization.TypePolicy#EXACT_TYPE_REQUIRED
-     * @see Specialization.BookmarkPolicy#IMMUTABLE
-     * @see Specialization.PojoPolicy#IMMUTABLE
+     * @param pojo
+     * @param spec
+     * @see ManagedObject.Specialization.TypePolicy#EXACT_TYPE_REQUIRED
+     * @see ManagedObject.Specialization.BookmarkPolicy#IMMUTABLE
+     * @see ManagedObject.Specialization.PojoPolicy#IMMUTABLE
      */
-    static ManagedObject service() {
-        return null; //FIXME
+    static ManagedObject service(
+            final @NonNull ObjectSpecification spec,
+            final @NonNull Object pojo) {
+        return new _ManagedObjectWithEagerSpec(spec, pojo); //FIXME
     }
     /**
      * VIEWMODEL
-     * @see Specialization.TypePolicy#EXACT_TYPE_REQUIRED
-     * @see Specialization.BookmarkPolicy#REFRESHABLE
-     * @see Specialization.PojoPolicy#STATEFUL
+     * @param pojo
+     * @param spec
+     * @see ManagedObject.Specialization.TypePolicy#EXACT_TYPE_REQUIRED
+     * @see ManagedObject.Specialization.BookmarkPolicy#REFRESHABLE
+     * @see ManagedObject.Specialization.PojoPolicy#STATEFUL
      */
-    static ManagedObject viewmodel() {
-        return null; //FIXME
+    static ManagedObject viewmodel(
+            final @NonNull ObjectSpecification spec,
+            final @NonNull Object pojo) {
+        return new _ManagedObjectWithEagerSpec(spec, pojo); //FIXME
     }
     /**
      * ENTITY
-     * @see Specialization.TypePolicy#EXACT_TYPE_REQUIRED
-     * @see Specialization.BookmarkPolicy#IMMUTABLE
-     * @see Specialization.PojoPolicy#REFETCHABLE
+     * @param pojo
+     * @param spec
+     * @see ManagedObject.Specialization.TypePolicy#EXACT_TYPE_REQUIRED
+     * @see ManagedObject.Specialization.BookmarkPolicy#IMMUTABLE
+     * @see ManagedObject.Specialization.PojoPolicy#REFETCHABLE
      */
-    static ManagedObject entity() {
-        return null; //FIXME
+    static ManagedObject entity(
+            final @NonNull ObjectSpecification spec,
+            final @NonNull Object pojo) {
+        return new _ManagedObjectWithEagerSpec(spec, pojo); //FIXME
     }
     /**
      * PACKED
-     * @see Specialization.TypePolicy#ABSTRACT_TYPE_ALLOWED
-     * @see Specialization.BookmarkPolicy#NO_BOOKMARK
-     * @see Specialization.PojoPolicy#PACKED
+     * @see ManagedObject.Specialization.TypePolicy#ABSTRACT_TYPE_ALLOWED
+     * @see ManagedObject.Specialization.BookmarkPolicy#NO_BOOKMARK
+     * @see ManagedObject.Specialization.PojoPolicy#PACKED
      */
     static PackedManagedObject packed(
             final @NonNull ObjectSpecification elementSpec,
@@ -429,6 +444,45 @@ public interface ManagedObject extends HasMetaModelContext {
         return new _ManagedObjectPacked(elementSpec, nonScalar);
     }
 
+    /**
+     * For cases, when the pojo's specification is not available and needs to be looked up.
+     * <p>
+     * Fails if the pojo is non-scalar.
+     * @param specLoader - required
+     * @param pojo - required, required non-scalar
+     */
+    static ManagedObject wrapScalar(
+            final @NonNull SpecificationLoader specLoader,
+            final @NonNull Object pojo) {
+        if(pojo instanceof ManagedObject) {
+            return (ManagedObject)pojo;
+        }
+        _Assert.assertFalse(_Collections.isCollectionOrArrayOrCanType(pojo.getClass()));
+
+        val spec = specLoader.specForType(pojo.getClass()).orElse(null);
+        val specialization = spec!=null
+                ? Specialization.inferFrom(spec, pojo)
+                : Specialization.UNSPECIFIED;
+
+        switch(specialization) {
+        case UNSPECIFIED:
+            return unspecified();
+        case VALUE:
+            return value(spec, pojo);
+        case SERVICE:
+            return service(spec, pojo);
+        case VIEWMODEL:
+            return viewmodel(spec, pojo);
+        case ENTITY:
+            return entity(spec, pojo);
+        // unreachable (in this context)
+        case EMPTY:
+        case PACKED:
+            throw _Exceptions.unexpectedCodeReach();
+        }
+        throw _Exceptions.unmatchedCase(specialization);
+    }
+
     // -- FACTORIES LEGACY
 
     @Deprecated
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 307e140361..d5aab332cf 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
@@ -34,6 +34,7 @@ import lombok.NonNull;
 import lombok.ToString;
 import lombok.val;
 
+@Deprecated
 @EqualsAndHashCode(of = "pojo", callSuper = false)
 @ToString(of = {"specification", "pojo"}) //ISIS-2317 make sure toString() is without side-effects
 @Getter
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
index 7b52c25002..0ca4c35c08 100644
--- 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
@@ -28,6 +28,7 @@ import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.NonNull;
 
+@Deprecated
 @EqualsAndHashCode(of = "pojo", callSuper = false)
 final class _ManagedObjectWithLazySpec
 extends _ManagedObjectWithBookmark {