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 2020/05/05 07:10:24 UTC

[isis] 02/03: ISIS-2340: allow ManagedObject to hold collection pojos

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 61260b745cb228ce92be143511856f18ca0e8030
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue May 5 09:00:18 2020 +0200

    ISIS-2340: allow ManagedObject to hold collection pojos
---
 .../isis/core/metamodel/facets/FacetedMethod.java  |  17 +---
 .../facets/actcoll/typeof/TypeOfFacet.java         |  50 ++++++++--
 .../action/ActionAnnotationFacetFactory.java       |   8 +-
 .../isis/core/metamodel/spec/ManagedObject.java    |  34 ++-----
 .../core/metamodel/spec/ObjectSpecification.java   |  54 ++++++++++-
 .../specimpl/dflt/ObjectSpecificationDefault.java  |  14 +--
 .../testspec/ObjectSpecificationStub.java          |   4 +-
 .../domainobjects/ActionResultReprRenderer.java    |   2 +-
 .../wicket/model/models/EntityCollectionModel.java | 101 +++++++++------------
 .../columns/ObjectAdapterPropertyColumn.java       |  10 +-
 10 files changed, 162 insertions(+), 132 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
index 5467ad2..cbdcd66 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
@@ -25,7 +25,6 @@ import java.util.Collections;
 import java.util.List;
 
 import org.apache.isis.applib.Identifier;
-import org.apache.isis.core.commons.internal.collections._Arrays;
 import org.apache.isis.core.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.commons.StringExtensions;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
@@ -115,10 +114,9 @@ public class FacetedMethod extends TypedHolderDefault implements IdentifiedHolde
             final Type genericParameterType = genericParameterTypes[paramNum];
 
             final FeatureType featureType =
-                    CollectionUtils
-                    .isParamCollection(parameterType, genericParameterType)
-                    ? FeatureType.ACTION_PARAMETER_COLLECTION
-                            : FeatureType.ACTION_PARAMETER_SCALAR;
+                    CollectionUtils.isParamCollection(parameterType, genericParameterType)
+                        ? FeatureType.ACTION_PARAMETER_COLLECTION
+                        : FeatureType.ACTION_PARAMETER_SCALAR;
 
             final FacetedMethodParameter fmp = new FacetedMethodParameter(featureType, declaringType, actionMethod, parameterType);
             actionParams.add(fmp);
@@ -131,13 +129,8 @@ public class FacetedMethod extends TypedHolderDefault implements IdentifiedHolde
                 FacetUtil.addFacet(semanticsFacet);
 
                 TypeOfFacet typeOfFacet = TypeOfFacet.Util
-                        .inferFromGenericParamType(fmp, parameterType, genericParameterType);
-
-                if(typeOfFacet == null ) {
-                    if (_Arrays.isArrayType(parameterType)) {
-                        typeOfFacet = TypeOfFacet.Util.inferFromArrayType(fmp, parameterType);
-                    }
-                }
+                        .inferFromParameterType(fmp, parameterType, genericParameterType);
+                
 
                 // copy over (corresponds to similar code for OneToManyAssociation in FacetMethodsBuilder).
                 if(typeOfFacet != null ) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
index 7e777b9..72c457f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
@@ -25,12 +25,13 @@ import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 
-import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.core.commons.internal.collections._Arrays;
 import org.apache.isis.core.commons.internal.collections._Collections;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.SingleClassValueFacet;
 
