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 2018/09/28 18:29:05 UTC

[isis] branch v2 updated: ISIS-1976: rework CollectionFacet API such that methods invoked on non-scalar types preserves their generic type nature

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

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


The following commit(s) were added to refs/heads/v2 by this push:
     new a445986  ISIS-1976: rework CollectionFacet API such that methods invoked on non-scalar types preserves their generic type nature
a445986 is described below

commit a445986c9bb3c8881c1960ef7edef6c348986e26
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Sep 28 20:28:27 2018 +0200

    ISIS-1976: rework CollectionFacet API such that methods invoked on
    non-scalar types preserves their generic type nature
    
    Task-Url: https://issues.apache.org/jira/browse/ISIS-1976
---
 .../isis/core/metamodel/adapter/ObjectAdapter.java |  68 ++++-----
 .../core/metamodel/facets/CollectionUtils.java     |  14 +-
 ...ctionInvocationFacetForDomainEventAbstract.java |  12 +-
 .../collections/CollectionFacetAbstract.java       |  36 +----
 .../javautilcollection/JavaArrayFacet.java         |  65 ++++----
 .../javautilcollection/JavaCollectionFacet.java    |  50 +++---
 .../facets/collections/modify/CollectionFacet.java |  55 +++----
 .../autocomplete/AutoCompleteFacetAbstract.java    |   4 +-
 .../impl/ObjectValidPropertiesFacetImpl.java       |   1 -
 ...arameterChoicesFacetFromParentedCollection.java |   2 +-
 .../isis/core/metamodel/spec/FreeStandingList.java |  27 +++-
 .../isis/core/metamodel/spec/ManagedObject.java    |  92 ++++++++++-
 .../CollectionFacetOnStandaloneList.java           |  44 +++---
 .../isis/core/runtime/snapshot/XmlSnapshot.java    |  22 +--
 .../system/persistence/PersistenceSession4.java    |   6 +-
 .../adapterfactory/pojo/PojoAdapterTest.java       |   2 +-
 .../transaction/PojoAdapterBuilder.java            |  14 +-
 .../runtime/system/ObjectMemberAbstractTest.java   |  21 ++-
 .../system/persistence/PersistenceSession5.java    |   6 +-
 .../adapterfactory/pojo/PojoAdapterTest.java       |   9 +-
 .../transaction/PojoAdapterBuilder.java            |  11 +-
 .../apache/isis/core/runtime/memento/Memento.java  |  12 +-
 .../runtime/persistence/adapter/PojoAdapter.java   | 169 ++++++++++-----------
 .../ObjectAdapterContext_Factories.java            |   2 +-
 .../ObjectAdapterContext_MementoSupport.java       |  24 +--
 .../domainobjects/ActionResultReprRenderer.java    |   6 +-
 .../ObjectCollectionReprRenderer.java              |  10 +-
 ...entNegotiationServiceForRestfulObjectsV1_0.java |   3 +-
 .../ContentNegotiationServiceOrgApacheIsisV1.java  |  22 +--
 29 files changed, 444 insertions(+), 365 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
index e28052e..f38375d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/ObjectAdapter.java
@@ -23,6 +23,7 @@ import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.List;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.annotation.Where;
@@ -34,13 +35,11 @@ import org.apache.isis.core.commons.lang.MethodExtensions;
 import org.apache.isis.core.commons.lang.MethodUtil;
 import org.apache.isis.core.metamodel.adapter.oid.Oid;
 import org.apache.isis.core.metamodel.adapter.oid.ParentedOid;
-import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.core.metamodel.adapter.version.Version;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.consent.InteractionResult;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
-import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
 import org.apache.isis.core.metamodel.interactions.InteractionUtils;
 import org.apache.isis.core.metamodel.interactions.ObjectVisibilityContext;
 import org.apache.isis.core.metamodel.interactions.VisibilityContext;