+import lombok.val;
+
 /**
  * The type of the collection or the action.
  *
@@ -43,9 +44,42 @@ public interface TypeOfFacet extends SingleClassValueFacet {
 
     public static class Util {
         private Util(){}
+        
+        public static TypeOfFacet inferFromParameterType(
+                final FacetHolder holder,
+                final Class<?> parameterType,
+                final Type genericParameterType) {
+        
+            TypeOfFacet typeOfFacet = inferFromGenericParamType(holder, parameterType, genericParameterType);
+            
+            if(typeOfFacet == null ) {
+                if (_Arrays.isArrayType(parameterType)) {
+                    typeOfFacet = inferFromArrayType(holder, parameterType);
+                }
+            }
+            
+            return typeOfFacet;
+        }
+        
+        public static TypeOfFacet inferFromMethodReturnType(
+                final FacetHolder holder,
+                final Class<?> methodOwner,
+                final Method method) {
+            
+            // infer from return type
+            val returnType = method.getReturnType();
+            TypeOfFacet typeOfFacet = inferFromArrayType(holder, returnType);
+
+            // infer from generic return type
+            if(typeOfFacet == null) {
+                typeOfFacet = inferFromGenericReturnType(methodOwner, method, holder);
+            }
+            
+            return typeOfFacet;
+        }
+        
 
-        @Programmatic
-        public static TypeOfFacet inferFromGenericReturnType(
+        private static TypeOfFacet inferFromGenericReturnType(
                 final Class<?> cls,
                 final Method method,
                 final FacetHolder holder) {
@@ -100,19 +134,17 @@ public interface TypeOfFacet extends SingleClassValueFacet {
             return null;
         }
 
-        @Programmatic
-        public static TypeOfFacet inferFromArrayType(
+        private static TypeOfFacet inferFromArrayType(
                 final FacetHolder holder,
                 final Class<?> type) {
 
             final Class<?> elementType = _Arrays.inferComponentTypeIfAny(type);
             return elementType != null
                     ? new TypeOfFacetInferredFromArray(elementType, holder)
-                            : null;
+                    : null;
         }
 
-        @Programmatic
-        public static TypeOfFacet inferFromGenericParamType(
+        private static TypeOfFacet inferFromGenericParamType(
                 final FacetHolder holder,
                 final Class<?> parameterType,
                 final Type genericParameterType) {
@@ -120,7 +152,7 @@ public interface TypeOfFacet extends SingleClassValueFacet {
             final Class<?> elementType = _Collections.inferElementTypeIfAny(parameterType, genericParameterType);
             return elementType != null
                     ? new TypeOfFacetInferredFromGenerics(elementType, holder)
-                            : null;
+                    : null;
         }
     }
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
index 9bcc4d8..c987208 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
@@ -248,16 +248,10 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract {
                 .map(typeOf -> new TypeOfFacetForActionAnnotation(typeOf, facetedMethod))
                 .orElse(null);
 
-        // infer from return type
-        if(typeOfFacet == null) {
-            val returnType = method.getReturnType();
-            typeOfFacet = TypeOfFacet.Util.inferFromArrayType(facetedMethod, returnType);
-        }
-
         // infer from generic return type
         if(typeOfFacet == null) {
             val cls = processMethodContext.getCls();
-            typeOfFacet = TypeOfFacet.Util.inferFromGenericReturnType(cls, method, facetedMethod);
+            typeOfFacet = TypeOfFacet.Util.inferFromMethodReturnType(facetedMethod, cls, method);
         }
 
         super.addFacet(typeOfFacet);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java
index 31603f6..a8bc77a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ManagedObject.java
@@ -279,7 +279,7 @@ public interface ManagedObject {
 
         private static String collectionTitleString(ManagedObject managedObject, final CollectionFacet facet) {
             final int size = facet.size(managedObject);
-            final ObjectSpecification elementSpecification = managedObject.getElementSpecification();
+            final ObjectSpecification elementSpecification = managedObject.getElementSpecification().orElse(null);
             if (elementSpecification == null || elementSpecification.getFullIdentifier().equals(Object.class.getName())) {
                 switch (size) {
                 case -1:
@@ -315,11 +315,8 @@ public interface ManagedObject {
 
     /**
      * Used only for (standalone or parented) collections.
-     * @deprecated use {@link ObjectSpecification#getElementSpecification()} instead, 
-     * (proposed for removal, to keep the API slim)
      */
-    @Deprecated
-    default public ObjectSpecification getElementSpecification() {
+    default public Optional<ObjectSpecification> getElementSpecification() {
         return getSpecification().getElementSpecification();
     }
 
@@ -330,8 +327,6 @@ public interface ManagedObject {
      * graphically.
      * <p>
      * May return <code>null</code> if no icon is specified.
-     * @deprecated use {@link ObjectSpecification#getIconName(ManagedObject))} instead, 
-     * (proposed for removal, to keep the API slim)
      */
     default public String getIconName() {
         return getSpecification().getIconName(this);
@@ -342,29 +337,18 @@ public interface ManagedObject {
     /**
      * Optimized for cases, when the pojo's specification is already available.
      * @param specification
-     * @param pojo
+     * @param pojo - might also be a collection of pojos
      * @return
      */
-    public static ManagedObject of(ObjectSpecification specification, Object pojo) {
-        // can do this check only when the pojo is not null, otherwise is always considered valid
-        if(pojo!=null) {
-            val expectedType = specification.getCorrespondingClass();
-            val actualType = pojo.getClass();
-            
-            if(!expectedType.isAssignableFrom(actualType)) {
-                if(!ClassExtensions.equalsWhenBoxing(expectedType, actualType)) {
-                    throw _Exceptions.illegalArgument(
-                            "Pojo not compatible with ObjectSpecification, " +
-                            "objectSpec.correspondingClass = %s, " +
-                            "pojo.getClass() = %s, " +
-                            "pojo.toString() = %s",
-                            specification.getCorrespondingClass(), pojo.getClass(), pojo.toString());    
-                }
-            }    
-        }
+    public static ManagedObject of(@NonNull ObjectSpecification specification, @Nullable Object pojo) {
+        
+        specification.assertPojoCompatible(pojo);
+        
         return new SimpleManagedObject(specification, pojo);
     }
     
+    
+    
     /**
      * Optimized for cases, when the pojo's specification and rootOid are already available.
      */
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 2c4993a..ef3f7b8 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
@@ -22,13 +22,20 @@ package org.apache.isis.core.metamodel.spec;
 import java.lang.reflect.Array;
 import java.lang.reflect.Modifier;
 import java.util.Comparator;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.stream.Stream;
 
+import javax.annotation.Nullable;
+
 import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.services.metamodel.BeanSort;
 import org.apache.isis.core.commons.exceptions.IsisException;
+import org.apache.isis.core.commons.internal.base._NullSafe;
 import org.apache.isis.core.commons.internal.collections._Streams;
-import org.apache.isis.applib.services.metamodel.BeanSort;
+import org.apache.isis.core.commons.internal.exceptions._Exceptions;
+import org.apache.isis.core.commons.internal.functions._Predicates;
+import org.apache.isis.core.metamodel.commons.ClassExtensions;
 import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.consent.InteractionResult;
@@ -215,10 +222,10 @@ public interface ObjectSpecification extends Specification, ObjectActionContaine
     boolean isAbstract();
 
     /**
-     * 
+     * @return optionally the element type spec based on presence of the TypeOfFacet
      * @since 2.0
      */
-    ObjectSpecification getElementSpecification();
+    Optional<ObjectSpecification> getElementSpecification();
 
     /**
      * 
@@ -442,8 +449,47 @@ public interface ObjectSpecification extends Specification, ObjectActionContaine
     default boolean isIdentifiable() {
         return isManagedBean() || isViewModel() || isEntity();
     }
-
     
+    // -- TYPE COMPATIBILITY UTILITIES
+    
+    default public void assertPojoCompatible(@Nullable Object pojo) {
+        if(!isPojoCompatible(pojo)) {
+            Objects.requireNonNull(pojo);
+            val expectedType = getCorrespondingClass();
+            throw _Exceptions.illegalArgument(
+                    "Pojo not compatible with ObjectSpecification, " +
+                    "objectSpec.correspondingClass = %s, " +
+                    "pojo.getClass() = %s, " +
+                    "pojo.toString() = %s",
+                    expectedType, pojo.getClass(), pojo.toString());
+        }
+    }
+    
+    default public boolean isPojoCompatible(@Nullable Object pojo) {
+        
+        // can do this check only when the pojo is not null, otherwise is always considered valid
+        if(pojo==null) {
+            return true;
+        }
+        
+        val expectedType = getCorrespondingClass();
+        val actualType = pojo.getClass();
+        
+        if(expectedType.isAssignableFrom(actualType)
+                || ClassExtensions.equalsWhenBoxing(expectedType, actualType)) {
+            return true;
+        }
+
+        if(getElementSpecification().isPresent()) {
+            
+            val elementSpec = getElementSpecification().get();
 
+            return _NullSafe.streamAutodetect(pojo)
+            .anyMatch(_Predicates.not(elementSpec::isPojoCompatible));
+        }
+        
+        return true;
+    }
+    
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index d423a7a..d985165 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -71,8 +71,6 @@ import org.apache.isis.core.metamodel.specloader.specimpl.ObjectSpecificationAbs
 import org.apache.isis.core.metamodel.specloader.specimpl.OneToManyAssociationDefault;
 import org.apache.isis.core.metamodel.specloader.specimpl.OneToOneAssociationDefault;
 
-import static org.apache.isis.core.commons.internal.base._With.mapIfPresentElse;
-
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
@@ -428,18 +426,16 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
 
     // -- ELEMENT SPECIFICATION
 
-    private final _Lazy<ObjectSpecification> elementSpecification = _Lazy.of(this::lookupElementSpecification); 
+    private final _Lazy<Optional<ObjectSpecification>> elementSpecification = _Lazy.of(this::lookupElementSpecification); 
 
     @Override
-    public ObjectSpecification getElementSpecification() {
+    public Optional<ObjectSpecification> getElementSpecification() {
         return elementSpecification.get();
     }
 
-    private ObjectSpecification lookupElementSpecification() {
-        return mapIfPresentElse(
-                getFacet(TypeOfFacet.class), 
-                typeOfFacet -> ElementSpecificationProvider.of(typeOfFacet).getElementType(), 
-                null);
+    private Optional<ObjectSpecification> lookupElementSpecification() {
+        return Optional.ofNullable(getFacet(TypeOfFacet.class))
+                .map(typeOfFacet -> ElementSpecificationProvider.of(typeOfFacet).getElementType());
     }
 
     // --
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
index a4b984e..be0e161 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
@@ -331,8 +331,8 @@ public class ObjectSpecificationStub extends FacetHolderImpl implements ObjectSp
     }
 
     @Override
-    public ObjectSpecification getElementSpecification() {
-        return elementSpecification;
+    public Optional<ObjectSpecification> getElementSpecification() {
+        return Optional.ofNullable(elementSpecification);
     }
 
     @Override
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
index 481ab33..917eb7a 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
@@ -143,7 +143,7 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
                     new ListReprRenderer(resourceContext, null, representation).withElementRel(Rel.ELEMENT);
             listReprRenderer.with(collectionAdapters)
             .withReturnType(action.getReturnType())
-            .withElementType(returnedAdapter.getElementSpecification());
+            .withElementType(returnedAdapter.getElementSpecification().orElse(null));
 
             return listReprRenderer;
 
diff --git a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
index a9f50f6..d8a3318 100644
--- a/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
+++ b/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
@@ -59,8 +59,8 @@ import org.apache.isis.viewer.wicket.model.models.Util.LowestCommonSuperclassFin
 import static org.apache.isis.core.commons.internal.base._NullSafe.stream;
 
 /**
- * Model representing a collection of entities, either {@link Type#STANDALONE
- * standalone} (eg result of invoking an action) or {@link Type#PARENTED
+ * Model representing a collection of entities, either {@link Variant#STANDALONE
+ * standalone} (eg result of invoking an action) or {@link Variant#PARENTED
  * parented} (contents of the collection of an entity).
  *
  * <p>
@@ -75,10 +75,22 @@ implements LinksProvider, UiHintContainer {
     private static final int PAGE_SIZE_DEFAULT_FOR_PARENTED = 12;
     private static final int PAGE_SIZE_DEFAULT_FOR_STANDALONE = 25;
 
-    // -- TOP LEVEL FACTORIES
+    // -- FACTORIES
 
-    public static EntityCollectionModel createParented(EntityModel modelWithCollectionLayoutMetadata) {
-        return parentedOf(modelWithCollectionLayoutMetadata);
+    public static EntityCollectionModel createParented(EntityModel entityModel) {
+
+        final OneToManyAssociation collection = collectionFor(entityModel);
+        final Class<?> typeOf = forName(collection.getSpecification());
+        final int pageSize = pageSize(collection.getFacet(PagedFacet.class), PAGE_SIZE_DEFAULT_FOR_PARENTED);
+        final SortedByFacet sortedByFacet = collection.getFacet(SortedByFacet.class);
+
+        final EntityCollectionModel colModel = new EntityCollectionModel(
+                entityModel.getCommonContext(), Variant.PARENTED, entityModel, typeOf, pageSize);
+
+        colModel.collectionMemento = new CollectionMemento(collection);
+        colModel.sortedBy = sortedByFacet != null ? sortedByFacet.value(): null;
+        
+        return colModel;
     }
 
     public static EntityCollectionModel createStandalone(
@@ -102,7 +114,7 @@ implements LinksProvider, UiHintContainer {
 
         final ObjectSpecification elementSpec = lowestCommonSuperclassFinder.getLowestCommonSuperclass()
                 .map(specificationLoader::loadSpecification)
-                .orElse(collectionAsAdapter.getSpecification().getElementSpecification());
+                .orElseGet(()->collectionAsAdapter.getSpecification().getElementSpecification().orElse(null));
 
         final Class<?> elementType;
         int pageSize = PAGE_SIZE_DEFAULT_FOR_STANDALONE;
@@ -113,47 +125,18 @@ implements LinksProvider, UiHintContainer {
             elementType = Object.class;
         }
 
-        return standaloneOf(model.getCommonContext(), elementType, mementoList, pageSize);
-    }
-
-    // -- LOW LEVEL FACTORIES (PRIVATE)
-
-    private static EntityCollectionModel parentedOf(EntityModel entityModel) {
-
-        final Type type = Type.PARENTED;
-
-        final OneToManyAssociation collection = collectionFor(entityModel);
-        final Class<?> typeOf = forName(collection.getSpecification());
-        final int pageSize = pageSize(collection.getFacet(PagedFacet.class), PAGE_SIZE_DEFAULT_FOR_PARENTED);
-        final SortedByFacet sortedByFacet = collection.getFacet(SortedByFacet.class);
-
-        final EntityCollectionModel colModel = new EntityCollectionModel(
-                entityModel.getCommonContext(), type, entityModel, typeOf, pageSize);
-
-        colModel.collectionMemento = new CollectionMemento(collection);
-        colModel.sortedBy = sortedByFacet != null ? sortedByFacet.value(): null;
-        
-        return colModel;
-    }
-
-    private static EntityCollectionModel standaloneOf(
-            IsisWebAppCommonContext commonContext, 
-            Class<?> typeOf, 
-            List<ObjectMemento> mementoList, 
-            int pageSize) {
-
-        final Type type = Type.STANDALONE;
         final EntityModel entityModel = null;
 
-        final EntityCollectionModel colModel = new EntityCollectionModel(commonContext, type, entityModel, typeOf, pageSize);
+        final EntityCollectionModel colModel = new EntityCollectionModel(
+                model.getCommonContext(), Variant.STANDALONE, entityModel, elementType, pageSize);
         colModel.mementoList = mementoList;
         return colModel;
-
+        
     }
 
     // -- VARIANTS
 
-    public enum Type {
+    public enum Variant {
         /**
          * A simple list of object mementos, eg the result of invoking an action
          *
@@ -295,7 +278,7 @@ implements LinksProvider, UiHintContainer {
      * that generated this {@link EntityCollectionModel}.
      *
      * <p>
-     * Populated only for {@link Type#STANDALONE standalone} collections.
+     * Populated only for {@link Variant#STANDALONE standalone} collections.
      *
      * @see #setActionHint(ActionModel)
      */
@@ -303,7 +286,7 @@ implements LinksProvider, UiHintContainer {
         return actionModelHint;
     }
     /**
-     * Called only for {@link Type#STANDALONE standalone} collections.
+     * Called only for {@link Variant#STANDALONE standalone} collections.
      *
      * @see #getActionModelHint()
      */
@@ -311,9 +294,9 @@ implements LinksProvider, UiHintContainer {
         this.actionModelHint = actionModelHint;
     }
 
-    private final Type type;
+    private final Variant type;
 
-    public Type getType() {
+    public Variant getType() {
         return type;
     }
 
@@ -321,23 +304,23 @@ implements LinksProvider, UiHintContainer {
     private transient ObjectSpecification typeOfSpec;
 
     /**
-     * Populated only if {@link Type#STANDALONE}.
+     * Populated only if {@link Variant#STANDALONE}.
      */
     private List<ObjectMemento> mementoList;
 
     /**
-     * Populated only if {@link Type#STANDALONE}.
+     * Populated only if {@link Variant#STANDALONE}.
      */
     private Map<String, ObjectMemento> toggledMementos;
 
     /**
-     * Populated only if {@link Type#PARENTED}.
+     * Populated only if {@link Variant#PARENTED}.
      */
     private final EntityModel entityModel;
 
 
     /**
-     * Populated only if {@link Type#PARENTED}.
+     * Populated only if {@link Variant#PARENTED}.
      */
     private CollectionMemento collectionMemento;
 
@@ -349,18 +332,18 @@ implements LinksProvider, UiHintContainer {
     private List<LinkAndLabel> linkAndLabels = _Lists.newArrayList();
 
     /**
-     * Optionally populated only if {@link Type#PARENTED}.
+     * Optionally populated only if {@link Variant#PARENTED}.
      */
     private Class<? extends Comparator<?>> sortedBy;
 
     /**
-     * Optionally populated, only if {@link Type#STANDALONE} (ie called from an action).
+     * Optionally populated, only if {@link Variant#STANDALONE} (ie called from an action).
      */
     private ActionModel actionModelHint;
 
     private EntityCollectionModel(
             IsisWebAppCommonContext commonContext,
-            Type type, 
+            Variant type, 
             EntityModel entityModel, 
             Class<?> typeOf, 
             int pageSize) {
@@ -401,11 +384,11 @@ implements LinksProvider, UiHintContainer {
     }
 
     public boolean isParented() {
-        return type == Type.PARENTED;
+        return type == Variant.PARENTED;
     }
 
     public boolean isStandalone() {
-        return type == Type.STANDALONE;
+        return type == Variant.STANDALONE;
     }
 
     public int getPageSize() {
@@ -429,7 +412,7 @@ implements LinksProvider, UiHintContainer {
     }
 
     /**
-     * Populated only if {@link Type#PARENTED}.
+     * Populated only if {@link Variant#PARENTED}.
      */
     public CollectionLayoutData getLayoutData() {
         return entityModel != null
@@ -465,21 +448,21 @@ implements LinksProvider, UiHintContainer {
     }
 
     /**
-     * Populated only if {@link Type#PARENTED}.
+     * Populated only if {@link Variant#PARENTED}.
      */
     public EntityModel getEntityModel() {
         return entityModel;
     }
 
     /**
-     * Populated only if {@link Type#PARENTED}.
+     * Populated only if {@link Variant#PARENTED}.
      */
     public ObjectMemento getParentObjectAdapterMemento() {
         return entityModel != null? entityModel.getObjectAdapterMemento(): null;
     }
 
     /**
-     * Populated only if {@link Type#PARENTED}.
+     * Populated only if {@link Variant#PARENTED}.
      */
     public CollectionMemento getCollectionMemento() {
         return collectionMemento;
@@ -523,8 +506,10 @@ implements LinksProvider, UiHintContainer {
     }
 
     public EntityCollectionModel asDummy() {
-        return standaloneOf(
-                super.getCommonContext(), typeOf, Collections.<ObjectMemento>emptyList(), pageSize);
+        final EntityCollectionModel dummy = new EntityCollectionModel(
+                super.getCommonContext(), Variant.STANDALONE, null, typeOf, pageSize);
+        dummy.mementoList = Collections.<ObjectMemento>emptyList();
+        return dummy;
     }
 
     // //////////////////////////////////////
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
index 4f26d37..69db3d5 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterPropertyColumn.java
@@ -28,6 +28,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.isis.core.commons.internal.base._Strings;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
 import org.apache.isis.viewer.wicket.model.mementos.PropertyMemento;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
@@ -38,7 +39,6 @@ import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanel;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
 import org.apache.isis.viewer.wicket.ui.util.Tooltips;
-import org.apache.isis.core.webapp.context.IsisWebAppCommonContext;
 
 import lombok.val;
 
@@ -55,7 +55,7 @@ public final class ObjectAdapterPropertyColumn extends ColumnAbstract<ManagedObj
 
     private static final long serialVersionUID = 1L;
 
-    private final EntityCollectionModel.Type type;
+    private final EntityCollectionModel.Variant collectionVariant;
     private final String propertyExpression;
     private final boolean escaped;
     private final String parentTypeName;
@@ -63,7 +63,7 @@ public final class ObjectAdapterPropertyColumn extends ColumnAbstract<ManagedObj
 
     public ObjectAdapterPropertyColumn(
             IsisWebAppCommonContext commonContext, 
-            EntityCollectionModel.Type type,
+            EntityCollectionModel.Variant collectionVariant,
             IModel<String> columnNameModel,
             String sortProperty,
             String propertyName,
@@ -72,7 +72,7 @@ public final class ObjectAdapterPropertyColumn extends ColumnAbstract<ManagedObj
             String describedAs) {
         
         super(commonContext, columnNameModel, sortProperty);
-        this.type = type;
+        this.collectionVariant = collectionVariant;
         this.propertyExpression = propertyName;
         this.escaped = escaped;
         this.parentTypeName = parentTypeName;
@@ -114,7 +114,7 @@ public final class ObjectAdapterPropertyColumn extends ColumnAbstract<ManagedObj
         final OneToOneAssociation property = (OneToOneAssociation) adapter.getSpecification().getAssociationElseFail(propertyExpression);
         final PropertyMemento pm = new PropertyMemento(property);
 
-        final ScalarModel scalarModel = entityModel.getPropertyModel(pm, EntityModel.Mode.VIEW, type.renderingHint());
+        final ScalarModel scalarModel = entityModel.getPropertyModel(pm, EntityModel.Mode.VIEW, collectionVariant.renderingHint());
 
         final ComponentFactory componentFactory = findComponentFactory(ComponentType.SCALAR_NAME_AND_VALUE, scalarModel);
         return componentFactory.createComponent(id, scalarModel);