@@ -70,23 +69,23 @@ public interface ObjectAdapter extends ManagedObject {
 //    @Override
 //    Object getObject();
     
-    /**
-     * Returns the title to display this object with, usually obtained from
-     * the wrapped {@link #getObject() domain object}.
-     *
-     * @deprecated - use {@link #titleString(ObjectAdapter)}
-     */
-    @Deprecated
-    String titleString();
-
-    /**
-     * Returns the title to display this object with, rendered within the context
-     * of some other adapter.
-     *
-     * <p>
-     * @see TitleFacet#title(ObjectAdapter, ObjectAdapter)
-     */
-    String titleString(ObjectAdapter contextAdapter);
+//    /**
+//     * Returns the title to display this object with, usually obtained from
+//     * the wrapped {@link #getObject() domain object}.
+//     *
+//     * @deprecated - use {@link #titleString(ObjectAdapter)}
+//     */
+//    @Deprecated
+//    String titleString();
+//
+//    /**
+//     * Returns the title to display this object with, rendered within the context
+//     * of some other adapter.
+//     *
+//     * <p>
+//     * @see TitleFacet#title(ObjectAdapter, ObjectAdapter)
+//     */
+//    String titleString(ObjectAdapter contextAdapter);
 
     /**
      * Return an {@link Instance} of the specified {@link Specification} with
@@ -288,8 +287,8 @@ public interface ObjectAdapter extends ManagedObject {
                 final ObjectAdapter collectionAdapter,
                 final InteractionInitiatedBy interactionInitiatedBy) {
 
-            final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collectionAdapter);
-            Iterable<ObjectAdapter> objectAdapters = facet.iterable(collectionAdapter);
+            final Stream<ObjectAdapter> objectAdapters = 
+                    CollectionFacet.Utils.streamAdapters(collectionAdapter);
 
             return visibleAdapters(objectAdapters, interactionInitiatedBy);
         }
@@ -298,6 +297,7 @@ public interface ObjectAdapter extends ManagedObject {
          * as per {@link #visibleAdapters(ObjectAdapter, InteractionInitiatedBy)}.
          *  @param objectAdapters - iterable over the respective adapters of a collection (as returned by a getter of a collection, or of an autoCompleteNXxx() or choicesNXxx() method, etc
          * @param interactionInitiatedBy
+         * @deprecated use stream variant instead
          */
         public static List<ObjectAdapter> visibleAdapters(
                 final Iterable<ObjectAdapter> objectAdapters,
@@ -312,6 +312,16 @@ public interface ObjectAdapter extends ManagedObject {
             }
             return adapters;
         }
+        
+        public static List<ObjectAdapter> visibleAdapters(
+                final Stream<ObjectAdapter> objectAdapters,
+                final InteractionInitiatedBy interactionInitiatedBy) {
+            
+            return objectAdapters
+                .filter(adapter->isVisible(adapter, interactionInitiatedBy))
+                .collect(Collectors.toList());
+        }
+        
 
         /**
          * @param adapter - an adapter around the domain object whose visibility is being checked
@@ -479,21 +489,5 @@ public interface ObjectAdapter extends ManagedObject {
 
     }
 
-    /**
-     * 
-     * @param newOid
-     * @return a copy of this adapter, having a new RootOid 
-     * @since 2.0.0-M2
-     */
-    ObjectAdapter withOid(RootOid newOid);
-
-    /**
-     * 
-     * @param newPojo
-     * @return a copy of this adapter, having a new Pojo 
-     * @since 2.0.0-M2
-     */
-    ObjectAdapter withPojo(Object newPojo);
-
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
index 13f89c1..4b73390 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
@@ -34,6 +34,7 @@ import java.util.TreeSet;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.function.Function;
+import java.util.stream.Stream;
 
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._With;
@@ -53,12 +54,13 @@ public final class CollectionUtils {
     public static Object[] getCollectionAsObjectArray(final Object option, final ObjectSpecification spec, final ObjectAdapterProvider adapterProvider) {
         final ObjectAdapter collection = adapterProvider.adapterFor(option);
         final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collection);
-        final Object[] optionArray = new Object[facet.size(collection)];
-        int j = 0;
-        for (final ObjectAdapter nextElement : facet.iterable(collection)) {
-            optionArray[j++] = nextElement != null? nextElement.getObject(): null;
-        }
-        return optionArray;
+        
+        final Stream<ObjectAdapter> objectAdapters = 
+                CollectionFacet.Utils.streamAdapters(collection);
+        
+        return objectAdapters
+            .map(nextElement->nextElement != null? nextElement.getObject(): null)
+            .collect(_Arrays.toArray(Object.class, facet.size(collection)));
     }
 
     private final static Map<Class<?>, Function<Iterable<Object>, Object>> factoriesByType = _With.hashMap(
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index c89e82a..01c7cca 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -493,19 +493,19 @@ implements ImperativeFacet {
         final Object result = resultAdapter.getObject();
 
         if(result instanceof Collection || result.getClass().isArray()) {
-            final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(resultAdapter);
-
-            final Iterable<ObjectAdapter> adapterList = facet.iterable(resultAdapter);
+            
+            final Stream<ObjectAdapter> adapters = CollectionFacet.Utils.streamAdapters(resultAdapter);
+            
             final List<ObjectAdapter> visibleAdapters =
-                    ObjectAdapter.Util.visibleAdapters(
-                            adapterList,
-                            interactionInitiatedBy);
+                    ObjectAdapter.Util.visibleAdapters(adapters, interactionInitiatedBy);
+            
             final Object visibleObjects =
                     CollectionUtils.copyOf(
                             stream(visibleAdapters)
                             .map(ObjectAdapter.Functions.getObject())
                             .collect(Collectors.toList()),
                             method.getReturnType());
+            
             if (visibleObjects != null) {
                 return getObjectAdapterProvider().adapterFor(visibleObjects);
             }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacetAbstract.java
index 06cb9ce..4f3dbda 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/CollectionFacetAbstract.java
@@ -19,46 +19,26 @@
 
 package org.apache.isis.core.metamodel.facets.collections;
 
-import java.util.Collection;
-import java.util.Iterator;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
 
 public abstract class CollectionFacetAbstract extends FacetAbstract implements CollectionFacet {
 
     public CollectionFacetAbstract(final FacetHolder holder) {
         super(CollectionFacet.class, holder, Derivation.NOT_DERIVED);
     }
-
-    @Override
-    public final boolean contains(final ObjectAdapter collectionAdapter, final ObjectAdapter candidateObjectAdapter) {
-        final Collection<ObjectAdapter> collection = collection(collectionAdapter);
-        return collection.contains(candidateObjectAdapter);
-    }
-
-    @Override
-    public final Iterator<ObjectAdapter> iterator(final ObjectAdapter collectionAdapter) {
-        final Collection<ObjectAdapter> collection = collection(collectionAdapter);
-        return collection.iterator();
-    }
-
-    @Override
-    public Iterable<ObjectAdapter> iterable(final ObjectAdapter collectionAdapter) {
-        return new Iterable<ObjectAdapter>() {
-            @Override
-            public Iterator<ObjectAdapter> iterator() {
-                return CollectionFacetAbstract.this.iterator(collectionAdapter);
-            }
-        };
-    }
-
+    
     @Override
     public final TypeOfFacet getTypeOfFacet() {
         return getFacetHolder().getFacet(TypeOfFacet.class);
     }
-
+    
+    @Override
+    public boolean contains(ManagedObject collectionAdapter, ManagedObject element) {
+        return stream(collectionAdapter).anyMatch(x->x.equals(element));
+    }
+    
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaArrayFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaArrayFacet.java
index a18ad9c..a99e414 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaArrayFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaArrayFacet.java
@@ -31,6 +31,8 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.collections.CollectionFacetAbstract;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 public class JavaArrayFacet extends CollectionFacetAbstract {
 
@@ -41,59 +43,44 @@ public class JavaArrayFacet extends CollectionFacetAbstract {
         this.adapterProvider = adapterProvider;
     }
 
-    /**
-     * Expected to be called with a {@link ObjectAdapter} wrapping an array.
-     */
     @Override
-    public ObjectAdapter init(
-            final ObjectAdapter arrayAdapter, 
-            final Stream<ObjectAdapter> initData, 
-            final int elementCount) {
+    public <T extends ManagedObject> Object populatePojo(
+            Object emptyCollectionPojo, 
+            ObjectSpecification collectionSpec,
+            Stream<T> initData, 
+            int elementCount) {
+        
+        //final Class<?> correspondingClass = collectionSpec.getCorrespondingClass();
         
         final Object[] array = initData
-            .map(ObjectAdapter::getObject)
-            .collect(toArray(Object.class, elementCount));
-        return arrayAdapter.withPojo(array);  
-    }
-
-    /**
-     * Expected to be called with a {@link ObjectAdapter} wrapping an array.
-     */
-    @Override
-    public Collection<ObjectAdapter> collection(final ObjectAdapter arrayAdapter) {
-        final Object[] array = pojoArray(arrayAdapter);
-        if(isEmpty(array)) {
-            return Collections.emptyList();
-        }
-        final ArrayList<ObjectAdapter> objectCollection = new ArrayList<ObjectAdapter>(array.length);
-        for (final Object element : array) {
-            final ObjectAdapter elementAdapter = getObjectAdapterProvider().adapterFor(element);
-            objectCollection.add(elementAdapter);
-        }
-        return objectCollection;
+                .map(ManagedObject::getPojo)
+                //.collect(toArray(correspondingClass.getComponentType(), elementCount));
+                .collect(toArray(Object.class, elementCount));
+        return array;
     }
 
-    /**
-     * Expected to be called with a {@link ObjectAdapter} wrapping an array.
-     */
     @Override
-    public ObjectAdapter firstElement(final ObjectAdapter arrayAdapter) {
+    public <T extends ManagedObject> Stream<T> stream(T arrayAdapter) {
         final Object[] array = pojoArray(arrayAdapter);
         if(isEmpty(array)) {
-            return null;
+            return Stream.of();
         }
-        return array.length > 0 ? getObjectAdapterProvider().adapterFor(array[0]) : null;
+        return Stream.of(array)
+                .map(getObjectAdapterProvider()::adapterFor)
+                .map(x->(T)x);
     }
-
+    
     /**
      * Expected to be called with a {@link ObjectAdapter} wrapping an array.
      */
     @Override
-    public int size(final ObjectAdapter arrayAdapter) {
+    public int size(final ManagedObject arrayAdapter) {
         return pojoArray(arrayAdapter).length;
     }
 
-    private Object[] pojoArray(final ObjectAdapter arrayAdapter) {
+    // -- HELPER
+    
+    private Object[] pojoArray(final ManagedObject arrayAdapter) {
         return (Object[]) arrayAdapter.getObject();
     }
 
@@ -105,4 +92,10 @@ public class JavaArrayFacet extends CollectionFacetAbstract {
         return adapterProvider;
     }
 
+
+
+
+
+
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaCollectionFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaCollectionFacet.java
index 499984b..3fbf693 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaCollectionFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/JavaCollectionFacet.java
@@ -20,14 +20,16 @@
 package org.apache.isis.core.metamodel.facets.collections.javautilcollection;
 
 import java.util.Collection;
-import java.util.Iterator;
 import java.util.stream.Stream;
 
+import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapterProvider;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.collections.CollectionFacetAbstract;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 public class JavaCollectionFacet extends CollectionFacetAbstract {
 
@@ -39,42 +41,46 @@ public class JavaCollectionFacet extends CollectionFacetAbstract {
     }
     
     @Override
-    public ObjectAdapter init(
-            final ObjectAdapter collection, 
-            final Stream<ObjectAdapter> initData,
-            final int elementCount) {
+    public <T extends ManagedObject> Object populatePojo(
+            Object emptyCollectionPojo, 
+            ObjectSpecification collectionSpec,
+            Stream<T> initData, 
+            int elementCount) {
         
-        final Collection<? super Object> pojoCollection = pojoCollection(collection);
+        final Collection<? super Object> pojoCollection = _Casts.uncheckedCast(emptyCollectionPojo);
         pojoCollection.clear();
         initData.forEach(pojoCollection::add);
-        return collection;
+        return pojoCollection;
     }
     
     @Override
-    public Collection<ObjectAdapter> collection(final ObjectAdapter collectionAdapter) {
-        final Collection<?> pojoCollection = pojoCollection(collectionAdapter);
-        
-        return _Lists.map(pojoCollection, adapterProvider::adapterFor);
-                
-    }
-
-    @Override
-    public ObjectAdapter firstElement(final ObjectAdapter collection) {
-        final Iterator<ObjectAdapter> iterator = iterator(collection);
-        return iterator.hasNext() ? iterator.next() : null;
+    public int size(final ManagedObject collection) {
+        return pojoCollection(collection).size();
     }
 
     @Override
-    public int size(final ObjectAdapter collection) {
-        return pojoCollection(collection).size();
+    public <T extends ManagedObject> Stream<T> stream(T collectionAdapter) {
+        return pojoCollection(collectionAdapter)
+                .stream()
+                .map(adapterProvider::adapterFor)
+                .map(x->(T)x);
     }
-
+    
     /**
      * The underlying collection of objects (not {@link ObjectAdapter}s).
      */
     @SuppressWarnings("unchecked")
-    private Collection<? super Object> pojoCollection(final ObjectAdapter collectionAdapter) {
+    private Collection<? super Object> pojoCollection(final ManagedObject collectionAdapter) {
         return (Collection<? super Object>) collectionAdapter.getObject();
     }
 
+    // -- HELPER
+
+    private Collection<ManagedObject> collection(final ManagedObject collectionAdapter) {
+        final Collection<?> pojoCollection = pojoCollection(collectionAdapter);
+        
+        return _Lists.map(pojoCollection, adapterProvider::adapterFor);
+                
+    }
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/modify/CollectionFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/modify/CollectionFacet.java
index 68ac8f1..b52fa5f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/modify/CollectionFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/modify/CollectionFacet.java
@@ -19,15 +19,15 @@
 
 package org.apache.isis.core.metamodel.facets.collections.modify;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 /**
@@ -40,26 +40,23 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
  */
 public interface CollectionFacet extends Facet {
 
-    int size(ObjectAdapter collection);
+    int size(ManagedObject collectionAdapter);
 
-    Iterable<ObjectAdapter> iterable(ObjectAdapter collectionAdapter);
+    <T extends ManagedObject> Stream<T> stream(T collectionAdapter);
 
-    Iterator<ObjectAdapter> iterator(ObjectAdapter collectionAdapter);
-
-    /**
-     * Returns an unmodifiable {@link Collection} of {@link ObjectAdapter}s.
-     */
-    Collection<ObjectAdapter> collection(ObjectAdapter collectionAdapter);
-
-    ObjectAdapter firstElement(ObjectAdapter collectionAdapter);
+    default <T extends ManagedObject> T firstElement(T collectionAdapter) {
+        return stream(collectionAdapter).findFirst().orElse(null);
+    }
 
-    boolean contains(ObjectAdapter collectionAdapter, ObjectAdapter element);
+    boolean contains(ManagedObject collectionAdapter, ManagedObject element);
 
     /**
      * Set the contents of this collection.
      * @return a possibly new instance
      */
-    ObjectAdapter init(ObjectAdapter collectionAdapter, Stream<ObjectAdapter> elements, int elementCount);
+    //<T extends ManagedObject> T init(T collectionAdapter, Stream<T> elements, int elementCount);
+    <T extends ManagedObject> Object populatePojo(
+            Object emptyCollectionPojo, ObjectSpecification collectionSpec, Stream<T> elements, int elementCount);
 
     /**
      * Convenience method that returns the {@link TypeOfFacet} on this facet's
@@ -67,27 +64,33 @@ public interface CollectionFacet extends Facet {
      */
     TypeOfFacet getTypeOfFacet();
 
-
     public static class Utils {
 
-        public static CollectionFacet getCollectionFacetFromSpec(final ObjectAdapter objectRepresentingCollection) {
+        public static CollectionFacet getCollectionFacetFromSpec(final ManagedObject objectRepresentingCollection) {
             final ObjectSpecification collectionSpec = objectRepresentingCollection.getSpecification();
             return collectionSpec.getFacet(CollectionFacet.class);
         }
 
-        public static int size(final ObjectAdapter collection) {
+        public static int size(final ManagedObject collection) {
             final CollectionFacet facet = getCollectionFacetFromSpec(collection);
             return facet.size(collection);
         }
 
-        public static List<ObjectAdapter> convertToAdapterList(final ObjectAdapter collection) {
-            final CollectionFacet facet = getCollectionFacetFromSpec(collection);
-            final List<ObjectAdapter> adapters = new ArrayList<ObjectAdapter>();
-            for (final ObjectAdapter adapter : facet.iterable(collection)) {
-                adapters.add(adapter);
-            }
-            return adapters;
+        public static <T extends ManagedObject> Stream<T> streamAdapters(final T collectionAdapter) {
+            final CollectionFacet facet = getCollectionFacetFromSpec(collectionAdapter);
+            return Utils.<T>downCast(facet.stream(collectionAdapter));
+        }
+        
+        public static <T extends ManagedObject> List<T> toAdapterList(final T collectionAdapter) {
+            return streamAdapters(collectionAdapter)
+                    .collect(Collectors.toList());
+        }
+        
+        private static <T extends ManagedObject> Stream<T> downCast(final Stream<ManagedObject> stream) {
+            final Function<ManagedObject, T> uncheckedCast = _Casts::uncheckedCast;
+            return stream.map(uncheckedCast);
         }
 
     }
+    
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java
index 13aaca0..e131342 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java
@@ -23,6 +23,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Stream;
 
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
@@ -99,8 +100,7 @@ public abstract class AutoCompleteFacetAbstract extends FacetAbstract implements
             return Collections.emptyList();
         }
 
-        final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(resultAdapter);
-        final Iterable<ObjectAdapter> adapterList = facet.iterable(resultAdapter);
+        final Stream<ObjectAdapter> adapterList = CollectionFacet.Utils.streamAdapters(resultAdapter) ;
 
         return ObjectAdapter.Util.visibleAdapters(adapterList, interactionInitiatedBy);
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java
index 15fa823..f53784e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectvalidprops/impl/ObjectValidPropertiesFacetImpl.java
@@ -20,7 +20,6 @@
 package org.apache.isis.core.metamodel.facets.object.objectvalidprops.impl;
 
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.object.objectvalidprops.ObjectValidPropertiesFacetAbstract;
 import org.apache.isis.core.metamodel.interactions.ObjectValidityContext;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/ActionParameterChoicesFacetFromParentedCollection.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/ActionParameterChoicesFacetFromParentedCollection.java
index 271af4a..58ec6b4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/ActionParameterChoicesFacetFromParentedCollection.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/postprocessors/param/ActionParameterChoicesFacetFromParentedCollection.java
@@ -55,7 +55,7 @@ public class ActionParameterChoicesFacetFromParentedCollection extends ActionPar
             final InteractionInitiatedBy interactionInitiatedBy) {
         final ObjectAdapter parentAdapter = determineParentAdapter(target);
         final ObjectAdapter objectAdapter = otma.get(parentAdapter, interactionInitiatedBy);
-        final List<ObjectAdapter> objectAdapters = CollectionFacet.Utils.convertToAdapterList(objectAdapter);
+        final List<ObjectAdapter> objectAdapters = CollectionFacet.Utils.toAdapterList(objectAdapter);
         return ObjectAdapter.Util.unwrap(objectAdapters.toArray(new ObjectAdapter[0]));
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/FreeStandingList.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/FreeStandingList.java
index d6bc424..0485514 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/FreeStandingList.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/FreeStandingList.java
@@ -20,30 +20,41 @@
 package org.apache.isis.core.metamodel.spec;
 
 import java.util.AbstractList;
-import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.isis.core.commons.util.ToString;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 
 /**
  * A list returned from an action, ie not associated or owned by any entity.
  */
-public class FreeStandingList extends AbstractList<ObjectAdapter> {
+public class FreeStandingList extends AbstractList<ManagedObject> {
 
-    private final List<ObjectAdapter> instances;
+    private final List<ManagedObject> instances;
     private final ObjectSpecification instanceSpecification;
 
-    public FreeStandingList(final ObjectSpecification instanceSpecification, final List<ObjectAdapter> instances) {
+    public static <T extends ManagedObject> FreeStandingList of(
+            final ObjectSpecification instanceSpecification, 
+            final List<T> instances) {
+        
+        return new FreeStandingList(instanceSpecification, instances.stream()
+                .map(x->(T)x)
+                .collect(Collectors.toList()));
+    }
+    
+    private FreeStandingList(
+            final ObjectSpecification instanceSpecification, 
+            final List<ManagedObject> instances) {
+        
         this.instanceSpecification = instanceSpecification;
-        this.instances = Collections.unmodifiableList(instances);
+        this.instances = instances;
     }
-
+    
     /**
      * Required implementation of {@link AbstractList}.
      */
     @Override
-    public ObjectAdapter get(final int index) {
+    public ManagedObject get(final int index) {
         return instances.get(index);
     }
 
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 de8b767..dd36175 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
@@ -25,6 +25,7 @@ import java.util.function.Supplier;
 
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
 
 /**
  * Represents an instance of some element of the meta-model.
@@ -49,6 +50,79 @@ public interface ManagedObject extends Instance {
      */
     Object getPojo();
     
+    // -- TITLE
+    
+    public default String titleString() {
+        return titleString(null);
+    }
+    
+    default String titleString(ObjectAdapter contextAdapterIfAny) {
+        return TitleUtil.titleString(this, contextAdapterIfAny);
+    }
+    
+    
+    public static class TitleUtil {
+        
+        public static String titleString(ManagedObject managedObject, ObjectAdapter contextAdapterIfAny) {
+            if (managedObject.getSpecification().isParentedOrFreeCollection()) {
+                final CollectionFacet facet = managedObject.getSpecification().getFacet(CollectionFacet.class);
+                return collectionTitleString(managedObject, facet);
+            } else {
+                return objectTitleString(managedObject, contextAdapterIfAny);
+            }
+        }
+
+        private static String objectTitleString(ManagedObject managedObject, ObjectAdapter contextAdapterIfAny) {
+            if (managedObject.getPojo() instanceof String) {
+                return (String) managedObject.getPojo();
+            }
+            final ObjectSpecification specification = managedObject.getSpecification();
+            String title = specification.getTitle(contextAdapterIfAny, managedObject);
+
+            if (title == null) {
+                title = getDefaultTitle(managedObject);
+            }
+            return title;
+        }
+
+        private static String collectionTitleString(ManagedObject managedObject, final CollectionFacet facet) {
+            final int size = facet.size(managedObject);
+            final ObjectSpecification elementSpecification = managedObject.getElementSpecification();
+            if (elementSpecification == null || elementSpecification.getFullIdentifier().equals(Object.class.getName())) {
+                switch (size) {
+                case -1:
+                    return "Objects";
+                case 0:
+                    return "No objects";
+                case 1:
+                    return "1 object";
+                default:
+                    return size + " objects";
+                }
+            } else {
+                switch (size) {
+                case -1:
+                    return elementSpecification.getPluralName();
+                case 0:
+                    return "No " + elementSpecification.getPluralName();
+                case 1:
+                    return "1 " + elementSpecification.getSingularName();
+                default:
+                    return size + " " + elementSpecification.getPluralName();
+                }
+            }
+        }
+        
+        private static String getDefaultTitle(ManagedObject managedObject) {
+            return "A" + (" " + managedObject.getSpecification().getSingularName()).toLowerCase();
+        }
+
+    }
+    
+    // -- COLLECTIN SUPPORT
+    
+    ObjectSpecification getElementSpecification();
+    
     // -- GLUE CODE
     
     default Object getObject() {
@@ -67,6 +141,11 @@ public interface ManagedObject extends Instance {
             public Object getPojo() {
                 return pojo;
             }
+            @Override
+            public ObjectSpecification getElementSpecification() {
+                // TODO Auto-generated method stub
+                return null;
+            }
         };
     }
     
@@ -82,18 +161,15 @@ public interface ManagedObject extends Instance {
             public Object getPojo() {
                 return pojo;
             }
+            @Override
+            public ObjectSpecification getElementSpecification() {
+                // TODO Auto-generated method stub
+                return null;
+            }
         };
     }
 
-    default String titleString(Object object) {
-        //FIXME
-        return "TODO: ManagedObject.titleString(Object)";
-    }
 
-    default String titleString() {
-        //FIXME
-        return "TODO: ManagedObject.titleString()";
-    }
     
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/CollectionFacetOnStandaloneList.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/CollectionFacetOnStandaloneList.java
index fcfe276..201124e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/CollectionFacetOnStandaloneList.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/CollectionFacetOnStandaloneList.java
@@ -22,10 +22,13 @@ package org.apache.isis.core.metamodel.specloader.specimpl.standalonelist;
 import java.util.List;
 import java.util.stream.Stream;
 
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.collections.CollectionFacetAbstract;
 import org.apache.isis.core.metamodel.spec.FreeStandingList;
+import org.apache.isis.core.metamodel.spec.ManagedObject;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 public class CollectionFacetOnStandaloneList extends CollectionFacetAbstract {
 
@@ -33,23 +36,16 @@ public class CollectionFacetOnStandaloneList extends CollectionFacetAbstract {
         super(holder);
     }
 
-    /**
-     * Expected to be called with a {@link ObjectAdapter} wrapping a
-     * {@link FreeStandingList}.
-     */
     @Override
-    public List<ObjectAdapter> collection(final ObjectAdapter wrappedObjectList) {
-        return (FreeStandingList) wrappedObjectList.getObject();
+    public <T extends ManagedObject> Stream<T> stream(T wrappedObjectList) {
+        final List<ManagedObject> list = collection(wrappedObjectList);
+        return list.stream()
+                .map(x->(T)x);
     }
-
-    /**
-     * Expected to be called with a {@link ObjectAdapter} wrapping a
-     * {@link FreeStandingList}.
-     */
+    
     @Override
-    public ObjectAdapter firstElement(final ObjectAdapter wrappedInstanceCollectionVector) {
-        final List<ObjectAdapter> icv = collection(wrappedInstanceCollectionVector);
-        return icv.size() > 0 ? icv.get(0) : null;
+    public boolean contains(ManagedObject collectionAdapter, ManagedObject element) {
+        return collection(collectionAdapter).contains(element);
     }
 
     /**
@@ -57,16 +53,24 @@ public class CollectionFacetOnStandaloneList extends CollectionFacetAbstract {
      * {@link FreeStandingList}.
      */
     @Override
-    public int size(final ObjectAdapter wrappedInstanceCollectionVector) {
+    public int size(final ManagedObject wrappedInstanceCollectionVector) {
         return collection(wrappedInstanceCollectionVector).size();
     }
 
-    /**
-     * Does nothing.
-     */
     @Override
-    public ObjectAdapter init(ObjectAdapter collectionAdapter, Stream<ObjectAdapter> elements, int elementCount) {
-        return collectionAdapter;
+    public <T extends ManagedObject> Object populatePojo(
+            Object emptyCollectionPojo,
+            ObjectSpecification collectionSpec,
+            Stream<T> elements, 
+            int elementCount) {
+        
+        throw _Exceptions.unexpectedCodeReach();
     }
 
+    // -- HELPER
+    
+    private List<ManagedObject> collection(final ManagedObject wrappedObjectList) {
+        return (FreeStandingList) wrappedObjectList.getObject();
+    }
+    
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
index f390bb4..7a877f0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/runtime/snapshot/XmlSnapshot.java
@@ -511,21 +511,25 @@ public class XmlSnapshot implements Snapshot {
 
             final OneToManyAssociation oneToManyAssociation = (OneToManyAssociation) field;
             final ObjectAdapter collection = oneToManyAssociation.get(fieldPlace.getObject(), InteractionInitiatedBy.FRAMEWORK);
-            final CollectionFacet facet = collection.getSpecification().getFacet(CollectionFacet.class);
-
+            
             if (LOG.isDebugEnabled()) {
-                LOG.debug("includeField(Pl, Vec, Str): 1->M: {}", log("collection.size", "" + facet.size(collection)));
+                LOG.debug("includeField(Pl, Vec, Str): 1->M: {}", log("collection.size", "" + CollectionFacet.Utils.size(collection)));
             }
-            boolean allFieldsNavigated = true;
-            for (final ObjectAdapter referencedObject : facet.iterable(collection)) {
-                final boolean appendedXml = appendXmlThenIncludeRemaining(fieldPlace, referencedObject, names, annotation);
+            
+            final boolean[] allFieldsNavigated = {true}; // fast non-thread-safe value reference
+            
+            CollectionFacet.Utils.streamAdapters(collection)
+            .forEach(referencedObject->{
+                final boolean appendedXml = 
+                        appendXmlThenIncludeRemaining(fieldPlace, referencedObject, names, annotation);
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("includeField(Pl, Vec, Str): 1->M: + invoked appendXmlThenIncludeRemaining for {}{}",log("referencedObj", referencedObject), andlog("returned", "" + appendedXml));
                 }
-                allFieldsNavigated = allFieldsNavigated && appendedXml;
-            }
+                allFieldsNavigated[0] = allFieldsNavigated[0] && appendedXml;
+            });
+            
             LOG.debug("includeField(Pl, Vec, Str): {}", log("returning", "" + allFieldsNavigated));
-            return allFieldsNavigated;
+            return allFieldsNavigated[0];
         }
 
         return false; // fall through, shouldn't get here but just in
diff --git a/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java b/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java
index 86c78f2..96bc80e 100644
--- a/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java
+++ b/core/plugins/jdo-datanucleus-4/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession4.java
@@ -320,12 +320,12 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     @Override
     public <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query) {
         final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.MULTIPLE);
-        return CollectionFacet.Utils.convertToAdapterList(instances);
+        return CollectionFacet.Utils.toAdapterList(instances);
     }
     @Override
     public <T> ObjectAdapter firstMatchingQuery(final Query<T> query) {
         final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.SINGLE);
-        final List<ObjectAdapter> list = CollectionFacet.Utils.convertToAdapterList(instances);
+        final List<ObjectAdapter> list = CollectionFacet.Utils.toAdapterList(instances);
         return list.size() > 0 ? list.get(0) : null;
     }
 
@@ -355,7 +355,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final List<ObjectAdapter> instances = transactionManager.executeWithinTransaction(
                 ()->processPersistenceQuery(processor, persistenceQuery) );
         final ObjectSpecification specification = persistenceQuery.getSpecification();
-        final FreeStandingList results = new FreeStandingList(specification, instances);
+        final FreeStandingList results = FreeStandingList.of(specification, instances);
         return adapterFor(results);
     }
 
diff --git a/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java b/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java
index 5aa9182..c7b381a 100644
--- a/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java
+++ b/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java
@@ -65,7 +65,7 @@ public class PojoAdapterTest {
     public void setUp() throws Exception {
         domainObject = new RuntimeTestPojo();
         
-        adapter = new PojoAdapter(domainObject, Factory.persistentOf(ObjectSpecId.of("CUS"), "1"), mockAuthenticationSession,
+        adapter = PojoAdapter.of(domainObject, Factory.persistentOf(ObjectSpecId.of("CUS"), "1"), mockAuthenticationSession,
                 mockSpecificationLoader, mockPersistenceSession);
         adapter.setVersion(mockVersion);
         
diff --git a/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java b/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java
index 2974c01..2aa948f 100644
--- a/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java
+++ b/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java
@@ -125,7 +125,8 @@ public class PojoAdapterBuilder {
         return this;
     }
 
-    public PojoAdapterBuilder withOid(String oidAndTitle) {
+    //test only
+    PojoAdapterBuilder withOid(String oidAndTitle) {
         final Iterator<String> iterator = Splitter.on("|").split(oidAndTitle).iterator();
         if(!iterator.hasNext()) { return this; }
         withObjectType(iterator.next());
@@ -191,15 +192,8 @@ public class PojoAdapterBuilder {
     public PojoAdapter build() {
         final RootOid rootOid = persistence.createOid(objectSpecId, identifier);
         final Oid oid = type.oidFor(rootOid, objectSpecId, aggregatedId);
-        final PojoAdapter pojoAdapter = new PojoAdapter(pojo, oid, authenticationSession,
-                specificationLoader, persistenceSession) {
-            @Override
-            public ObjectSpecification getSpecification() { return objectSpec != null? objectSpec: super.getSpecification(); }
-            @Override
-            public String titleString() {
-                return titleString != null? titleString: super.titleString();
-            }
-        };
+        final PojoAdapter pojoAdapter = PojoAdapter.of(pojo, oid, authenticationSession,
+                specificationLoader, persistenceSession);
         if(persistence == Persistence.PERSISTENT && version != null) {
             pojoAdapter.setVersion(version);
         }
diff --git a/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/system/ObjectMemberAbstractTest.java b/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/system/ObjectMemberAbstractTest.java
index beb6411..1b2c2cc 100644
--- a/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/system/ObjectMemberAbstractTest.java
+++ b/core/plugins/jdo-datanucleus-4/src/test/java/org/apache/isis/core/runtime/system/ObjectMemberAbstractTest.java
@@ -33,6 +33,7 @@ import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
 import org.apache.isis.core.commons.config.IsisConfigurationDefault;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.oid.Oid.Factory;
 import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -56,6 +57,7 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.core.metamodel.specloader.specimpl.ObjectMemberAbstract;
+import org.apache.isis.core.runtime.persistence.adapter.PojoAdapter;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.PojoAdapterBuilder;
 import org.apache.isis.core.runtime.persistence.objectstore.transaction.PojoAdapterBuilder.Persistence;
 import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
@@ -110,11 +112,20 @@ public class ObjectMemberAbstractTest {
             allowing(mockAuthenticationSessionProvider).getAuthenticationSession();
             will(returnValue(mockAuthenticationSession));
         }});
-        persistentAdapter = PojoAdapterBuilder.create()
-                .with(mockSpecificationLoader)
-                .withOid("CUS|1")
-                .withPojo(mockPersistable)
-                .build();
+//        persistentAdapter = PojoAdapterBuilder.create()
+//                .with(mockSpecificationLoader)
+//                .withOid("CUS|1")
+//                .withPojo(mockPersistable)
+//                .build();
+        
+        persistentAdapter = PojoAdapter.of(
+                mockPersistable, 
+                Factory.persistentOf(ObjectSpecId.of("CUS"), "1"),
+                mockAuthenticationSession,
+                mockSpecificationLoader, 
+                null);
+        
+        
         transientAdapter = PojoAdapterBuilder.create()
                 .with(mockSpecificationLoader)
                 .with(Persistence.TRANSIENT)
diff --git a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
index e24afea..921b202 100644
--- a/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
+++ b/core/plugins/jdo-datanucleus-5/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession5.java
@@ -319,12 +319,12 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
     @Override
     public <T> List<ObjectAdapter> allMatchingQuery(final Query<T> query) {
         final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.MULTIPLE);
-        return CollectionFacet.Utils.convertToAdapterList(instances);
+        return CollectionFacet.Utils.toAdapterList(instances);
     }
     @Override
     public <T> ObjectAdapter firstMatchingQuery(final Query<T> query) {
         final ObjectAdapter instances = findInstancesInTransaction(query, QueryCardinality.SINGLE);
-        final List<ObjectAdapter> list = CollectionFacet.Utils.convertToAdapterList(instances);
+        final List<ObjectAdapter> list = CollectionFacet.Utils.toAdapterList(instances);
         return list.size() > 0 ? list.get(0) : null;
     }
 
@@ -354,7 +354,7 @@ implements IsisLifecycleListener.PersistenceSessionLifecycleManagement {
         final List<ObjectAdapter> instances = transactionManager.executeWithinTransaction(
                 ()->processPersistenceQuery(processor, persistenceQuery) );
         final ObjectSpecification specification = persistenceQuery.getSpecification();
-        final FreeStandingList results = new FreeStandingList(specification, instances);
+        final FreeStandingList results = FreeStandingList.of(specification, instances);
         return adapterFor(results);
     }
 
diff --git a/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java b/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java
index 9146d11..a76a6cf 100644
--- a/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java
+++ b/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/adapterfactory/pojo/PojoAdapterTest.java
@@ -65,8 +65,13 @@ public class PojoAdapterTest {
     public void setUp() throws Exception {
         domainObject = new RuntimeTestPojo();
         
-        adapter = new PojoAdapter(domainObject, Factory.persistentOf(ObjectSpecId.of("CUS"), "1"), mockAuthenticationSession,
-                mockSpecificationLoader, mockPersistenceSession);
+        adapter = PojoAdapter.of(
+                domainObject, 
+                Factory.persistentOf(ObjectSpecId.of("CUS"), "1"),
+                mockAuthenticationSession,
+                mockSpecificationLoader, 
+                mockPersistenceSession);
+        
         adapter.setVersion(mockVersion);
         
         allowUnimportantMethodCallsOn(mockVersion);
diff --git a/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java b/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java
index e5f3681..cbd3ba7 100644
--- a/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java
+++ b/core/plugins/jdo-datanucleus-5/src/test/java/org/apache/isis/core/runtime/persistence/objectstore/transaction/PojoAdapterBuilder.java
@@ -191,15 +191,8 @@ public class PojoAdapterBuilder {
     public PojoAdapter build() {
         final RootOid rootOid = persistence.createOid(objectSpecId, identifier);
         final Oid oid = type.oidFor(rootOid, objectSpecId, aggregatedId);
-        final PojoAdapter pojoAdapter = new PojoAdapter(pojo, oid, authenticationSession,
-                specificationLoader, persistenceSession) {
-            @Override
-            public ObjectSpecification getSpecification() { return objectSpec != null? objectSpec: super.getSpecification(); }
-            @Override
-            public String titleString() {
-                return titleString != null? titleString: super.titleString();
-            }
-        };
+        final PojoAdapter pojoAdapter = PojoAdapter.of(pojo, oid, authenticationSession,
+                specificationLoader, persistenceSession);
         if(persistence == Persistence.PERSISTENT && version != null) {
             pojoAdapter.setVersion(version);
         }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java
index c2f7675..27da09c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/memento/Memento.java
@@ -27,6 +27,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.isis.commons.internal.base._Casts;
+import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.commons.exceptions.UnknownTypeException;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -86,12 +87,11 @@ public class Memento implements Serializable {
     }
 
     private Data createCollectionData(final ObjectAdapter adapter) {
-        final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(adapter);
-        final Data[] collData = new Data[facet.size(adapter)];
-        int i = 0;
-        for (final ObjectAdapter ref : facet.iterable(adapter)) {
-            collData[i++] = createReferenceData(ref);
-        }
+        
+        final Data[] collData = CollectionFacet.Utils.streamAdapters(adapter)
+            .map(ref->createReferenceData(ref))
+            .collect(_Arrays.toArray(Data.class, CollectionFacet.Utils.size(adapter)));
+        
         final String elementTypeSpecName = adapter.getSpecification().getFullIdentifier();
         return new CollectionData(clone(adapter.getOid()), elementTypeSpecName, collData);
     }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
index 393df3b..0f6a16c 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/persistence/adapter/PojoAdapter.java
@@ -34,7 +34,6 @@ import org.apache.isis.core.metamodel.adapter.oid.ParentedOid;
 import org.apache.isis.core.metamodel.adapter.oid.RootOid;
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
 import org.apache.isis.core.metamodel.adapter.version.Version;
-import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.core.metamodel.spec.ElementSpecificationProvider;
 import org.apache.isis.core.metamodel.spec.Instance;
 import org.apache.isis.core.metamodel.spec.InstanceAbstract;
@@ -44,7 +43,7 @@ import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
 
-public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
+public final class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
 
     private final static Logger LOG = LoggerFactory.getLogger(PojoAdapter.class);
 
@@ -57,17 +56,21 @@ public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
     private final Object pojo;
     private final Oid oid;
     
-    @Override
-    public Object getPojo() {
-        return pojo;
-    }
-
     /**
      * only for standalone or parented collections.
      */
     private ElementSpecificationProvider elementSpecificationProvider;
+    
+    public static PojoAdapter of(
+            final Object pojo,
+            final Oid oid,
+            final AuthenticationSession authenticationSession,
+            final SpecificationLoader specificationLoader,
+            final PersistenceSession persistenceSession) {
+        return new PojoAdapter(pojo, oid, authenticationSession, specificationLoader, persistenceSession);
+    }
 
-    public PojoAdapter(
+    private PojoAdapter(
             final Object pojo,
             final Oid oid,
             final AuthenticationSession authenticationSession,
@@ -89,6 +92,11 @@ public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
         this.oid = requires(oid, "oid");
     }
     
+    @Override
+    public Object getPojo() {
+        return pojo;
+    }
+    
     // -- getSpecification
 
     /**
@@ -218,71 +226,71 @@ public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
 
 
     // -- titleString
-    /**
-     * Returns the title from the underlying business object.
-     *
-     * <p>
-     * If the object has not yet been resolved the specification will be asked
-     * for a unresolved title, which could of been persisted by the persistence
-     * mechanism. If either of the above provides null as the title then this
-     * method will return a title relating to the name of the object type, e.g.
-     * "A Customer", "A Product".
-     */
-    @Override
-    public String titleString() {
-        return titleString(null);
-    }
-
-    @Override
-    public String titleString(ObjectAdapter contextAdapterIfAny) {
-        if (getSpecification().isParentedOrFreeCollection()) {
-            final CollectionFacet facet = getSpecification().getFacet(CollectionFacet.class);
-            return collectionTitleString(facet);
-        } else {
-            return objectTitleString(contextAdapterIfAny);
-        }
-    }
-
-    private String objectTitleString(ObjectAdapter contextAdapterIfAny) {
-        if (getObject() instanceof String) {
-            return (String) getObject();
-        }
-        final ObjectSpecification specification = getSpecification();
-        String title = specification.getTitle(contextAdapterIfAny, this);
-
-        if (title == null) {
-            title = getDefaultTitle();
-        }
-        return title;
-    }
-
-    private String collectionTitleString(final CollectionFacet facet) {
-        final int size = facet.size(this);
-        final ObjectSpecification elementSpecification = getElementSpecification();
-        if (elementSpecification == null || elementSpecification.getFullIdentifier().equals(Object.class.getName())) {
-            switch (size) {
-            case -1:
-                return "Objects";
-            case 0:
-                return "No objects";
-            case 1:
-                return "1 object";
-            default:
-                return size + " objects";
-            }
-        } else {
-            switch (size) {
-            case -1:
-                return elementSpecification.getPluralName();
-            case 0:
-                return "No " + elementSpecification.getPluralName();
-            case 1:
-                return "1 " + elementSpecification.getSingularName();
-            default:
-                return size + " " + elementSpecification.getPluralName();
-            }
-        }
-    }
+//    /**
+//     * Returns the title from the underlying business object.
+//     *
+//     * <p>
+//     * If the object has not yet been resolved the specification will be asked
+//     * for a unresolved title, which could of been persisted by the persistence
+//     * mechanism. If either of the above provides null as the title then this
+//     * method will return a title relating to the name of the object type, e.g.
+//     * "A Customer", "A Product".
+//     */
+//    @Override
+//    public String titleString() {
+//        return titleString(null);
+//    }
+
+//    @Override
+//    public String titleString(ObjectAdapter contextAdapterIfAny) {
+//        if (getSpecification().isParentedOrFreeCollection()) {
+//            final CollectionFacet facet = getSpecification().getFacet(CollectionFacet.class);
+//            return collectionTitleString(facet);
+//        } else {
+//            return objectTitleString(contextAdapterIfAny);
+//        }
+//    }
+//
+//    private String objectTitleString(ObjectAdapter contextAdapterIfAny) {
+//        if (getObject() instanceof String) {
+//            return (String) getObject();
+//        }
+//        final ObjectSpecification specification = getSpecification();
+//        String title = specification.getTitle(contextAdapterIfAny, this);
+//
+//        if (title == null) {
+//            title = getDefaultTitle();
+//        }
+//        return title;
+//    }
+//
+//    private String collectionTitleString(final CollectionFacet facet) {
+//        final int size = facet.size(this);
+//        final ObjectSpecification elementSpecification = getElementSpecification();
+//        if (elementSpecification == null || elementSpecification.getFullIdentifier().equals(Object.class.getName())) {
+//            switch (size) {
+//            case -1:
+//                return "Objects";
+//            case 0:
+//                return "No objects";
+//            case 1:
+//                return "1 object";
+//            default:
+//                return size + " objects";
+//            }
+//        } else {
+//            switch (size) {
+//            case -1:
+//                return elementSpecification.getPluralName();
+//            case 0:
+//                return "No " + elementSpecification.getPluralName();
+//            case 1:
+//                return "1 " + elementSpecification.getSingularName();
+//            default:
+//                return size + " " + elementSpecification.getPluralName();
+//            }
+//        }
+//    }
 
     @Override
     public String toString() {
@@ -298,9 +306,9 @@ public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
         return str.toString();
     }
 
-    protected String getDefaultTitle() {
-        return "A" + (" " + getSpecification().getSingularName()).toLowerCase();
-    }
+//    protected String getDefaultTitle() {
+//        return "A" + (" " + getSpecification().getSingularName()).toLowerCase();
+//    }
 
     protected void toString(final ToString str) {
         str.append(aggregateResolveStateCode());
@@ -381,15 +389,6 @@ public class PojoAdapter extends InstanceAbstract implements ObjectAdapter {
     public Instance getInstance(final Specification specification) {
         throw new UnsupportedOperationException();
     }
-
-    @Override
-    public ObjectAdapter withOid(RootOid newOid) {
-        return new PojoAdapter(pojo, newOid, authenticationSession, specificationLoader, persistenceSession);
-    }
     
-    @Override
-    public ObjectAdapter withPojo(Object newPojo) {
-        return new PojoAdapter(newPojo, oid, authenticationSession, specificationLoader, persistenceSession);
-    }
 
 }
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Factories.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Factories.java
index b951e0c..fffc74f 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Factories.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_Factories.java
@@ -91,7 +91,7 @@ class ObjectAdapterContext_Factories implements ObjectAdapterFactories {
     private ObjectAdapter createAdapter(
             final Object pojo,
             final Oid oid) {
-        return new PojoAdapter(
+        return PojoAdapter.of(
                 pojo, oid,
                 authenticationSession,
                 specificationLoader, session);
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
index f31d9e5..ec66fe6 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/adaptermanager/ObjectAdapterContext_MementoSupport.java
@@ -24,7 +24,6 @@ import java.util.stream.Stream;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.commons.ensure.Assert;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -72,10 +71,12 @@ class ObjectAdapterContext_MementoSupport implements MementoRecreateObjectSuppor
         
         if (spec.isParentedOrFreeCollection()) {
 
-            final Object recreatedPojo = objectAdapterContext.instantiateAndInjectServices(spec);
-            adapter = objectAdapterContext.recreatePojo(oid, recreatedPojo);
-            adapter = populateCollection(adapter, (CollectionData) data);
+            final Object emptyCollectionPojo = objectAdapterContext.instantiateAndInjectServices(spec);
+            
+            final Object collectionPojo = populateCollection(emptyCollectionPojo, spec, (CollectionData) data);
+            adapter = objectAdapterContext.recreatePojo(oid, collectionPojo);
 
+            
         } else {
             Assert.assertTrue("oid must be a RootOid representing an object because spec is not a collection and cannot be a value", oid instanceof RootOid);
             RootOid typedOid = (RootOid) oid;
@@ -130,12 +131,16 @@ class ObjectAdapterContext_MementoSupport implements MementoRecreateObjectSuppor
         }
     }
     
-    private ObjectAdapter populateCollection(final ObjectAdapter collectionAdapter, final CollectionData state) {
+    private Object populateCollection(
+            final Object emptyCollectionPojo, 
+            final ObjectSpecification collectionSpec, 
+            final CollectionData state) {
+        
         final Stream<ObjectAdapter> initData = state.streamElements()
             .map((final Data elementData) -> recreateReference(elementData));
         
-        final CollectionFacet facet = collectionAdapter.getSpecification().getFacet(CollectionFacet.class);
-        return facet.init(collectionAdapter, initData, state.getElementCount());
+        final CollectionFacet facet = collectionSpec.getFacet(CollectionFacet.class);
+        return facet.populatePojo(emptyCollectionPojo, collectionSpec, initData, state.getElementCount());
     }
     
     private void updateFieldsAndResolveState(final ObjectAdapter objectAdapter, final Data data) {
@@ -200,10 +205,7 @@ class ObjectAdapterContext_MementoSupport implements MementoRecreateObjectSuppor
     private void updateOneToManyAssociation(final ObjectAdapter objectAdapter, final OneToManyAssociation otma, final CollectionData collectionData) {
         final ObjectAdapter collection = otma.get(objectAdapter, InteractionInitiatedBy.FRAMEWORK);
         final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collection);
-        final List<ObjectAdapter> original = _Lists.newArrayList();
-        for (final ObjectAdapter adapter : facet.iterable(collection)) {
-            original.add(adapter);
-        }
+        final List<ObjectAdapter> original = CollectionFacet.Utils.toAdapterList(collection); 
 
         collectionData.streamElements().forEach((final Data data) -> {
             final ObjectAdapter elementAdapter = recreateReference(data);
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
index efa31b6..435c2cb 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ActionResultReprRenderer.java
@@ -135,9 +135,9 @@ public class ActionResultReprRenderer extends ReprRendererAbstract<ActionResultR
 
         case LIST:
 
-            final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
-            final Collection<ObjectAdapter> collectionAdapters = collectionFacet.collection(returnedAdapter);
-
+            final Collection<ObjectAdapter> collectionAdapters =
+                CollectionFacet.Utils.toAdapterList(returnedAdapter);
+            
             final ListReprRenderer listReprRenderer =
                     new ListReprRenderer(rendererContext, null, representation).withElementRel(Rel.ELEMENT);
             listReprRenderer.with(collectionAdapters)
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
index 1531d24..88b6223 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectCollectionReprRenderer.java
@@ -19,6 +19,7 @@ package org.apache.isis.viewer.restfulobjects.rendering.domainobjects;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Stream;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.commons.internal.collections._Lists;
@@ -89,10 +90,11 @@ public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRender
         final LinkFollowSpecs followHref = linkFollower.follow("href");
         boolean eagerlyRender = rendererContext.honorUiHints() && renderEagerly(valueAdapter) || !followHref.isTerminated();
 
-        final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(valueAdapter);
+        final Stream<ObjectAdapter> elementAdapters = CollectionFacet.Utils.streamAdapters(valueAdapter);
+        
         final List<JsonRepresentation> list = _Lists.newArrayList();
-        for (final ObjectAdapter elementAdapter : facet.iterable(valueAdapter)) {
-
+        
+        elementAdapters.forEach(elementAdapter->{
             final LinkBuilder valueLinkBuilder = DomainObjectReprRenderer.newLinkToBuilder(rendererContext, Rel.VALUE, elementAdapter);
             if(eagerlyRender) {
                 final DomainObjectReprRenderer renderer = new DomainObjectReprRenderer(getRendererContext(), followHref, JsonRepresentation.newMap()
@@ -106,7 +108,7 @@ public class ObjectCollectionReprRenderer extends AbstractObjectMemberReprRender
             }
 
             list.add(valueLinkBuilder.build());
-        }
+        });
 
         representation.mapPut("value", list);
     }
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
index 306e3dd..40f240f 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
@@ -21,6 +21,7 @@ import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
@@ -322,7 +323,7 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
 
         final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
         return collectionFacet != null
-                ? collectionFacet.collection(returnedAdapter)
+                ? collectionFacet.stream(returnedAdapter).collect(Collectors.toList())
                         : null;
     }
 
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheIsisV1.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheIsisV1.java
index 77e3ce9..fed50d5 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheIsisV1.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceOrgApacheIsisV1.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.viewer.restfulobjects.rendering.service.conneg;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.stream.Stream;
 
@@ -248,8 +247,10 @@ public class ContentNegotiationServiceOrgApacheIsisV1 extends ContentNegotiation
             rootRepresentation = JsonRepresentation.newArray();
 
             final CollectionFacet collectionFacet = returnType.getFacet(CollectionFacet.class);
-            final Collection<ObjectAdapter> collectionAdapters = collectionFacet.collection(returnedAdapter);
-            appendIterableTo(rendererContext, collectionAdapters, rootRepresentation);
+            
+            final Stream<ObjectAdapter> collectionAdapters = CollectionFacet.Utils.streamAdapters(returnedAdapter);
+            
+            appendStreamTo(rendererContext, collectionAdapters, rootRepresentation);
 
             // $$ro representation will be an object in the list with a single property named "$$ro"
             if(!suppressRO) {
@@ -374,22 +375,21 @@ public class ContentNegotiationServiceOrgApacheIsisV1 extends ContentNegotiation
             return;
         }
 
-        final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(valueAdapter);
-        final Iterable<ObjectAdapter> iterable = facet.iterable(valueAdapter);
-        appendIterableTo(rendererContext, iterable, representation);
+        final Stream<ObjectAdapter> adapters = CollectionFacet.Utils.streamAdapters(valueAdapter);
+        appendStreamTo(rendererContext, adapters, representation);
     }
 
-    private void appendIterableTo(
+    private void appendStreamTo(
             final RepresentationService.Context2 rendererContext,
-            final Iterable<ObjectAdapter> iterable,
+            final Stream<ObjectAdapter> adapters,
             final JsonRepresentation collectionRepresentation) {
-        for (final ObjectAdapter elementAdapter : iterable) {
-
+        
+        adapters.forEach(elementAdapter->{
             JsonRepresentation elementRepresentation = JsonRepresentation.newMap();
             appendPropertiesTo(rendererContext, elementAdapter, elementRepresentation);
 
             collectionRepresentation.arrayAdd(elementRepresentation);
-        }
+        });
     }
 
     private static InteractionInitiatedBy determineInteractionInitiatedByFrom(