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 2019/12/18 14:31:27 UTC

[isis] 04/04: ISIS-2226: refactoring all the argument lists/arrays into Can

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 2f9661c601b1b15a316ed5d80c1a8a279d9b8467
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Dec 18 15:31:10 2019 +0100

    ISIS-2226: refactoring all the argument lists/arrays into Can<T>
---
 .../isis/metamodel/facets/DomainEventHelper.java   |  23 +--
 .../invocation/ActionDomainEventFacetAbstract.java |  10 +-
 .../action/invocation/ActionInvocationFacet.java   |   3 +-
 ...ctionInvocationFacetForDomainEventAbstract.java |  36 ++---
 .../actions/action/invocation/CommandUtil.java     |  11 +-
 .../actions/validate/ActionValidationFacet.java    |   3 +-
 .../method/ActionValidationFacetViaMethod.java     |   3 +-
 .../interactions/ActionArgValidityContext.java     |  33 ++--
 .../interactions/ActionValidityContext.java        |  26 ++-
 .../metamodel/objectmanager/ObjectManager.java     |   3 +-
 .../objectmanager/ObjectManagerDefault.java        |   4 +-
 .../param/DeriveFacetsPostProcessor.java           |  18 +--
 .../command/CommandDtoServiceInternal.java         |   5 +-
 .../services/homepage/HomePageAction.java          |   3 +-
 .../ixn/InteractionDtoServiceInternal.java         |   5 +-
 .../services/metamodel/DomainMemberDefault.java    |   9 +-
 .../services/metamodel/MetaModelExporter.java      |   2 +-
 .../apache/isis/metamodel/spec/ManagedObject.java  |  18 +++
 .../isis/metamodel/spec/feature/ObjectAction.java  |  26 +--
 .../spec/feature/ObjectActionContainer.java        |   4 +-
 .../spec/feature/ObjectActionParameter.java        |   6 +-
 .../metamodel/spec/feature/ObjectAssociation.java  |   6 +-
 .../specloader/specimpl/ContributeeMember.java     |   2 +-
 .../specimpl/ObjectActionContributee.java          | 104 ++++++------
 .../specloader/specimpl/ObjectActionDefault.java   | 178 +++++++++------------
 .../specloader/specimpl/ObjectActionMixedIn.java   |  26 +--
 .../specimpl/ObjectActionParameterAbstract.java    |  74 +++------
 .../ObjectActionParameterContributeeAbstract.java  |   4 +-
 .../ObjectActionParameterMixedInAbstract.java      |   4 +-
 .../specimpl/OneToManyAssociationContributee.java  |   7 +-
 .../specimpl/OneToManyAssociationDefault.java      |  11 +-
 .../specimpl/OneToManyAssociationMixedIn.java      |   3 +-
 .../specimpl/OneToOneAssociationContributee.java   |  13 +-
 .../specimpl/OneToOneAssociationDefault.java       |  34 ++--
 .../specimpl/OneToOneAssociationMixedIn.java       |   3 +-
 .../specimpl/dflt/ObjectSpecificationDefault.java  |  19 ++-
 .../ObjectSpecificationOnStandaloneList.java       |   9 +-
 ...ionParameterAbstractTest_getId_and_getName.java |   7 +-
 .../specimpl/ObjectAssociationAbstractTest.java    |   5 +-
 ...ObjectAssociationAbstractTest_alwaysHidden.java |   5 +-
 .../testspec/ObjectSpecificationStub.java          |   7 +-
 .../command/CommandDtoServiceInternalDefault.java  |  26 +--
 .../command/CommandExecutorServiceDefault.java     |  18 ++-
 .../ixn/InteractionDtoServiceInternalDefault.java  |   6 +-
 .../handlers/DomainObjectInvocationHandler.java    |  41 +++--
 .../domainobjects/ObjectActionReprRenderer.java    |  15 +-
 .../domainobjects/ObjectAndActionInvocation.java   |  10 +-
 .../domainobjects/ObjectPropertyReprRenderer.java  |  12 +-
 .../domaintypes/ActionDescriptionReprRenderer.java |   8 +-
 ...entNegotiationServiceForRestfulObjectsV1_0.java |  11 +-
 .../swagger/internal/ClassExcluderAbstract.java    |   5 +-
 .../service/swagger/internal/Generation.java       |   4 +-
 .../rendering/service/swagger/internal/Util.java   |   3 +-
 .../viewer/resources/DomainResourceHelper.java     |  15 +-
 .../viewer/resources/ObjectActionArgHelper.java    |  20 ++-
 .../model/mementos/ActionParameterMemento.java     |   4 +-
 .../viewer/wicket/model/models/ActionModel.java    |  63 ++++----
 .../viewer/wicket/model/models/ScalarModel.java    |  26 +--
 .../components/actions/ActionParametersForm.java   |   5 +-
 .../components/scalars/ScalarPanelAbstract2.java   |   9 +-
 .../scalars/ScalarPanelSelect2Abstract.java        |   2 +-
 .../java/demoapp/dom/actions/depargs/DemoItem.java |   2 +-
 .../SupportingMethodValidatorRefinerFactory.java   |  24 +--
 63 files changed, 537 insertions(+), 564 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/DomainEventHelper.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/DomainEventHelper.java
index a05d2c0..1b736bd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/DomainEventHelper.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/DomainEventHelper.java
@@ -24,7 +24,6 @@ import java.lang.reflect.InvocationTargetException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.stream.Collectors;
 
 import org.apache.isis.applib.FatalException;
 import org.apache.isis.applib.Identifier;
@@ -33,7 +32,9 @@ import org.apache.isis.applib.events.domain.ActionDomainEvent;
 import org.apache.isis.applib.events.domain.CollectionDomainEvent;
 import org.apache.isis.applib.events.domain.PropertyDomainEvent;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.assertions._Assert;
+import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.metamodel.facetapi.IdentifiedHolder;
 import org.apache.isis.metamodel.services.events.MetamodelEventService;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -67,7 +68,7 @@ public class DomainEventHelper {
             final IdentifiedHolder identified,
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final ManagedObject resultAdapter) {
         
         return postEventForAction(phase, uncheckedCast(eventType), /*existingEvent*/null, objectAction, identified, 
@@ -82,7 +83,7 @@ public class DomainEventHelper {
             final IdentifiedHolder identified,
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final ManagedObject resultAdapter) {
         
         return postEventForAction(phase, 
@@ -98,7 +99,7 @@ public class DomainEventHelper {
             final IdentifiedHolder identified,
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final ManagedObject resultAdapter) {
         
         _Assert.assertTypeIsInstanceOf(eventType, ActionDomainEvent.class);
@@ -125,19 +126,19 @@ public class DomainEventHelper {
                     // should always be the case...
                     event.setActionSemantics(objectAction.getSemantics());
 
-                    final List<ObjectActionParameter> parameters = objectAction.getParameters();
+                    val parameters = objectAction.getParameters();
 
-                    final List<String> parameterNames = parameters.stream()
+                    val parameterNames = parameters.stream()
                             .map(ObjectActionParameter::getName)
-                            .collect(Collectors.toList());
+                            .collect(_Lists.toUnmodifiable());
 
-                    final List<Class<?>> parameterTypes = parameters.stream()
+                    val parameterTypes = parameters.stream()
                             .map(ObjectActionParameter::getSpecification)
                             .map(ObjectSpecification::getCorrespondingClass)
-                            .collect(Collectors.toList());
+                            .collect(_Lists.toUnmodifiable());
 
-                    event.setParameterNames(Collections.unmodifiableList(parameterNames));
-                    event.setParameterTypes(Collections.unmodifiableList(parameterTypes));
+                    event.setParameterNames(parameterNames);
+                    event.setParameterTypes(parameterTypes);
                 }
             }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
index 0582cfb..f8ad455 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionDomainEventFacetAbstract.java
@@ -27,6 +27,7 @@ import org.apache.isis.applib.services.wrapper.events.InteractionEvent;
 import org.apache.isis.applib.services.wrapper.events.UsabilityEvent;
 import org.apache.isis.applib.services.wrapper.events.ValidityEvent;
 import org.apache.isis.applib.services.wrapper.events.VisibilityEvent;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.facetapi.FacetHolder;
 import org.apache.isis.metamodel.facetapi.IdentifiedHolder;
 import org.apache.isis.metamodel.facets.DomainEventHelper;
@@ -141,18 +142,17 @@ implements ActionDomainEventFacet {
         return ((ActionInteractionContext) ic).getObjectAction();
     }
 
-    private static ManagedObject[] argumentAdaptersFrom(
+    private static Can<ManagedObject> argumentAdaptersFrom(
             final InteractionContext<? extends InteractionEvent> ic) {
         
         val contributee = ic.getContributeeWithParamIndex();
 
-        if(contributee!=null) {
-            int paramIndex = contributee.getIndex(); 
+        if(contributee!=null && contributee.getIndex() == 0) {
             ManagedObject adapter = contributee.getValue();
-            return new ManagedObject[]{paramIndex==0 ? adapter : null};
+            return Can.ofSingleton(adapter);    
         }
 
-        return null;
+        return Can.empty();
     }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java
index 3530131..d47138e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacet.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.metamodel.facets.actions.action.invocation;
 
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.facetapi.Facet;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -39,7 +40,7 @@ public interface ActionInvocationFacet extends Facet {
             ObjectAction owningAction,
             ManagedObject targetAdapter,
             ManagedObject mixedInAdapter,  // null for regular or contributed (not mixin) actions
-            ManagedObject[] argumentAdapters,
+            Can<ManagedObject> argumentAdapters,
             InteractionInitiatedBy interactionInitiatedBy);
     
     ObjectSpecification getReturnType();
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
index 0f22089..5fdb4cc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/ActionInvocationFacetForDomainEventAbstract.java
@@ -21,7 +21,6 @@ package org.apache.isis.metamodel.facets.actions.action.invocation;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
@@ -47,10 +46,12 @@ import org.apache.isis.applib.services.metamodel.MetaModelService;
 import org.apache.isis.applib.services.metamodel.MetaModelService.Mode;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.services.registry.ServiceRegistry;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.exceptions.IsisException;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Arrays;
+import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.ioc.BeanSort;
 import org.apache.isis.metamodel.commons.MethodInvocationPreprocessor;
 import org.apache.isis.metamodel.commons.ThrowableExtensions;
@@ -120,7 +121,7 @@ implements ImperativeFacet {
             final ObjectAction owningAction,
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
         final ManagedObject executionResult = 
@@ -153,7 +154,7 @@ implements ImperativeFacet {
             final ObjectAction owningAction,
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final InteractionInitiatedBy interactionInitiatedBy) {
         // similar code in PropertySetterOrClearFacetFDEA
 
@@ -187,18 +188,20 @@ implements ImperativeFacet {
 
             final Object mixinElseRegularPojo = ManagedObject.unwrapPojo(mixinElseRegularAdapter);
 
-            final List<ManagedObject> argumentAdapterList = Arrays.asList(argumentAdapters);
-            final List<Object> argumentPojos = ManagedObject.unwrapPojoListElseEmpty(argumentAdapterList);
+            final List<Object> argumentPojos = argumentAdapters.stream()
+                    .map(ManagedObject::unwrapPojo)
+                    .collect(_Lists.toUnmodifiable());
 
             final String targetMember = targetNameFor(owningAction, mixedInAdapter);
             final String targetClass = CommandUtil.targetClassNameFor(mixinElseRegularAdapter);
 
             final Interaction.ActionInvocation execution =
-                    new Interaction.ActionInvocation(interaction, actionId, mixinElseRegularPojo, argumentPojos, targetMember,
+                    new Interaction.ActionInvocation(
+                            interaction, actionId, mixinElseRegularPojo, argumentPojos, targetMember,
                             targetClass);
             final Interaction.MemberExecutor<Interaction.ActionInvocation> callable =
                     new DomainEventMemberExecutor(
-                            argumentAdapters, targetAdapter, argumentAdapterList, command, owningAction,
+                            argumentAdapters, targetAdapter, argumentAdapters, command, owningAction,
                             mixinElseRegularAdapter, mixedInAdapter, execution);
 
             // sets up startedAt and completedAt on the execution, also manages the execution call graph
@@ -255,15 +258,12 @@ implements ImperativeFacet {
     }
 
     private Object invokeMethodElseFromCache(
-            final ManagedObject targetAdapter, final ManagedObject[] arguments)
+            final ManagedObject targetAdapter, 
+            final Can<ManagedObject> arguments)
                     throws IllegalAccessException, InvocationTargetException {
 
-        final Object[] executionParameters = new Object[arguments.length];
-        for (int i = 0; i < arguments.length; i++) {
-            executionParameters[i] = unwrap(arguments[i]);
-        }
-
-        final Object targetPojo = unwrap(targetAdapter);
+        final Object[] executionParameters = ManagedObject.unwrapPojoArray(arguments);
+        final Object targetPojo = ManagedObject.unwrapPojo(targetAdapter);
 
         final ActionSemanticsFacet semanticsFacet = getFacetHolder().getFacet(ActionSemanticsFacet.class);
         final boolean cacheable = semanticsFacet != null && semanticsFacet.value().isSafeAndRequestCacheable();
@@ -388,10 +388,6 @@ implements ImperativeFacet {
         }
     }
 
-    private static Object unwrap(final ManagedObject adapter) {
-        return adapter == null ? null : adapter.getPojo();
-    }
-    
     private CommandContext getCommandContext() {
         return serviceRegistry.lookupServiceElseFail(CommandContext.class);
     }
@@ -424,9 +420,9 @@ implements ImperativeFacet {
     private final class DomainEventMemberExecutor 
     implements Interaction.MemberExecutor<Interaction.ActionInvocation> {
         
-        private final ManagedObject[] argumentAdapters;
+        private final Can<ManagedObject> argumentAdapters;
         private final ManagedObject targetAdapter;
-        private final List<ManagedObject> argumentAdapterList;
+        private final Can<ManagedObject> argumentAdapterList;
         private final Command command;
         private final ObjectAction owningAction;
         private final ManagedObject mixinElseRegularAdapter;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/CommandUtil.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/CommandUtil.java
index 78874ad..dde8f61 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/CommandUtil.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/action/invocation/CommandUtil.java
@@ -19,9 +19,8 @@
 
 package org.apache.isis.metamodel.facets.actions.action.invocation;
 
-import java.util.List;
-
 import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.metamodel.adapter.ObjectAdapterProvider;
@@ -64,15 +63,15 @@ public class CommandUtil {
     
     public static String argDescriptionFor(
             final ObjectAction owningAction,
-            final ManagedObject[] arguments) {
+            final Can<ManagedObject> arguments) {
         
         val argsBuf = new StringBuilder();
-        List<ObjectActionParameter> parameters = owningAction.getParameters();
-        if(parameters.size() == arguments.length) {
+        val parameters = owningAction.getParameters();
+        if(parameters.size() == arguments.size()) {
             // should be the case
             int i=0;
             for (ObjectActionParameter param : parameters) {
-                CommandUtil.appendParamArg(argsBuf, param, arguments[i++]);
+                CommandUtil.appendParamArg(argsBuf, param, arguments.getOrThrow(i++));
             }
         }
         return argsBuf.toString();
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/ActionValidationFacet.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/ActionValidationFacet.java
index dd00b83..6ec767a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/ActionValidationFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/ActionValidationFacet.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.metamodel.facets.actions.validate;
 
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.facetapi.Facet;
 import org.apache.isis.metamodel.facets.actions.action.invocation.ActionInvocationFacet;
 import org.apache.isis.metamodel.interactions.ValidatingInteractionAdvisor;
@@ -43,5 +44,5 @@ public interface ActionValidationFacet extends Facet, ValidatingInteractionAdvis
     /**
      * Reason why the validation has failed, or <tt>null</tt> if okay.
      */
-    public String invalidReason(ManagedObject target, ManagedObject[] arguments);
+    public String invalidReason(ManagedObject target, Can<ManagedObject> arguments);
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
index 3b7c053..6be2414 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/facets/actions/validate/method/ActionValidationFacetViaMethod.java
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import org.apache.isis.applib.services.i18n.TranslatableString;
 import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.facetapi.FacetHolder;
 import org.apache.isis.metamodel.facets.ImperativeFacet;
 import org.apache.isis.metamodel.facets.actions.validate.ActionValidationFacetAbstract;
@@ -59,7 +60,7 @@ public class ActionValidationFacetViaMethod extends ActionValidationFacetAbstrac
     }
 
     @Override
-    public String invalidReason(final ManagedObject owningAdapter, final ManagedObject[] proposedArgumentAdapters) {
+    public String invalidReason(final ManagedObject owningAdapter, final Can<ManagedObject> proposedArgumentAdapters) {
         final Object returnValue = ManagedObject.InvokeUtil.invoke(method, owningAdapter, proposedArgumentAdapters);
         if(returnValue instanceof String) {
             return (String) returnValue;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionArgValidityContext.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionArgValidityContext.java
index f86c051..cb87a49 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionArgValidityContext.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionArgValidityContext.java
@@ -21,6 +21,7 @@ package org.apache.isis.metamodel.interactions;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.wrapper.events.ActionArgumentEvent;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.consent.InteractionContextType;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -28,22 +29,24 @@ import org.apache.isis.metamodel.spec.feature.ObjectAction;
 
 import static org.apache.isis.metamodel.spec.ManagedObject.unwrapPojo;
 
+import lombok.Getter;
+
 /**
  * See {@link InteractionContext} for overview; analogous to
  * {@link ActionArgumentEvent}.
  */
 public class ActionArgValidityContext extends ValidityContext<ActionArgumentEvent> implements ProposedHolder, ActionInteractionContext {
 
-    private final ObjectAction objectAction;
-    private final ManagedObject[] args;
-    private final int position;
-    private final ManagedObject proposed;
+    @Getter(onMethod = @__(@Override)) private final ObjectAction objectAction;
+    @Getter(onMethod = @__(@Override)) private final ManagedObject proposed;
+    @Getter private final Can<ManagedObject> args;
+    @Getter private final int position;
 
     public ActionArgValidityContext(
             final ManagedObject targetAdapter,
             final ObjectAction objectAction,
             final Identifier id,
-            final ManagedObject[] args,
+            final Can<ManagedObject> args,
             final int position,
             final InteractionInitiatedBy interactionInitiatedBy) {
         super(InteractionContextType.ACTION_PROPOSED_ARGUMENT, targetAdapter, id, interactionInitiatedBy);
@@ -51,25 +54,7 @@ public class ActionArgValidityContext extends ValidityContext<ActionArgumentEven
 
         this.args = args;
         this.position = position;
-        this.proposed = args[position];
-    }
-
-    @Override
-    public ObjectAction getObjectAction() {
-        return objectAction;
-    }
-
-    public ManagedObject[] getArgs() {
-        return args;
-    }
-
-    public int getPosition() {
-        return position;
-    }
-
-    @Override
-    public ManagedObject getProposed() {
-        return proposed;
+        this.proposed = args.getOrThrow(position);
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionValidityContext.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionValidityContext.java
index 47c790d..8f45f75 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionValidityContext.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/interactions/ActionValidityContext.java
@@ -21,6 +21,7 @@ package org.apache.isis.metamodel.interactions;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.services.wrapper.events.ActionInvocationEvent;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.consent.InteractionContextType;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -28,38 +29,35 @@ import org.apache.isis.metamodel.spec.feature.ObjectAction;
 
 import static org.apache.isis.metamodel.spec.ManagedObject.unwrapPojo;
 
+import lombok.Getter;
+
 /**
  * See {@link InteractionContext} for overview; analogous to
  * {@link ActionInvocationEvent}.
  */
-public class ActionValidityContext extends ValidityContext<ActionInvocationEvent> implements ActionInteractionContext {
+public class ActionValidityContext
+extends ValidityContext<ActionInvocationEvent> 
+implements ActionInteractionContext {
 
-    private final ObjectAction objectAction;
-    private final ManagedObject[] args;
+    @Getter(onMethod = @__(@Override)) private final ObjectAction objectAction;
+    @Getter private final Can<ManagedObject> args;
 
     public ActionValidityContext(
             final ManagedObject targetAdapter,
             final ObjectAction objectAction,
             final Identifier id,
-            final ManagedObject[] args,
+            final Can<ManagedObject> args,
             final InteractionInitiatedBy interactionInitiatedBy) {
+        
         super(InteractionContextType.ACTION_INVOKE, targetAdapter, id, interactionInitiatedBy);
         this.objectAction = objectAction;
         this.args = args;
     }
 
     @Override
-    public ObjectAction getObjectAction() {
-        return objectAction;
-    }
-
-    public ManagedObject[] getArgs() {
-        return args;
-    }
-
-    @Override
     public ActionInvocationEvent createInteractionEvent() {
-        return new ActionInvocationEvent(unwrapPojo(getTarget()), getIdentifier(), ManagedObject.unwrapPojoArray(getArgs()));
+        return new ActionInvocationEvent(
+                unwrapPojo(getTarget()), getIdentifier(), ManagedObject.unwrapPojoArray(getArgs()));
     }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManager.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManager.java
index f5f6d85..01d7a66 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManager.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManager.java
@@ -84,10 +84,9 @@ public interface ObjectManager {
         getObjectRefresher().refreshObject(managedObject);
     }
     
-    @Nullable
     public default ManagedObject adapt(@Nullable Object pojo) {
         if(pojo==null) {
-            return null; // don't propagate null into ManagedObject, null has no type 
+            return ManagedObject.empty(); 
         }
         return ManagedObject.of(this::loadSpecification, pojo);
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManagerDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManagerDefault.java
index cb2fbd0..acfe2dc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManagerDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/objectmanager/ObjectManagerDefault.java
@@ -22,12 +22,12 @@ import javax.annotation.PostConstruct;
 import javax.inject.Inject;
 import javax.inject.Named;
 
-import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.annotation.Primary;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.metamodel.context.MetaModelContext;
 import org.apache.isis.metamodel.objectmanager.create.ObjectCreator;
 import org.apache.isis.metamodel.objectmanager.identify.ObjectIdentifier;
@@ -35,7 +35,6 @@ import org.apache.isis.metamodel.objectmanager.load.ObjectLoader;
 import org.apache.isis.metamodel.objectmanager.refresh.ObjectRefresher;
 
 import lombok.Getter;
-import lombok.extern.log4j.Log4j2;
 import lombok.val;
 
 /**
@@ -48,7 +47,6 @@ import lombok.val;
 @Order(OrderPrecedence.HIGH)
 @Primary
 @Qualifier("DEFAULT")
-@Log4j2
 public class ObjectManagerDefault implements ObjectManager {
     
     @Inject @Getter(onMethod = @__(@Override)) private MetaModelContext metaModelContext;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/postprocessors/param/DeriveFacetsPostProcessor.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/postprocessors/param/DeriveFacetsPostProcessor.java
index 135850e..51dcb61 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/postprocessors/param/DeriveFacetsPostProcessor.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/postprocessors/param/DeriveFacetsPostProcessor.java
@@ -20,7 +20,6 @@
 package org.apache.isis.metamodel.postprocessors.param;
 
 import java.lang.reflect.Method;
-import java.util.Collections;
 import java.util.List;
 import java.util.stream.Stream;
 
@@ -138,7 +137,7 @@ implements ObjectSpecificationPostProcessor, MetaModelContextAware {
         objectActions.forEach(objectAction -> {
 
             // ... for each action parameter
-            final List<ObjectActionParameter> parameters = objectAction.getParameters();
+            val parameters = objectAction.getParameters();
 
             for (final ObjectActionParameter parameter : parameters) {
 
@@ -193,15 +192,10 @@ implements ObjectSpecificationPostProcessor, MetaModelContextAware {
             .filter(ObjectAction.Predicates.associatedWith(collection))
             .forEach(action->{
 
-                final List<ObjectActionParameter> parameters = action.getParameters();
+                val parameters = action.getParameters();
 
-                final List<ObjectActionParameter> compatibleCollectionParams =
-                        Collections.unmodifiableList(
-                                _Lists.filter(parameters, whetherCollectionParamOfType));
-
-                final List<ObjectActionParameter> compatibleScalarParams = 
-                        Collections.unmodifiableList(
-                                _Lists.filter(parameters, whetherScalarParamOfType));
+                val compatibleCollectionParams = parameters.filter(whetherCollectionParamOfType);
+                val compatibleScalarParams = parameters.filter(whetherScalarParamOfType);
 
                 // for collection parameters, install an defaults facet (if there isn't one already)
                 // this will cause the UI to render the collection with toggleboxes
@@ -409,11 +403,11 @@ implements ObjectSpecificationPostProcessor, MetaModelContextAware {
         // this loop within the outer loop (for every param) is really weird,
         // but arises from porting the old facet factory
         final ObjectAction objectAction = parameter.getAction();
-        final List<ObjectSpecification> parameterSpecs = objectAction.getParameterTypes();
+        val parameterSpecs = objectAction.getParameterTypes();
         final DefaultedFacet[] parameterTypeDefaultedFacets = new DefaultedFacet[parameterSpecs.size()];
         boolean hasAtLeastOneDefault = false;
         for (int i = 0; i < parameterSpecs.size(); i++) {
-            final ObjectSpecification parameterSpec = parameterSpecs.get(i);
+            final ObjectSpecification parameterSpec = parameterSpecs.getOrThrow(i);
             parameterTypeDefaultedFacets[i] = parameterSpec.getFacet(DefaultedFacet.class);
             hasAtLeastOneDefault = hasAtLeastOneDefault | (parameterTypeDefaultedFacets[i] != null);
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/command/CommandDtoServiceInternal.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/command/CommandDtoServiceInternal.java
index 06ea486..a3c3750 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/command/CommandDtoServiceInternal.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/command/CommandDtoServiceInternal.java
@@ -21,6 +21,7 @@ package org.apache.isis.metamodel.services.command;
 import java.util.List;
 
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.spec.ManagedObject;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.metamodel.spec.feature.OneToOneAssociation;
@@ -44,7 +45,7 @@ public interface CommandDtoServiceInternal {
     CommandDto asCommandDto(
             final List<ManagedObject> targetAdapters,
             final ObjectAction objectAction,
-            final ManagedObject[] argAdapters);
+            final Can<ManagedObject> argAdapters);
 
     /**
      * Returns a JAXB DTO (hence convertible to XML) that represents the intention to edit (set or clear) a property on
@@ -60,7 +61,7 @@ public interface CommandDtoServiceInternal {
     void addActionArgs(
             final ObjectAction objectAction,
             final ActionDto actionDto,
-            final ManagedObject[] argAdapters);
+            final Can<ManagedObject> argAdapters);
 
     @Programmatic
     void addPropertyValue(
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/homepage/HomePageAction.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/homepage/HomePageAction.java
index d5a3730..a7eeb68 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/homepage/HomePageAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/homepage/HomePageAction.java
@@ -19,6 +19,7 @@
 package org.apache.isis.metamodel.services.homepage;
 
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.spec.ManagedObject;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
@@ -39,7 +40,7 @@ public final class HomePageAction {
     public Object getHomePagePojo() {
 
         final ManagedObject mixedInAdapter = null;
-        final ManagedObject[] parameters = {};
+        final Can<ManagedObject> parameters = Can.empty();
 
         final ManagedObject resultAdapter = objectAction.executeWithRuleChecking(
                 objectAdapter, mixedInAdapter, parameters,
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/ixn/InteractionDtoServiceInternal.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/ixn/InteractionDtoServiceInternal.java
index b542a91..9dc0b96 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/ixn/InteractionDtoServiceInternal.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/ixn/InteractionDtoServiceInternal.java
@@ -18,9 +18,8 @@
  */
 package org.apache.isis.metamodel.services.ixn;
 
-import java.util.List;
-
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.spec.ManagedObject;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.metamodel.spec.feature.OneToOneAssociation;
@@ -33,7 +32,7 @@ public interface InteractionDtoServiceInternal {
     ActionInvocationDto asActionInvocationDto(
             ObjectAction objectAction,
             ManagedObject targetAdapter,
-            List<ManagedObject> argumentAdapters);
+            Can<ManagedObject> argumentAdapters);
 
     @Programmatic
     PropertyEditDto asPropertyEditDto(
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/DomainMemberDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/DomainMemberDefault.java
index ed471b5..ba0c7f7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/DomainMemberDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/DomainMemberDefault.java
@@ -20,7 +20,6 @@ package org.apache.isis.metamodel.services.metamodel;
 
 import java.util.Arrays;
 import java.util.Comparator;
-import java.util.List;
 import java.util.SortedSet;
 import java.util.stream.Collectors;
 
@@ -60,6 +59,8 @@ import org.apache.isis.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.metamodel.specloader.specimpl.ContributeeMember;
 import org.apache.isis.metamodel.specloader.specimpl.MixedInMember;
 
+import lombok.val;
+
 @XmlRootElement(name = "domain-member")
 @XmlAccessorType(XmlAccessType.PROPERTY)
 public class DomainMemberDefault implements DomainMember {
@@ -180,7 +181,7 @@ public class DomainMemberDefault implements DomainMember {
         case COLLECTION:
             return "";
         default:
-            final List<ObjectActionParameter> parameters = this.action.getParameters();
+            val parameters = this.action.getParameters();
             final SortedSet<String> interpretations = _Sets.newTreeSet();
             for (ObjectActionParameter param : parameters) {
                 final ActionParameterChoicesFacet facet = param.getFacet(ActionParameterChoicesFacet.class);
@@ -199,7 +200,7 @@ public class DomainMemberDefault implements DomainMember {
         } else if(memberType == MemberType.COLLECTION) {
             return "";
         } else {
-            final List<ObjectActionParameter> parameters = this.action.getParameters();
+            val parameters = this.action.getParameters();
             final SortedSet<String> interpretations = _Sets.newTreeSet();
             for (ObjectActionParameter param : parameters) {
                 final ActionParameterAutoCompleteFacet facet = param.getFacet(ActionParameterAutoCompleteFacet.class);
@@ -216,7 +217,7 @@ public class DomainMemberDefault implements DomainMember {
         } else if(memberType == MemberType.COLLECTION) {
             return "";
         } else {
-            final List<ObjectActionParameter> parameters = this.action.getParameters();
+            val parameters = this.action.getParameters();
             final SortedSet<String> interpretations = _Sets.newTreeSet();
             for (ObjectActionParameter param : parameters) {
                 final ActionParameterDefaultsFacet facet = param.getFacet(ActionParameterDefaultsFacet.class);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/MetaModelExporter.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/MetaModelExporter.java
index f2d80a8..5a1d3d9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/MetaModelExporter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/services/metamodel/MetaModelExporter.java
@@ -326,7 +326,7 @@ class MetaModelExporter {
 
         addFacets(oa, actionType.getFacets(), config);
 
-        final List<ObjectActionParameter> parameters = oa.getParameters();
+        val parameters = oa.getParameters();
         final List<Param> params = actionType.getParams().getParam();
         for (final ObjectActionParameter parameter : parameters) {
             params.add(asXsdType(parameter, domainClassByObjectSpec, config));
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ManagedObject.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ManagedObject.java
index 4577c8f..3b80096 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ManagedObject.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/ManagedObject.java
@@ -705,7 +705,25 @@ public interface ManagedObject {
         return adapter.getSpecification().getBeanSort().isCollection();
     }
 
+    static class EmptyUtil {
+        private final static ManagedObject EMPTY = new ManagedObject() {
 
+            @Override
+            public ObjectSpecification getSpecification() {
+                throw _Exceptions.unsupportedOperation();
+            }
+
+            @Override
+            public Object getPojo() {
+                return null;
+            }
+            
+        };
+    }
+    
+    static ManagedObject empty() {
+        return EmptyUtil.EMPTY;
+    }
 
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAction.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAction.java
index c5ce02b..e4f9d6c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAction.java
@@ -35,12 +35,13 @@ import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.value.Blob;
 import org.apache.isis.applib.value.Clob;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Sets;
-import org.apache.isis.metamodel.context.MetaModelContext;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.metamodel.context.MetaModelContext;
 import org.apache.isis.metamodel.facets.actions.action.associateWith.AssociatedWithFacet;
 import org.apache.isis.metamodel.facets.actions.position.ActionPositionFacet;
 import org.apache.isis.metamodel.facets.all.named.NamedFacet;
@@ -108,7 +109,7 @@ public interface ObjectAction extends ObjectMember {
     ManagedObject executeWithRuleChecking(
             final ManagedObject target,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] parameters,
+            final Can<ManagedObject> parameters,
             final InteractionInitiatedBy interactionInitiatedBy,
             final Where where) throws AuthorizationException;
 
@@ -123,7 +124,7 @@ public interface ObjectAction extends ObjectMember {
     ManagedObject execute(
             ManagedObject targetAdapter,
             ManagedObject mixedInAdapter,
-            ManagedObject[] parameters,
+            Can<ManagedObject> parameters,
             final InteractionInitiatedBy interactionInitiatedBy);
 
 
@@ -143,17 +144,17 @@ public interface ObjectAction extends ObjectMember {
      */
     Consent isProposedArgumentSetValid(
             ManagedObject object,
-            ManagedObject[] proposedArguments,
-            final InteractionInitiatedBy interactionInitiatedBy);
+            Can<ManagedObject> proposedArguments,
+            InteractionInitiatedBy interactionInitiatedBy);
 
     Consent isEachIndividualArgumentValid(
             ManagedObject objectAdapter,
-            ManagedObject[] proposedArguments,
+            Can<ManagedObject> proposedArguments,
             InteractionInitiatedBy interactionInitiatedBy);
 
     Consent isArgumentSetValid(
             ManagedObject objectAdapter,
-            ManagedObject[] proposedArguments,
+            Can<ManagedObject> proposedArguments,
             InteractionInitiatedBy interactionInitiatedBy);
 
 
@@ -173,20 +174,19 @@ public interface ObjectAction extends ObjectMember {
      *
      * @return
      */
-    List<ObjectActionParameter> getParameters();
+    Can<ObjectActionParameter> getParameters();
 
     /**
      * Returns the {@link ObjectSpecification type} of each of the {@link #getParameters() parameters}.
      */
-    List<ObjectSpecification> getParameterTypes();
+    Can<ObjectSpecification> getParameterTypes();
 
     /**
      * Returns set of parameter information matching the supplied filter.
      *
      * @return
      */
-    List<ObjectActionParameter> getParameters(
-            Predicate<ObjectActionParameter> predicate);
+    Can<ObjectActionParameter> getParameters(Predicate<ObjectActionParameter> predicate);
 
     /**
      * Returns the parameter with provided id.
@@ -215,13 +215,13 @@ public interface ObjectAction extends ObjectMember {
     /**
      * Returns the defaults references/values to be used for the action.
      */
-    ManagedObject[] getDefaults(ManagedObject target);
+    Can<ManagedObject> getDefaults(ManagedObject target);
 
     /**
      * Returns a list of possible references/values for each parameter, which
      * the user can choose from.
      */
-    ManagedObject[][] getChoices(
+    Can<Can<ManagedObject>> getChoices(
             final ManagedObject target,
             final InteractionInitiatedBy interactionInitiatedBy);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionContainer.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionContainer.java
index fbe9c5b..df5c0ee 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionContainer.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionContainer.java
@@ -20,10 +20,10 @@
 package org.apache.isis.metamodel.spec.feature;
 
 import java.util.Collection;
-import java.util.List;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.Identifier;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.spec.ActionType;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
 
@@ -34,7 +34,7 @@ public interface ObjectActionContainer {
     /**
      * Returns the action of the specified type with the specified signature.
      */
-    ObjectAction getObjectAction(ActionType type, String id, List<ObjectSpecification> parameters);
+    ObjectAction getObjectAction(ActionType type, String id, Can<ObjectSpecification> parameters);
 
     /**
      * Get the action object represented by the specified identity string.
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionParameter.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionParameter.java
index 93c3ad3..85abee4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionParameter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectActionParameter.java
@@ -75,7 +75,7 @@ public interface ObjectActionParameter extends ObjectFeature, CurrentHolder {
     // internal API
     ActionArgValidityContext createProposedArgumentInteractionContext(
             ManagedObject targetObject,
-            ManagedObject[] args,
+            Can<ManagedObject> args,
             int position,
             InteractionInitiatedBy interactionInitiatedBy);
 
@@ -90,7 +90,7 @@ public interface ObjectActionParameter extends ObjectFeature, CurrentHolder {
      * Returns a list of possible references/values for this parameter, which the
      * user can choose from, based on the input search argument.
      */
-    ManagedObject[] getAutoComplete(
+    Can<ManagedObject> getAutoComplete(
             ManagedObject adapter,
             Can<ManagedObject> pendingArgs,
             String searchArg,
@@ -109,7 +109,7 @@ public interface ObjectActionParameter extends ObjectFeature, CurrentHolder {
      * Returns a list of possible references/values for this parameter, which the
      * user can choose from.
      */
-    ManagedObject[] getChoices(
+    Can<ManagedObject> getChoices(
             ManagedObject adapter,
             Can<ManagedObject> pendingArgs,
             InteractionInitiatedBy interactionInitiatedBy);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAssociation.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAssociation.java
index 499cebe..d782f6f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAssociation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/feature/ObjectAssociation.java
@@ -29,9 +29,11 @@ import java.util.stream.Stream;
 import javax.enterprise.inject.Vetoed;
 
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
+import org.apache.isis.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.facetapi.Facet;
 import org.apache.isis.metamodel.facets.WhereValueFacet;
@@ -89,7 +91,7 @@ public interface ObjectAssociation extends ObjectMember, CurrentHolder {
      * Returns a list of possible references/values for this field, which the
      * user can choose from.
      */
-    public ManagedObject[] getChoices(
+    public Can<ManagedObject> getChoices(
             ManagedObject object,
             InteractionInitiatedBy interactionInitiatedBy);
 
@@ -103,7 +105,7 @@ public interface ObjectAssociation extends ObjectMember, CurrentHolder {
      * Returns a list of possible references/values for this field, which the
      * user can choose from, based on the provided search argument.
      */
-    public ManagedObject[] getAutoComplete(
+    public Can<ManagedObject> getAutoComplete(
             ManagedObject object,
             String searchArg,
             InteractionInitiatedBy interactionInitiatedBy);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ContributeeMember.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ContributeeMember.java
index f6f836e..9d8271a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ContributeeMember.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ContributeeMember.java
@@ -37,7 +37,7 @@ public interface ContributeeMember extends ObjectMember {
     /**
      * Which parameter of the original contributed action was contributed to (zero-based).
      */
-    int getContributeeParamPosition();
+    int getContributeeParamIndex();
 
     ObjectSpecification getServiceContributedBy();
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionContributee.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionContributee.java
index 51f00c3..fedab95 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionContributee.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionContributee.java
@@ -18,11 +18,11 @@
  */
 package org.apache.isis.metamodel.specloader.specimpl;
 
-import java.util.Arrays;
 import java.util.List;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -39,11 +39,13 @@ import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.metamodel.spec.feature.ObjectActionParameter;
 
+import lombok.val;
+
 public class ObjectActionContributee extends ObjectActionDefault implements ContributeeMember {
 
     private final Object servicePojo;
     private final ObjectActionDefault serviceAction;
-    private final int contributeeParam;
+    private final int contributeeParamIndex;
     private final ObjectSpecification contributeeType;
 
     /**
@@ -65,7 +67,7 @@ public class ObjectActionContributee extends ObjectActionDefault implements Cont
         this.servicePojo = servicePojo;
         this.serviceAction = serviceAction;
         this.contributeeType = contributeeType;
-        this.contributeeParam = contributeeParam;
+        this.contributeeParamIndex = contributeeParam;
 
         // copy over facets from contributed to own.
         FacetUtil.copyFacets(serviceAction.getFacetedMethod(), facetHolder);
@@ -87,41 +89,33 @@ public class ObjectActionContributee extends ObjectActionDefault implements Cont
         return serviceAction.getParameterCount() - 1;
     }
 
-    public int getContributeeParam() {
-        return contributeeParam;
-    }
-
     @Override
     public boolean isContributedBy(final ObjectAction serviceAction) {
         return serviceAction == this.serviceAction;
     }
 
     @Override
-    public int getContributeeParamPosition() {
-        return contributeeParam;
+    public int getContributeeParamIndex() {
+        return contributeeParamIndex;
     }
 
     @Override
-    protected synchronized List<ObjectActionParameter> determineParameters() {
-        if (parameters != null) {
-            // because possible race condition (caller isn't synchronized)
-            return parameters;
-        }
+    protected synchronized Can<ObjectActionParameter> determineParameters() {
 
-        final List<ObjectActionParameter> serviceParameters = serviceAction.getParameters();
+        val serviceParameters = serviceAction.getParameters();
         final List<FacetedMethodParameter> paramPeers = getFacetedMethod().getParameters(); //side effects?
 
         final List<ObjectActionParameter> contributeeParameters = _Lists.newArrayList();
         int contributeeParamNum = 0;
 
         for (int serviceParamNum = 0; serviceParamNum < serviceParameters.size(); serviceParamNum++ ) {
-            if(serviceParamNum == contributeeParam) {
+            if(serviceParamNum == contributeeParamIndex) {
                 // skip so is omitted from the Contributed action
                 continue;
             }
 
             final ObjectActionParameterAbstract serviceParameter =
-                    (ObjectActionParameterAbstract) serviceParameters.get(serviceParamNum);
+                    (ObjectActionParameterAbstract) serviceParameters.getOrThrow(serviceParamNum);
 
             final ObjectActionParameterContributee contributedParam =
                     serviceParameter.getPeer().getFeatureType() == FeatureType.ACTION_PARAMETER_SCALAR
@@ -134,7 +128,7 @@ public class ObjectActionContributee extends ObjectActionDefault implements Cont
 
                             contributeeParamNum++;
         }
-        return contributeeParameters;
+        return Can.ofCollection(contributeeParameters);
     }
 
     @Override
@@ -144,7 +138,7 @@ public class ObjectActionContributee extends ObjectActionDefault implements Cont
             Where where) {
         final VisibilityContext<?> ic = serviceAction.createVisibleInteractionContext(getServiceAdapter(),
                 interactionInitiatedBy, where);
-        ic.putContributee(this.contributeeParam, contributee);
+        ic.putContributee(this.contributeeParamIndex, contributee);
         return InteractionUtils.isVisibleResult(this, ic).createConsent();
     }
 
@@ -154,69 +148,77 @@ public class ObjectActionContributee extends ObjectActionDefault implements Cont
             final InteractionInitiatedBy interactionInitiatedBy, final Where where) {
         final UsabilityContext<?> ic = serviceAction.createUsableInteractionContext(getServiceAdapter(),
                 interactionInitiatedBy, where);
-        ic.putContributee(this.contributeeParam, contributee);
+        ic.putContributee(this.contributeeParamIndex, contributee);
         return InteractionUtils.isUsableResult(this, ic).createConsent();
     }
 
     @Override
-    public ManagedObject[] getDefaults(final ManagedObject target) {
-        final ManagedObject[] contributorDefaults = serviceAction.getDefaults(getServiceAdapter());
-        return removeElementFromArray(contributorDefaults, contributeeParam, new ManagedObject[]{});
+    public Can<ManagedObject> getDefaults(final ManagedObject target) {
+        val contributorDefaults = serviceAction.getDefaults(getServiceAdapter());
+        return contributorDefaults.remove(contributeeParamIndex);
     }
 
     @Override
-    public ManagedObject[][] getChoices(
+    public Can<Can<ManagedObject>> getChoices(
             final ManagedObject target,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        final ManagedObject[][] serviceChoices = serviceAction.getChoices(getServiceAdapter(),
-                interactionInitiatedBy);
-        return removeElementFromArray(serviceChoices, contributeeParam, new ManagedObject[][]{});
+        val serviceChoices = serviceAction.getChoices(getServiceAdapter(), interactionInitiatedBy);
+        return serviceChoices.remove(contributeeParamIndex);
     }
 
     @Override
     public Consent isProposedArgumentSetValid(
             final ManagedObject contributee,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        final ManagedObject[] serviceArguments = argsPlusContributee(contributee, proposedArguments);
-        return serviceAction.isProposedArgumentSetValid(getServiceAdapter(), serviceArguments, interactionInitiatedBy);
+        
+        val serviceArguments = argsPlusContributee(contributee, proposedArguments);
+        return serviceAction
+                .isProposedArgumentSetValid(getServiceAdapter(), serviceArguments, interactionInitiatedBy);
     }
 
     @Override
     public Consent isEachIndividualArgumentValid(
             final ManagedObject contributee,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        final ManagedObject[] serviceArguments = argsPlusContributee(contributee, proposedArguments);
-        return serviceAction.isEachIndividualArgumentValid(getServiceAdapter(), serviceArguments, interactionInitiatedBy);
+        
+        val serviceArguments = argsPlusContributee(contributee, proposedArguments);
+        return serviceAction
+                .isEachIndividualArgumentValid(getServiceAdapter(), serviceArguments, interactionInitiatedBy);
     }
 
     @Override
     public Consent isArgumentSetValid(
             final ManagedObject contributee,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        final ManagedObject[] serviceArguments = argsPlusContributee(contributee, proposedArguments);
-        return serviceAction.isArgumentSetValid(getServiceAdapter(), serviceArguments, interactionInitiatedBy);
+        
+        val serviceArguments = argsPlusContributee(contributee, proposedArguments);
+        return serviceAction
+                .isArgumentSetValid(getServiceAdapter(), serviceArguments, interactionInitiatedBy);
     }
 
     @Override
     public ManagedObject execute(
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
         setupCommand(targetAdapter, argumentAdapters);
 
-        final ManagedObject[] serviceArguments = argsPlusContributee(targetAdapter, argumentAdapters);
+        val serviceArguments = argsPlusContributee(targetAdapter, argumentAdapters);
         return serviceAction.executeInternal(
                 getServiceAdapter(), mixedInAdapter, serviceArguments, interactionInitiatedBy);
     }
 
 
-    private ManagedObject[] argsPlusContributee(final ManagedObject contributee, final ManagedObject[] arguments) {
-        return addElementToArray(arguments, contributeeParam, contributee, new ManagedObject[]{});
+    private Can<ManagedObject> argsPlusContributee(
+            final ManagedObject contributee, 
+            final Can<ManagedObject> arguments) {
+        
+        return arguments.add(contributeeParamIndex, contributee);
     }
 
     // //////////////////////////////////////
@@ -240,17 +242,17 @@ public class ObjectActionContributee extends ObjectActionDefault implements Cont
 
     // //////////////////////////////////////
 
-    static <T> T[] addElementToArray(T[] array, final int n, final T element, final T[] type) {
-        List<T> list = _Lists.newArrayList(Arrays.asList(array));
-        list.add(n, element);
-        return list.toArray(type);
-    }
-
-    static <T> T[] removeElementFromArray(T[] array, int n, T[] t) {
-        List<T> list = _Lists.newArrayList(Arrays.asList(array));
-        list.remove(n);
-        return list.toArray(t);
-    }
+//    static <T> T[] addElementToArray(T[] array, final int n, final T element, final T[] type) {
+//        List<T> list = _Lists.newArrayList(Arrays.asList(array));
+//        list.add(n, element);
+//        return list.toArray(type);
+//    }
+//
+//    static <T> T[] removeElementFromArray(T[] array, int n, T[] t) {
+//        List<T> list = _Lists.newArrayList(Arrays.asList(array));
+//        list.remove(n);
+//        return list.toArray(t);
+//    }
 
     public ManagedObject getServiceAdapter() {
         return getObjectManager().adapt(servicePojo);
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionDefault.java
index c0e43e1..5ea211f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionDefault.java
@@ -19,6 +19,7 @@
 
 package org.apache.isis.metamodel.specloader.specimpl;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -33,6 +34,7 @@ import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.exceptions.UnknownTypeException;
 import org.apache.isis.commons.internal._Constants;
+import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -78,10 +80,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
     // -- fields
 
-    /**
-     * Lazily initialized by {@link #getParameters()} (so don't use directly!)
-     */
-    List<ObjectActionParameter> parameters;
+    private final _Lazy<Can<ObjectActionParameter>> parameters = _Lazy.threadSafe(this::determineParameters);
 
     // -- constructors
 
@@ -155,31 +154,17 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
         return getFacetedMethod().getParameters().size();
     }
 
-
-    /**
-     * Build lazily by {@link #getParameters()}.
-     *
-     * <p>
-     * Although this is lazily loaded, the method is also <tt>synchronized</tt>
-     * so there shouldn't be any thread race conditions.
-     */
     @Override
-    public List<ObjectActionParameter> getParameters() {
-        if (parameters == null) {
-            parameters = determineParameters();
-        }
-        return parameters;
+    public Can<ObjectActionParameter> getParameters() {
+        return parameters.get();
     }
 
-    protected synchronized List<ObjectActionParameter> determineParameters() {
-        if (parameters != null) {
-            // because possible race condition (caller isn't synchronized)
-            return parameters;
-        }
-        final int parameterCount = getParameterCount();
-        final List<FacetedMethodParameter> paramPeers = getFacetedMethod().getParameters();
+    protected Can<ObjectActionParameter> determineParameters() {
+        
+        val parameterCount = getParameterCount();
+        val paramPeers = getFacetedMethod().getParameters();
 
-        final List<ObjectActionParameter> parameters = _Lists.newArrayList();
+        val parameters = _Lists.<ObjectActionParameter>newArrayList();
         for (int paramNum = 0; paramNum < parameterCount; paramNum++) {
             final FacetedMethodParameter paramPeer = paramPeers.get(paramNum);
 
@@ -193,61 +178,44 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
                     parameters.add(parameter);
         }
-        return parameters;
+        return Can.ofCollection(parameters);
     }
 
     @Override
-    public List<ObjectSpecification> getParameterTypes() {
-        final List<ObjectSpecification> parameterTypes = _Lists.newArrayList();
-        final List<ObjectActionParameter> parameters = getParameters();
-        for (final ObjectActionParameter parameter : parameters) {
-            parameterTypes.add(parameter.getSpecification());
-        }
+    public Can<ObjectSpecification> getParameterTypes() {
+        val parameters = getParameters();
+        val parameterTypes = parameters.map(ObjectActionParameter::getSpecification);
         return parameterTypes;
     }
 
     @Override
     public ObjectActionParameter getParameterById(final String paramId) {
-        final List<ObjectActionParameter> allParameters = getParameters();
-        for (int i = 0; i < allParameters.size(); i++) {
-            final ObjectActionParameter param = allParameters.get(i);
-            if (Objects.equals(paramId, param.getId())) {
-                return param;
-            }
-        }
-        return null;
+        return getParameters().stream()
+                .filter(param->Objects.equals(paramId, param.getId()))
+                .findAny()
+                .orElse(null);
     }
 
     @Override
     public ObjectActionParameter getParameterByName(final String paramName) {
-        final List<ObjectActionParameter> allParameters = getParameters();
-        for (int i = 0; i < allParameters.size(); i++) {
-            final ObjectActionParameter param = allParameters.get(i);
-            if (Objects.equals(paramName, param.getName())) {
-                return param;
-            }
-        }
-        return null;
+        return getParameters().stream()
+                .filter(param->Objects.equals(paramName, param.getName()))
+                .findAny()
+                .orElse(null);
     }
 
     @Override
-    public List<ObjectActionParameter> getParameters(final Predicate<ObjectActionParameter> predicate) {
-        final List<ObjectActionParameter> allParameters = getParameters();
-        final List<ObjectActionParameter> selectedParameters = _Lists.newArrayList();
-        for (int i = 0; i < allParameters.size(); i++) {
-            if (predicate.test(allParameters.get(i))) {
-                selectedParameters.add(allParameters.get(i));
-            }
-        }
-        return selectedParameters;
+    public Can<ObjectActionParameter> getParameters(final Predicate<ObjectActionParameter> filter) {
+        return getParameters().filter(filter);
     }
 
     ObjectActionParameter getParameter(final int position) {
-        final List<ObjectActionParameter> parameters = getParameters();
+        val parameters = getParameters();
         if (position >= parameters.size()) {
-            throw new IllegalArgumentException("getParameter(int): only " + parameters.size() + " parameters, position=" + position);
+            throw new IllegalArgumentException(
+                    "getParameter(int): only " + parameters.size() + " parameters, position=" + position);
         }
-        return parameters.get(position);
+        return parameters.getOrThrow(position);
     }
 
 
@@ -286,7 +254,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     @Override
     public Consent isProposedArgumentSetValid(
             final ManagedObject targetObject,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
         final InteractionResultSet resultSet = new InteractionResultSet();
@@ -316,7 +284,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     @Override
     public Consent isEachIndividualArgumentValid(
             final ManagedObject objectAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
         final InteractionResultSet resultSet = new InteractionResultSet();
@@ -328,16 +296,17 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
     private void validateArgumentsIndividually(
             final ManagedObject objectAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy,
             final InteractionResultSet resultSet) {
-        final List<ObjectActionParameter> actionParameters = getParameters();
+        
+        val actionParameters = getParameters();
         if (proposedArguments != null) {
-            for (int i = 0; i < proposedArguments.length; i++) {
-                final ValidityContext<?> ic =
-                        actionParameters.get(i).createProposedArgumentInteractionContext(
-                                objectAdapter, proposedArguments, i, interactionInitiatedBy
-                                );
+            for (int i = 0; i < proposedArguments.size(); i++) {
+                final ValidityContext<?> ic = actionParameters.getOrThrow(i)
+                        .createProposedArgumentInteractionContext(
+                                objectAdapter, proposedArguments, i, interactionInitiatedBy);
+                
                 InteractionUtils.isValidResultSet(getParameter(i), ic, resultSet);
             }
         }
@@ -359,7 +328,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     @Override
     public Consent isArgumentSetValid(
             final ManagedObject objectAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
         final InteractionResultSet resultSet = new InteractionResultSet();
@@ -370,9 +339,10 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
     protected void validateArgumentSet(
             final ManagedObject objectAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy,
             final InteractionResultSet resultSet) {
+        
         final ValidityContext<?> ic = createActionInvocationInteractionContext(
                 objectAdapter, proposedArguments, interactionInitiatedBy);
         InteractionUtils.isValidResultSet(this, ic, resultSet);
@@ -380,8 +350,9 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
     ActionValidityContext createActionInvocationInteractionContext(
             final ManagedObject targetObject,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
+        
         return new ActionValidityContext(targetObject, this, getIdentifier(), proposedArguments,
                 interactionInitiatedBy);
     }
@@ -394,7 +365,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     public ManagedObject executeWithRuleChecking(
             final ManagedObject target,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] arguments,
+            final Can<ManagedObject> arguments,
             final InteractionInitiatedBy interactionInitiatedBy,
             final Where where) {
 
@@ -430,7 +401,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     public ManagedObject execute(
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters,
+            final Can<ManagedObject> argumentAdapters,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
         setupCommand(targetAdapter, argumentAdapters);
@@ -444,11 +415,12 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     public ManagedObject executeInternal(
             final ManagedObject targetAdapter,
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] argumentAdapters, 
+            final Can<ManagedObject> argumentAdapters, 
             final InteractionInitiatedBy interactionInitiatedBy) {
         
         val actionInvocationFacet = getFacet(ActionInvocationFacet.class);
-        return actionInvocationFacet.invoke(this, targetAdapter, mixedInAdapter, argumentAdapters, interactionInitiatedBy);
+        return actionInvocationFacet
+                .invoke(this, targetAdapter, mixedInAdapter, argumentAdapters, interactionInitiatedBy);
     }
 
     protected ActionInvocationFacet getActionInvocationFacet() {
@@ -461,10 +433,10 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     // -- defaults
 
     @Override
-    public ManagedObject[] getDefaults(final ManagedObject target) {
+    public Can<ManagedObject> getDefaults(final ManagedObject target) {
 
         final int parameterCount = getParameterCount();
-        final List<ObjectActionParameter> parameters = getParameters();
+        val parameters = getParameters();
 
         final Object[] parameterDefaultPojos;
 
@@ -478,7 +450,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
             for (int i = 0; i < parameterCount; i++) {
                 if (parameterDefaultPojos[i] != null) {
                     final ObjectSpecification componentSpec = getSpecificationLoader().loadSpecification(parameterDefaultPojos[i].getClass());
-                    final ObjectSpecification parameterSpec = parameters.get(i).getSpecification();
+                    final ObjectSpecification parameterSpec = parameters.getOrThrow(i).getSpecification();
                     // TODO: should implement this instead as a MetaModelValidator
                     if (!componentSpec.isOfType(parameterSpec)) {
                         throw new DomainModelException("Defaults type incompatible with parameter " + (i + 1) + " type; expected " + parameterSpec.getFullIdentifier() + ", but was " + componentSpec.getFullIdentifier());
@@ -490,7 +462,8 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
             // (the reflector will have made sure both aren't installed).
             parameterDefaultPojos = new Object[parameterCount];
             for (int i = 0; i < parameterCount; i++) {
-                final ActionParameterDefaultsFacet paramFacet = parameters.get(i).getFacet(ActionParameterDefaultsFacet.class);
+                final ActionParameterDefaultsFacet paramFacet = parameters.getOrThrow(i)
+                        .getFacet(ActionParameterDefaultsFacet.class);
                 if (paramFacet != null && !paramFacet.isFallback()) {
                     parameterDefaultPojos[i] = paramFacet
                             .getDefault(
@@ -505,14 +478,11 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
         final ManagedObject[] parameterDefaultAdapters = new ManagedObject[parameterCount];
         for (int i = 0; i < parameterCount; i++) {
-            parameterDefaultAdapters[i] = adapterFor(parameterDefaultPojos[i]);
+            val paramSpec = parameters.getOrThrow(i).getSpecification();
+            parameterDefaultAdapters[i] = ManagedObject.of(paramSpec, parameterDefaultPojos[i]);
         }
 
-        return parameterDefaultAdapters;
-    }
-
-    private ManagedObject adapterFor(final Object pojo) {
-        return pojo == null ? null : getObjectManager().adapt(pojo);
+        return Can.ofArray(parameterDefaultAdapters);
     }
 
     private static ThreadLocal<List<ManagedObject>> commandTargetAdaptersHolder = new ThreadLocal<>();
@@ -541,7 +511,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
     // -- choices
 
     @Override
-    public ManagedObject[][] getChoices(
+    public Can<Can<ManagedObject>> getChoices(
             final ManagedObject target,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
@@ -549,7 +519,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
         Object[][] parameterChoicesPojos;
 
         final ActionChoicesFacet facet = getFacet(ActionChoicesFacet.class);
-        final List<ObjectActionParameter> parameters = getParameters();
+        val parameters = getParameters();
 
         if (!facet.isFallback()) {
             // using the old choicesXxx() approach
@@ -570,7 +540,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
             parameterChoicesPojos = new Object[parameterCount][];
             for (int i = 0; i < parameterCount; i++) {
-                final ActionParameterChoicesFacet paramFacet = parameters.get(i).getFacet(ActionParameterChoicesFacet.class);
+                final ActionParameterChoicesFacet paramFacet = parameters.getOrThrow(i).getFacet(ActionParameterChoicesFacet.class);
                 if (paramFacet != null && !paramFacet.isFallback()) {
                     parameterChoicesPojos[i] = paramFacet.getChoices(target, null,
                             interactionInitiatedBy);
@@ -580,29 +550,35 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
             }
         }
 
-        final ManagedObject[][] parameterChoicesAdapters = new ManagedObject[parameterCount][];
+        final List<Can<ManagedObject>> parameterChoicesAdapters = new ArrayList<>(parameterCount);
         for (int i = 0; i < parameterCount; i++) {
-            final ObjectSpecification paramSpec = parameters.get(i).getSpecification();
+            
+            ManagedObject[] choices;
+            
+            final ObjectSpecification paramSpec = parameters.getOrThrow(i).getSpecification();
 
             if (parameterChoicesPojos[i] != null && parameterChoicesPojos[i].length > 0) {
                 ObjectActionParameterAbstract.checkChoicesOrAutoCompleteType(
                         getSpecificationLoader(), parameterChoicesPojos[i], paramSpec);
-                parameterChoicesAdapters[i] = new ManagedObject[parameterChoicesPojos[i].length];
+                choices = new ManagedObject[parameterChoicesPojos[i].length];
                 for (int j = 0; j < parameterChoicesPojos[i].length; j++) {
-                    parameterChoicesAdapters[i][j] = adapterFor(parameterChoicesPojos[i][j]);
+                    choices[j] = ManagedObject.of(paramSpec, parameterChoicesPojos[i][j]);
                 }
             } else if (paramSpec.isNotCollection()) {
-                parameterChoicesAdapters[i] = new ManagedObject[0];
+                choices = new ManagedObject[0];
             } else {
                 throw new UnknownTypeException(paramSpec);
             }
 
-            if (parameterChoicesAdapters[i].length == 0) {
-                parameterChoicesAdapters[i] = null;
+            if (choices.length == 0) {
+                choices = null;
             }
+            
+            parameterChoicesAdapters.add(Can.ofArray(choices));
+            
         }
 
-        return parameterChoicesAdapters;
+        return Can.ofCollection(parameterChoicesAdapters);
     }
 
 
@@ -636,7 +612,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
      */
     public void setupCommand(
             final ManagedObject targetAdapter,
-            final ManagedObject[] argumentAdapters) {
+            final Can<ManagedObject> argumentAdapters) {
 
         setupCommandTarget(targetAdapter, argumentAdapters);
         setupCommandMemberIdentifier();
@@ -645,7 +621,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
     private void setupCommandTarget(
             final ManagedObject targetAdapter,
-            final ManagedObject[] argumentAdapters) {
+            final Can<ManagedObject> argumentAdapters) {
 
         final String arguments = CommandUtil.argDescriptionFor(this, argumentAdapters);
         super.setupCommandTarget(targetAdapter, arguments);
@@ -653,7 +629,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
 
     private void setupCommandMementoAndExecutionContext(
             final ManagedObject targetAdapter,
-            final ManagedObject[] argumentAdapters) {
+            final Can<ManagedObject> argumentAdapters) {
 
         val commandDtoServiceInternal = getCommandDtoService();
         final List<ManagedObject> commandTargetAdapters =
@@ -689,7 +665,7 @@ public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectA
             if (i > 0) {
                 sb.append(",");
             }
-            sb.append(getParameters().get(i).getSpecification().getShortIdentifier());
+            sb.append(getParameters().getOrThrow(i).getSpecification().getShortIdentifier());
         }
         sb.append("}]");
         return sb.toString();
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionMixedIn.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionMixedIn.java
index b22a1a0..466761a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionMixedIn.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionMixedIn.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.metamodel.consent.Consent;
@@ -44,6 +45,7 @@ import org.apache.isis.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.metamodel.spec.feature.ObjectActionParameter;
 
 import lombok.Getter;
+import lombok.val;
 
 public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInMember {
 
@@ -71,7 +73,7 @@ public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInM
     /**
      * Lazily initialized by {@link #getParameters()} (so don't use directly!)
      */
-    private List<ObjectActionParameter> parameters;
+    private Can<ObjectActionParameter> parameters;
 
     private final Identifier identifier;
 
@@ -134,22 +136,22 @@ public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInM
     }
 
     @Override
-    protected synchronized List<ObjectActionParameter> determineParameters() {
+    protected synchronized Can<ObjectActionParameter> determineParameters() {
         if (parameters != null) {
             // because possible race condition (caller isn't synchronized)
             return parameters;
         }
-        final List<ObjectActionParameter> mixinActionParameters = mixinAction.getParameters();
+        val mixinActionParameters = mixinAction.getParameters();
         final List<FacetedMethodParameter> paramPeers = getFacetedMethod().getParameters();
 
         final List<ObjectActionParameter> mixedInParameters = _Lists.newArrayList();
 
-        for(int paramNum = 0; paramNum < mixinActionParameters.size(); paramNum++) {
+        for(int paramIndex = 0; paramIndex < mixinActionParameters.size(); paramIndex++) {
 
-            final ObjectActionParameterAbstract mixinParameter =
-                    (ObjectActionParameterAbstract) mixinActionParameters.get(paramNum);
+            val mixinParameter =
+                    (ObjectActionParameterAbstract) mixinActionParameters.getOrThrow(paramIndex);
 
-            final TypedHolder paramPeer = paramPeers.get(paramNum);
+            final TypedHolder paramPeer = paramPeers.get(paramIndex);
             getSpecificationLoader().loadSpecification(paramPeer.getType());
 
             final ObjectActionParameterMixedIn mixedInParameter =
@@ -158,7 +160,7 @@ public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInM
                             : new OneToManyActionParameterMixedIn(mixinParameter, this);
                     mixedInParameters.add(mixedInParameter);
         }
-        return mixedInParameters;
+        return Can.ofCollection(mixedInParameters);
     }
 
     @Override
@@ -187,13 +189,13 @@ public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInM
     }
 
     @Override
-    public ManagedObject[] getDefaults(final ManagedObject mixedInAdapter) {
+    public Can<ManagedObject> getDefaults(final ManagedObject mixedInAdapter) {
         final ManagedObject mixinAdapter = mixinAdapterFor(mixedInAdapter);
         return mixinAction.getDefaults(mixinAdapter);
     }
 
     @Override
-    public ManagedObject[][] getChoices(
+    public Can<Can<ManagedObject>> getChoices(
             final ManagedObject mixedInAdapter,
             final InteractionInitiatedBy interactionInitiatedBy) {
         final ManagedObject mixinAdapter = mixinAdapterFor(mixedInAdapter);
@@ -207,7 +209,7 @@ public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInM
     @Override
     protected void validateArgumentSet(
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final InteractionInitiatedBy interactionInitiatedBy,
             final InteractionResultSet resultSet) {
 
@@ -226,7 +228,7 @@ public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInM
     public ManagedObject execute(
             final ManagedObject target,         // will be the mixedInAdapter
             final ManagedObject mixedInAdapter, // will be passed in as null
-            final ManagedObject[] arguments,
+            final Can<ManagedObject> arguments,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
index f8819d9..9545022 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
@@ -20,7 +20,6 @@
 package org.apache.isis.metamodel.specloader.specimpl;
 
 import java.util.List;
-import java.util.function.Predicate;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.commons.collections.Can;
@@ -148,27 +147,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
 
     @Override
     public String getId() {
-        final NamedFacet facet = getFacet(NamedFacet.class);
-        if (facet != null && facet.value() != null) {
-            return StringExtensions.asCamelLowerFirst(facet.value());
-        }
-        final String name = getSpecification().getSingularName();
-        final List<ObjectActionParameter> parameters = this.getAction().getParameters(new Predicate<ObjectActionParameter>() {
-
-            @Override
-            public boolean test(final ObjectActionParameter t) {
-                return equalsShortIdentifier(t.getSpecification(), getSpecification());
-            }
-
-            protected boolean equalsShortIdentifier(final ObjectSpecification spec1, final ObjectSpecification spec2) {
-                return spec1.getShortIdentifier().toLowerCase().equals(spec2.getShortIdentifier().toLowerCase());
-            }
-        });
-        if (parameters.size() == 1) {
-            return StringExtensions.asCamelLowerFirst(name);
-        }
-        final int indexOf = parameters.indexOf(this);
-        return StringExtensions.asCamelLowerFirst(name + (indexOf + 1));
+        return StringExtensions.asCamelLowerFirst(getName());
     }
 
     @Override
@@ -177,23 +156,20 @@ implements ObjectActionParameter, FacetHolder.Delegating {
         if (facet != null && facet.value() != null) {
             return facet.value();
         }
-        final String name = getSpecification().getSingularName();
-        final List<ObjectActionParameter> parameters = getAction().getParameters(new Predicate<ObjectActionParameter>() {
-
-            @Override
-            public boolean test(final ObjectActionParameter t) {
-                return equalsShortIdentifier(t.getSpecification(), getSpecification());
-            }
-
-            protected boolean equalsShortIdentifier(final ObjectSpecification spec1, final ObjectSpecification spec2) {
-                return spec1.getShortIdentifier().toLowerCase().equals(spec2.getShortIdentifier().toLowerCase());
-            }
-        });
-        if (parameters.size() == 1) {
-            return name;
+        val singularName = getSpecification().getSingularName();
+        val parameters = getAction().getParameters(this::equalsShortIdentifier);
+        if (parameters.isCardinalityOne()) {
+            return singularName;
         }
         final int indexOf = parameters.indexOf(this);
-        return name + " " + (indexOf + 1);
+        return singularName + " " + (indexOf + 1);
+    }
+    
+    private boolean equalsShortIdentifier(final ObjectActionParameter objParam) {
+        val spec1 = objParam.getSpecification(); 
+        val spec2 = getSpecification();
+        return spec1.getShortIdentifier().toLowerCase()
+                .equals(spec2.getShortIdentifier().toLowerCase());
     }
 
     @Override
@@ -229,7 +205,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
     }
 
     @Override
-    public ManagedObject[] getAutoComplete(
+    public Can<ManagedObject> getAutoComplete(
             final ManagedObject adapter,
             final Can<ManagedObject> pendingArgs,
             final String searchArg,
@@ -246,7 +222,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
                 adapters.add(getObjectManager().adapt(choice));
             }
         }
-        return adapters.toArray(new ManagedObject[0]);
+        return Can.ofCollection(adapters);
     }
 
     @Override
@@ -266,7 +242,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
     }
 
     @Override
-    public ManagedObject[] getChoices(
+    public Can<ManagedObject> getChoices(
             final ManagedObject adapter,
             final Can<ManagedObject> pendingArgs,
             final InteractionInitiatedBy interactionInitiatedBy) {
@@ -277,7 +253,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
         return findChoices(target, args, interactionInitiatedBy);
     }
 
-    private ManagedObject[] findChoices(
+    private Can<ManagedObject> findChoices(
             final ManagedObject target,
             final Can<ManagedObject> pendingArgs,
             final InteractionInitiatedBy interactionInitiatedBy) {
@@ -293,7 +269,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
                 adapters.add(adapter);
             }
         }
-        return adapters.toArray(new ManagedObject[adapters.size()]);
+        return Can.ofCollection(adapters);
     }
 
     // -- Defaults
@@ -445,7 +421,7 @@ implements ObjectActionParameter, FacetHolder.Delegating {
     @Override
     public ActionArgValidityContext createProposedArgumentInteractionContext(
             final ManagedObject objectAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final int position,
             final InteractionInitiatedBy interactionInitiatedBy) {
         
@@ -472,10 +448,9 @@ implements ObjectActionParameter, FacetHolder.Delegating {
             }
         }
 
-        final ManagedObject[] argumentAdapters = arguments(proposedValueAdapter);
+        val argumentAdapters = arguments(proposedValueAdapter);
         final ValidityContext<?> ic = createProposedArgumentInteractionContext(
-                objectAdapter, argumentAdapters, getNumber(), interactionInitiatedBy
-                );
+                objectAdapter, argumentAdapters, getNumber(), interactionInitiatedBy);
 
         final InteractionResultSet buf = new InteractionResultSet();
         InteractionUtils.isValidResultSet(this, ic, buf);
@@ -492,11 +467,14 @@ implements ObjectActionParameter, FacetHolder.Delegating {
      * to do this in two passes, one to build up the argument set as a single
      * unit, and then validate each in turn.
      */
-    private ManagedObject[] arguments(final ManagedObject proposedValue) {
+    private Can<ManagedObject> arguments(final ManagedObject proposedValue) {
         final int parameterCount = getAction().getParameterCount();
         final ManagedObject[] arguments = new ManagedObject[parameterCount];
+        for(int i=0; i< parameterCount; ++i) {
+            arguments[i] = ManagedObject.empty();
+        }
         arguments[getNumber()] = proposedValue;
-        return arguments;
+        return Can.ofArray(arguments);
     }
 
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterContributeeAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterContributeeAbstract.java
index 70803a2..cef6871 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterContributeeAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterContributeeAbstract.java
@@ -57,7 +57,7 @@ implements ObjectActionParameterContributee {
     }
 
     @Override
-    public ManagedObject[] getAutoComplete(
+    public Can<ManagedObject> getAutoComplete(
             final ManagedObject adapter,
             final Can<ManagedObject> pendingArgs,
             final String searchArg,
@@ -87,7 +87,7 @@ implements ObjectActionParameterContributee {
 
         final List<ManagedObject> suppliedArgs = pendingArgs.stream()
                 .collect(Collectors.toCollection(ArrayList::new));
-        final int contributeeParam = contributeeAction.getContributeeParam();
+        final int contributeeParam = contributeeAction.getContributeeParamIndex();
         ListExtensions.insert(suppliedArgs, contributeeParam, contributee);
         return Can.ofCollection(suppliedArgs);
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterMixedInAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterMixedInAbstract.java
index 6906c11..91129cd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterMixedInAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterMixedInAbstract.java
@@ -43,7 +43,7 @@ implements ObjectActionParameterMixedIn {
     }
 
     @Override
-    public ManagedObject[] getAutoComplete(
+    public Can<ManagedObject> getAutoComplete(
             final ManagedObject mixedInAdapter,
             final Can<ManagedObject> pendingArgs,
             final String searchArg,
@@ -68,7 +68,7 @@ implements ObjectActionParameterMixedIn {
     @Override
     public ActionArgValidityContext createProposedArgumentInteractionContext(
             final ManagedObject mixedInAdapter,
-            final ManagedObject[] proposedArguments,
+            final Can<ManagedObject> proposedArguments,
             final int position,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationContributee.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
index 3e23224..be1c51b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.ioc.ManagedBeanAdapter;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -124,7 +125,9 @@ extends OneToManyAssociationDefault implements ContributeeMember {
             final ManagedObject ownerAdapter, 
             final InteractionInitiatedBy interactionInitiatedBy) {
         
-        return serviceAction.execute(getServiceAdapter(), null, new ManagedObject[]{ownerAdapter}, interactionInitiatedBy);
+        val params = Can.ofSingleton(ownerAdapter);
+        
+        return serviceAction.execute(getServiceAdapter(), /*mixin*/null, params, interactionInitiatedBy);
     }
 
     @Override
@@ -143,7 +146,7 @@ extends OneToManyAssociationDefault implements ContributeeMember {
     }
 
     @Override
-    public int getContributeeParamPosition() {
+    public int getContributeeParamIndex() {
         // always 0 for contributed collections
         return 0;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationDefault.java
index 8bb8619..57ecdce 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationDefault.java
@@ -20,6 +20,7 @@
 package org.apache.isis.metamodel.specloader.specimpl;
 
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.commons.ToString;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -235,10 +236,11 @@ extends ObjectAssociationAbstract implements OneToManyAssociation {
     // -- choices & autoComplete
 
     @Override
-    public ManagedObject[] getChoices(
+    public Can<ManagedObject> getChoices(
             final ManagedObject ownerAdapter,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        return new ManagedObject[0];
+        
+        return Can.empty();
     }
 
     @Override
@@ -253,11 +255,12 @@ extends ObjectAssociationAbstract implements OneToManyAssociation {
     }
 
     @Override
-    public ManagedObject[] getAutoComplete(
+    public Can<ManagedObject> getAutoComplete(
             ManagedObject object,
             String searchArg,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        return new ManagedObject[0];
+        
+        return Can.empty();
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
index 58e8071..91dcaad 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToManyAssociationMixedIn.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -153,7 +154,7 @@ public class OneToManyAssociationMixedIn extends OneToManyAssociationDefault imp
                 new PublisherDispatchService.Block<ManagedObject>() {
                     @Override public ManagedObject exec() {
                         return mixinAction.executeInternal(
-                                mixinAdapter, mixedInAdapter, new ManagedObject[0], interactionInitiatedBy);
+                                mixinAdapter, mixedInAdapter, Can.empty(), interactionInitiatedBy);
                     }
                 });
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationContributee.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationContributee.java
index 524f347..7cf2d1f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationContributee.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationContributee.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.ioc.ManagedBeanAdapter;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -41,8 +42,11 @@ import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
 
 import lombok.Getter;
+import lombok.val;
 
-public class OneToOneAssociationContributee extends OneToOneAssociationDefault implements ContributeeMember {
+public class OneToOneAssociationContributee 
+extends OneToOneAssociationDefault 
+implements ContributeeMember {
 
     private final ManagedBeanAdapter serviceBean;
     private final ObjectAction serviceAction;
@@ -108,8 +112,9 @@ public class OneToOneAssociationContributee extends OneToOneAssociationDefault i
             final ManagedObject ownerAdapter, 
             final InteractionInitiatedBy interactionInitiatedBy) {
         
-        return serviceAction.execute(
-                getServiceAdapter(), null, new ManagedObject[]{ownerAdapter}, interactionInitiatedBy);
+        val params = Can.ofSingleton(ownerAdapter);
+        
+        return serviceAction.execute(getServiceAdapter(), /*mixin*/null, params, interactionInitiatedBy);
     }
 
     @Override
@@ -128,7 +133,7 @@ public class OneToOneAssociationContributee extends OneToOneAssociationDefault i
     }
 
     @Override
-    public int getContributeeParamPosition() {
+    public int getContributeeParamIndex() {
         // always 0 for contributed properties
         return 0;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
index 5a6d723..9cb2e8b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationDefault.java
@@ -20,12 +20,10 @@
 package org.apache.isis.metamodel.specloader.specimpl;
 
 import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.commons.exceptions.IsisException;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.metamodel.commons.ToString;
 import org.apache.isis.metamodel.consent.Consent;
@@ -256,7 +254,7 @@ public class OneToOneAssociationDefault extends ObjectAssociationAbstract implem
     }
 
     @Override
-    public ManagedObject[] getChoices(
+    public Can<ManagedObject> getChoices(
             final ManagedObject ownerAdapter,
             final InteractionInitiatedBy interactionInitiatedBy) {
 
@@ -269,10 +267,10 @@ public class OneToOneAssociationDefault extends ObjectAssociationAbstract implem
                 ownerAdapter,
                 interactionInitiatedBy);
 
-        List<ManagedObject> adapters = _NullSafe.stream(pojoOptions)
-                .map(  getObjectManager()::adapt )
-                .collect(Collectors.toList());
-        return adapters.toArray(new ManagedObject[]{});
+        val adapters = _NullSafe.stream(pojoOptions)
+                .map(getObjectManager()::adapt)
+                .collect(Can.toCan());
+        return adapters;
     }
 
 
@@ -283,21 +281,19 @@ public class OneToOneAssociationDefault extends ObjectAssociationAbstract implem
     }
 
     @Override
-    public ManagedObject[] getAutoComplete(
+    public Can<ManagedObject> getAutoComplete(
             final ManagedObject ownerAdapter,
             final String searchArg,
             final InteractionInitiatedBy interactionInitiatedBy) {
+        
         final PropertyAutoCompleteFacet propertyAutoCompleteFacet = getFacet(PropertyAutoCompleteFacet.class);
-        final Object[] pojoOptions = propertyAutoCompleteFacet.autoComplete(ownerAdapter, searchArg,
-                interactionInitiatedBy);
-        if (pojoOptions != null) {
-            final ManagedObject[] options = new ManagedObject[pojoOptions.length];
-            for (int i = 0; i < options.length; i++) {
-                options[i] = getObjectManager().adapt(pojoOptions[i]);
-            }
-            return options;
-        }
-        return null;
+        final Object[] pojoOptions = propertyAutoCompleteFacet
+                .autoComplete(ownerAdapter, searchArg, interactionInitiatedBy);
+        
+        val adapters = _NullSafe.stream(pojoOptions)
+                .map(getObjectManager()::adapt)
+                .collect(Can.toCan());
+        return adapters;
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
index 89cffe5..97028f1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/OneToOneAssociationMixedIn.java
@@ -22,6 +22,7 @@ import java.util.List;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -139,7 +140,7 @@ public class OneToOneAssociationMixedIn extends OneToOneAssociationDefault imple
                     @Override
                     public ManagedObject exec() {
                         return mixinAction.executeInternal(
-                                mixinAdapter, mixedInAdapter, new ManagedObject[0], interactionInitiatedBy);
+                                mixinAdapter, mixedInAdapter, Can.empty(), interactionInitiatedBy);
                     }
                 }
                 );
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index fc3d0f0..66b4120 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -29,6 +29,7 @@ import javax.annotation.Nullable;
 
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
@@ -290,7 +291,11 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
     // -- getObjectAction
 
     @Override
-    public ObjectAction getObjectAction(final ActionType type, final String id, final List<ObjectSpecification> parameters) {
+    public ObjectAction getObjectAction(
+            final ActionType type, 
+            final String id, 
+            final Can<ObjectSpecification> parameters) {
+        
         introspectUpTo(IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED);
         final Stream<ObjectAction> actions =
                 streamObjectActions(type, Contributed.INCLUDED);
@@ -318,7 +323,7 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
     private static ObjectAction firstAction(
             final Stream<ObjectAction> candidateActions,
             final String actionName,
-            final List<ObjectSpecification> parameters) {
+            final Can<ObjectSpecification> parameters) {
 
         return candidateActions
                 .filter(action->actionName == null || actionName.equals(action.getId()))
@@ -328,14 +333,18 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
     }
 
     private static  boolean isMatchingSignature(
-            final List<ObjectSpecification> a,
-            final List<ObjectActionParameter> b) {
+            final Can<ObjectSpecification> a,
+            final Can<ObjectActionParameter> b) {
 
         if(a.size() != b.size()) {
             return false;
         }
         for (int j = 0; j < a.size(); j++) {
-            if (!a.get(j).isOfType(b.get(j).getSpecification())) {
+            
+            val elementA = a.get(j).get(); 
+            val elementB = b.get(j).get();
+            
+            if (!elementA.isOfType(elementB.getSpecification())) {
                 return false;
             }
         }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java
index 971687c..13e7860 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java
@@ -19,8 +19,7 @@
 
 package org.apache.isis.metamodel.specloader.specimpl.standalonelist;
 
-import java.util.List;
-
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Lazy;
 import org.apache.isis.commons.internal.ioc.BeanSort;
 import org.apache.isis.metamodel.facetapi.FacetUtil;
@@ -134,7 +133,11 @@ public class ObjectSpecificationOnStandaloneList extends ObjectSpecificationAbst
      * Review: is it necessary to override for this subclass?
      */
     @Override
-    public ObjectAction getObjectAction(final ActionType type, final String id, final List<ObjectSpecification> parameters) {
+    public ObjectAction getObjectAction(
+            final ActionType type, 
+            final String id, 
+            final Can<ObjectSpecification> parameters) {
+        
         return null;
     }
 
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstractTest_getId_and_getName.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstractTest_getId_and_getName.java
index 30bfd42..813b3dd 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstractTest_getId_and_getName.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectActionParameterAbstractTest_getId_and_getName.java
@@ -27,6 +27,7 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -165,7 +166,7 @@ public class ObjectActionParameterAbstractTest_getId_and_getName {
                 will(returnValue(null));
 
                 oneOf(parentAction).getParameters(with(Expectations.<Predicate<ObjectActionParameter>>anything()));
-                will(returnValue(_Lists.of(objectActionParameter)));
+                will(returnValue(Can.ofCollection(_Lists.of(objectActionParameter))));
             }
         });
 
@@ -184,7 +185,7 @@ public class ObjectActionParameterAbstractTest_getId_and_getName {
                 will(returnValue(null));
 
                 oneOf(parentAction).getParameters(with(Expectations.<Predicate<ObjectActionParameter>>anything()));
-                will(returnValue(_Lists.of(stubObjectActionParameterString, objectActionParameter, stubObjectActionParameterString2)));
+                will(returnValue(Can.ofCollection(_Lists.of(stubObjectActionParameterString, objectActionParameter, stubObjectActionParameterString2))));
             }
         });
 
@@ -203,7 +204,7 @@ public class ObjectActionParameterAbstractTest_getId_and_getName {
                 will(returnValue(null));
 
                 oneOf(parentAction).getParameters(with(Expectations.<Predicate<ObjectActionParameter>>anything()));
-                will(returnValue(_Lists.of(stubObjectActionParameterString, objectActionParameter, stubObjectActionParameterString2)));
+                will(returnValue(Can.ofCollection(_Lists.of(stubObjectActionParameterString, objectActionParameter, stubObjectActionParameterString2))));
             }
         });
 
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java
index 2ee42d6..e789c38 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest.java
@@ -27,6 +27,7 @@ import org.junit.Test;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.facetapi.Facet;
 import org.apache.isis.metamodel.facetapi.FeatureType;
@@ -93,7 +94,7 @@ public class ObjectAssociationAbstractTest {
             }
 
             @Override
-            public ManagedObject[] getChoices(
+            public Can<ManagedObject> getChoices(
                     final ManagedObject object,
                     final InteractionInitiatedBy interactionInitiatedBy) {
                 return null;
@@ -133,7 +134,7 @@ public class ObjectAssociationAbstractTest {
             }
 
             @Override
-            public ManagedObject[] getAutoComplete(
+            public Can<ManagedObject> getAutoComplete(
                     ManagedObject object,
                     String searchArg,
                     final InteractionInitiatedBy interactionInitiatedBy) {
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest_alwaysHidden.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest_alwaysHidden.java
index 8d3d6b3..dbb4298 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest_alwaysHidden.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/specloader/specimpl/ObjectAssociationAbstractTest_alwaysHidden.java
@@ -27,6 +27,7 @@ import org.junit.Test;
 
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.inject.ServiceInjector;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.facetapi.Facet;
@@ -95,7 +96,7 @@ public class ObjectAssociationAbstractTest_alwaysHidden {
             }
 
             @Override
-            public ManagedObject[] getChoices(
+            public Can<ManagedObject> getChoices(
                     final ManagedObject object,
                     final InteractionInitiatedBy interactionInitiatedBy) {
                 return null;
@@ -135,7 +136,7 @@ public class ObjectAssociationAbstractTest_alwaysHidden {
             }
 
             @Override
-            public ManagedObject[] getAutoComplete(
+            public Can<ManagedObject> getAutoComplete(
                     final ManagedObject object,
                     final String searchArg,
                     final InteractionInitiatedBy interactionInitiatedBy) {
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java
index 0602073..357b1e6 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java
@@ -25,6 +25,7 @@ import java.util.Set;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.Identifier;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.exceptions.IsisException;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.ioc.BeanSort;
@@ -152,7 +153,11 @@ public class ObjectSpecificationStub extends FacetHolderImpl implements ObjectSp
     }
 
     @Override
-    public ObjectAction getObjectAction(final ActionType type, final String name, final List<ObjectSpecification> parameters) {
+    public ObjectAction getObjectAction(
+            final ActionType type, 
+            final String name, 
+            final Can<ObjectSpecification> parameters) {
+        
         if (action != null && action.getId().equals(name)) {
             return action;
         }
diff --git a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandDtoServiceInternalDefault.java b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandDtoServiceInternalDefault.java
index 5845188..bf91a36 100644
--- a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandDtoServiceInternalDefault.java
+++ b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandDtoServiceInternalDefault.java
@@ -24,11 +24,19 @@ import java.util.UUID;
 import javax.inject.Inject;
 import javax.inject.Named;
 
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Service;
+
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.applib.util.schema.CommandDtoUtils;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.adapter.oid.RootOid;
 import org.apache.isis.metamodel.facets.actions.action.invocation.CommandUtil;
 import org.apache.isis.metamodel.services.command.CommandDtoServiceInternal;
@@ -45,14 +53,7 @@ import org.apache.isis.schema.cmd.v1.PropertyDto;
 import org.apache.isis.schema.common.v1.InteractionType;
 import org.apache.isis.schema.common.v1.OidsDto;
 import org.apache.isis.schema.common.v1.ValueWithTypeDto;
-import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.context.annotation.Primary;
-import org.springframework.core.annotation.Order;
-import org.springframework.stereotype.Service;
 
-import lombok.extern.log4j.Log4j2;
 import lombok.val;
 
 @Service
@@ -60,7 +61,6 @@ import lombok.val;
 @Order(OrderPrecedence.MIDPOINT)
 @Primary
 @Qualifier("Default")
-@Log4j2
 public class CommandDtoServiceInternalDefault implements CommandDtoServiceInternal {
 
     @Inject private CommandContext commandContext;
@@ -70,7 +70,7 @@ public class CommandDtoServiceInternalDefault implements CommandDtoServiceIntern
     public CommandDto asCommandDto(
             final List<ManagedObject> targetAdapters,
             final ObjectAction objectAction,
-            final ManagedObject[] argAdapters) {
+            final Can<ManagedObject> argAdapters) {
 
         final CommandDto dto = asCommandDto(targetAdapters);
 
@@ -130,7 +130,7 @@ public class CommandDtoServiceInternalDefault implements CommandDtoServiceIntern
     public void addActionArgs(
             final ObjectAction objectAction,
             final ActionDto actionDto,
-            final ManagedObject[] argAdapters) {
+            final Can<ManagedObject> argAdapters) {
         
         final String actionId = CommandUtil.memberIdentifierFor(objectAction);
         final ObjectSpecification onType = objectAction.getOnType();
@@ -139,12 +139,12 @@ public class CommandDtoServiceInternalDefault implements CommandDtoServiceIntern
         actionDto.setLogicalMemberIdentifier(objectType + "#" + localId);
         actionDto.setMemberIdentifier(actionId);
 
-        List<ObjectActionParameter> actionParameters = objectAction.getParameters();
+        val actionParameters = objectAction.getParameters();
         for (int paramNum = 0; paramNum < actionParameters.size(); paramNum++) {
-            final ObjectActionParameter actionParameter = actionParameters.get(paramNum);
+            final ObjectActionParameter actionParameter = actionParameters.getOrThrow(paramNum);
             final String parameterName = actionParameter.getName();
             final Class<?> paramType = actionParameter.getSpecification().getCorrespondingClass();
-            final ManagedObject argAdapter = argAdapters[paramNum];
+            final ManagedObject argAdapter = argAdapters.getOrThrow(paramNum);
             final Object arg = argAdapter != null? argAdapter.getPojo(): null;
             final ParamsDto parameters = CommandDtoUtils.parametersFor(actionDto);
             final List<ParamDto> parameterList = parameters.getParameter();
diff --git a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandExecutorServiceDefault.java b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandExecutorServiceDefault.java
index fd6bd6d..6d188e8 100644
--- a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandExecutorServiceDefault.java
+++ b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/command/CommandExecutorServiceDefault.java
@@ -27,12 +27,12 @@ import java.util.stream.Stream;
 import javax.inject.Inject;
 import javax.inject.Named;
 
-import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.context.annotation.Primary;
 import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
+import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.bookmark.BookmarkService;
 import org.apache.isis.applib.services.clock.ClockService;
@@ -44,6 +44,9 @@ import org.apache.isis.applib.services.iactn.Interaction;
 import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.applib.services.sudo.SudoService;
 import org.apache.isis.applib.services.xactn.TransactionService;
+import org.apache.isis.applib.util.schema.CommandDtoUtils;
+import org.apache.isis.applib.util.schema.CommonDtoUtils;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -68,8 +71,6 @@ import org.apache.isis.schema.common.v1.InteractionType;
 import org.apache.isis.schema.common.v1.OidDto;
 import org.apache.isis.schema.common.v1.OidsDto;
 import org.apache.isis.schema.common.v1.ValueWithTypeDto;
-import org.apache.isis.applib.util.schema.CommandDtoUtils;
-import org.apache.isis.applib.util.schema.CommonDtoUtils;
 
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
@@ -161,7 +162,7 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
 
                         // we pass 'null' for the mixedInAdapter; if this action _is_ a mixin then
                         // it will switch the targetAdapter to be the mixedInAdapter transparently
-                        final ManagedObject[] argAdapters = argAdaptersFor(actionDto);
+                        val argAdapters = argAdaptersFor(actionDto);
                         val resultAdapter = objectAction.execute(
                                 targetAdapter, null, argAdapters, InteractionInitiatedBy.FRAMEWORK);
 
@@ -298,15 +299,16 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
 
     }
 
-    private ManagedObject[] argAdaptersFor(final ActionDto actionDto) {
+    private Can<ManagedObject> argAdaptersFor(final ActionDto actionDto) {
         
         val paramDtos = paramDtosFrom(actionDto);
         
-        return paramDtos
+        val argStream = paramDtos
                 .stream()
                 .map(CommonDtoUtils::getValue)
-                .map(this::adapterFor)
-                .collect(_Arrays.toArray(ManagedObject.class, paramDtos.size()));
+                .map(this::adapterFor);
+                
+        return Can.ofStream(argStream);
     }
 
     private static List<ParamDto> paramDtosFrom(final ActionDto actionDto) {
diff --git a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/ixn/InteractionDtoServiceInternalDefault.java b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
index 8a48058..ff34330 100644
--- a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
+++ b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/ixn/InteractionDtoServiceInternalDefault.java
@@ -37,6 +37,7 @@ import org.apache.isis.applib.services.iactn.InteractionContext;
 import org.apache.isis.applib.services.user.UserService;
 import org.apache.isis.applib.util.schema.CommandDtoUtils;
 import org.apache.isis.applib.util.schema.InteractionDtoUtils;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.services.command.CommandDtoServiceInternal;
 import org.apache.isis.metamodel.services.ixn.InteractionDtoServiceInternal;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -66,7 +67,7 @@ public class InteractionDtoServiceInternalDefault implements InteractionDtoServi
     public ActionInvocationDto asActionInvocationDto(
             final ObjectAction objectAction,
             final ManagedObject targetAdapter,
-            final List<ManagedObject> argumentAdapters) {
+            final Can<ManagedObject> argumentAdapters) {
 
         final Interaction interaction = interactionContext.getInteraction();
         final int nextEventSequence = interaction.next(Interaction.Sequence.INTERACTION.id());
@@ -81,8 +82,7 @@ public class InteractionDtoServiceInternalDefault implements InteractionDtoServi
         final String currentUser = userService.getUser().getName();
 
         final ActionDto actionDto = new ActionDto();
-        commandDtoServiceInternal.addActionArgs(
-                objectAction, actionDto, argumentAdapters.toArray(new ManagedObject[]{}));
+        commandDtoServiceInternal.addActionArgs(objectAction, actionDto, argumentAdapters);
         final List<ParamDto> parameterDtos = CommandDtoUtils.parametersFor(actionDto).getParameter();
 
         return InteractionDtoUtils.newActionInvocation(
diff --git a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/wrapper/handlers/DomainObjectInvocationHandler.java b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/wrapper/handlers/DomainObjectInvocationHandler.java
index 347df6b..bd4735e 100644
--- a/core/runtime-services/src/main/java/org/apache/isis/runtime/services/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/runtime-services/src/main/java/org/apache/isis/runtime/services/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -41,6 +41,8 @@ import org.apache.isis.applib.services.wrapper.events.PropertyAccessEvent;
 import org.apache.isis.applib.services.wrapper.events.UsabilityEvent;
 import org.apache.isis.applib.services.wrapper.events.ValidityEvent;
 import org.apache.isis.applib.services.wrapper.events.VisibilityEvent;
+import org.apache.isis.commons.collections.Can;
+import org.apache.isis.commons.internal.base._NullSafe;
 import org.apache.isis.commons.internal.collections._Arrays;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.metamodel.consent.InteractionResult;
@@ -142,7 +144,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             return delegate(method, args);
         }
 
-        final ManagedObject targetAdapter = adapterForPojo(getDelegate());
+        final ManagedObject targetAdapter = getObjectManager().adapt(getDelegate());
 
         if (isTitleMethod(method)) {
             return handleTitleMethod(targetAdapter);
@@ -437,7 +439,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
             checkUsability(targetAdapter, property);
         });
         
-        val argumentAdapter = adapterForPojo(singleArg);
+        val argumentAdapter = getObjectManager().adapt(singleArg);
         
         resolveIfRequired(targetAdapter);
 
@@ -539,7 +541,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         });
         
         resolveIfRequired(targetAdapter);
-        val argumentAdapter = adapterForPojo(singleArg);
+        val argumentAdapter = getObjectManager().adapt(singleArg);
         
         runValidationTask(()->{
             val interactionResult = otma.isValidToAdd(targetAdapter, argumentAdapter,
@@ -575,7 +577,7 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         });
 
         resolveIfRequired(targetAdapter);
-        val argumentAdapter = adapterForPojo(singleArg);
+        val argumentAdapter = getObjectManager().adapt(singleArg);
 
         runValidationTask(()->{
             val interactionResult = collection.isValidToRemove(targetAdapter, argumentAdapter,
@@ -604,10 +606,10 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
         final ManagedObject contributeeAdapter;
         final Object[] contributeeArgs;
         if(contributeeMember != null) {
-            val contributeeParamPosition = contributeeMember.getContributeeParamPosition();
+            val contributeeParamPosition = contributeeMember.getContributeeParamIndex();
             val contributee = args[contributeeParamPosition];
             
-            contributeeAdapter = adapterForPojo(contributee);
+            contributeeAdapter = getObjectManager().adapt(contributee);
             contributeeArgs = _Arrays.removeByIndex(args, contributeeParamPosition); 
         } else {
             contributeeAdapter = null;
@@ -624,7 +626,8 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
                 if(contributeeMember instanceof ObjectActionContributee) {
                     val objectActionContributee = (ObjectActionContributee) contributeeMember;
                     val contributeeArgAdapters = asObjectAdaptersUnderlying(contributeeArgs);
-                    checkValidity(contributeeAdapter, objectActionContributee, contributeeArgAdapters);
+                    //TODO remove cast after refactored 
+                    checkValidity(contributeeAdapter, (ObjectAction) objectActionContributee, contributeeArgAdapters);
                 }
                 // nothing to do for contributed properties or collections
                 
@@ -651,28 +654,22 @@ public class DomainObjectInvocationHandler<T> extends DelegatingInvocationHandle
     private void checkValidity(
             final ManagedObject targetAdapter, 
             final ObjectAction objectAction, 
-            final ManagedObject[] argAdapters) {
+            final Can<ManagedObject> argAdapters) {
         
-        val interactionResult = objectAction.isProposedArgumentSetValid(targetAdapter, argAdapters,
-                getInteractionInitiatedBy()).getInteractionResult();
+        val interactionResult = objectAction
+                .isProposedArgumentSetValid(targetAdapter, argAdapters,getInteractionInitiatedBy())
+                .getInteractionResult();
         notifyListenersAndVetoIfRequired(interactionResult);
     }
 
-    private ManagedObject[] asObjectAdaptersUnderlying(final Object[] args) {
-
-        val argAdapters = new ManagedObject[args.length];
-        int i = 0;
-        for (final Object arg : args) {
-            argAdapters[i++] = adapterForPojo(underlying(arg));
-        }
-
+    private Can<ManagedObject> asObjectAdaptersUnderlying(final Object[] args) {
+        val argAdapters = _NullSafe.stream(args)
+        .map(getObjectManager()::adapt)
+        .collect(Can.toCan());
+        
         return argAdapters;
     }
 
-    private ManagedObject adapterForPojo(final Object pojo) {
-        return pojo != null ? getObjectManager().adapt(pojo) : null;
-    }
-
     private Object underlying(final Object arg) {
         if (arg instanceof WrappingObject) {
             val argViewObject = (WrappingObject) arg;
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
index 1646518..9611163 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
@@ -36,8 +36,8 @@ import org.apache.isis.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
-import org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs;
 import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
+import org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs;
 import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.ActionDescriptionReprRenderer;
 
 import lombok.val;
@@ -123,9 +123,9 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
     @Override
     protected JsonRepresentation mutatorArgs(final MutatorSpec mutatorSpec) {
         final JsonRepresentation argMap = JsonRepresentation.newMap();
-        final List<ObjectActionParameter> parameters = objectMember.getParameters();
+        val parameters = objectMember.getParameters();
         for (int i = 0; i < objectMember.getParameterCount(); i++) {
-            argMap.mapPut(parameters.get(i).getId() + ".value", argValueFor(i));
+            argMap.mapPut(parameters.getOrThrow(i).getId() + ".value", argValueFor(i));
         }
         return argMap;
     }
@@ -144,7 +144,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
         if(gsoc2013) {
             final List<Object> parameters = _Lists.newArrayList();
             for (int i = 0; i < objectMember.getParameterCount(); i++) {
-                final ObjectActionParameter param = objectMember.getParameters().get(i);
+                final ObjectActionParameter param = objectMember.getParameters().getOrThrow(i);
                 final Object paramDetails = paramDetails(param, getInteractionInitiatedBy());
                 parameters.add(paramDetails);
             }
@@ -152,7 +152,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
         } else {
             final Map<String,Object> parameters = _Maps.newLinkedHashMap();
             for (int i = 0; i < objectMember.getParameterCount(); i++) {
-                final ObjectActionParameter param = objectMember.getParameters().get(i);
+                final ObjectActionParameter param = objectMember.getParameters().getOrThrow(i);
                 final Object paramDetails = paramDetails(param, getInteractionInitiatedBy());
                 parameters.put(param.getId(), paramDetails);
             }
@@ -181,8 +181,9 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
     private Object choicesFor(
             final ObjectActionParameter param,
             final InteractionInitiatedBy interactionInitiatedBy) {
-        final ManagedObject[] choiceAdapters = param.getChoices(objectAdapter, null, interactionInitiatedBy);
-        if (choiceAdapters == null || choiceAdapters.length == 0) {
+        
+        val choiceAdapters = param.getChoices(objectAdapter, null, interactionInitiatedBy);
+        if (choiceAdapters == null || choiceAdapters.isEmpty()) {
             return null;
         }
         final List<Object> list = _Lists.newArrayList();
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
index 48d3b50..d6ad588 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectAndActionInvocation.java
@@ -18,8 +18,7 @@
  */
 package org.apache.isis.viewer.restfulobjects.rendering.domainobjects;
 
-import java.util.List;
-
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.metamodel.facets.object.encodeable.EncodableFacet;
 import org.apache.isis.metamodel.spec.ManagedObject;
@@ -33,7 +32,7 @@ public class ObjectAndActionInvocation {
     private final ManagedObject objectAdapter;
     private final ObjectAction action;
     private final JsonRepresentation arguments;
-    private final List<ManagedObject> argAdapters;
+    private final Can<ManagedObject> argAdapters;
     private final ManagedObject returnedAdapter;
     private final ActionResultReprRenderer.SelfLink selfLink;
 
@@ -41,9 +40,10 @@ public class ObjectAndActionInvocation {
             final ManagedObject objectAdapter,
             final ObjectAction action,
             final JsonRepresentation arguments,
-            final List<ManagedObject> argAdapters,
+            final Can<ManagedObject> argAdapters,
             final ManagedObject returnedAdapter,
             final ActionResultReprRenderer.SelfLink selfLink) {
+        
         this.objectAdapter = objectAdapter;
         this.action = action;
         this.arguments = arguments;
@@ -64,7 +64,7 @@ public class ObjectAndActionInvocation {
         return arguments;
     }
 
-    public List<ManagedObject> getArgAdapters() {
+    public Can<ManagedObject> getArgAdapters() {
         return argAdapters;
     }
 
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
index eefbb76..bb5a9ef 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectPropertyReprRenderer.java
@@ -33,14 +33,13 @@ import org.apache.isis.metamodel.facets.object.title.TitleFacet;
 import org.apache.isis.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.metamodel.facets.value.bigdecimal.BigDecimalValueFacet;
 import org.apache.isis.metamodel.facets.value.biginteger.BigIntegerValueFacet;
-import org.apache.isis.metamodel.spec.ManagedObject;
 import org.apache.isis.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
 import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
 import org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs;
-import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
 import org.apache.isis.viewer.restfulobjects.rendering.domaintypes.PropertyDescriptionReprRenderer;
 
 import lombok.val;
@@ -213,11 +212,10 @@ extends AbstractObjectMemberReprRenderer<ObjectPropertyReprRenderer, OneToOneAss
     }
 
     private Object propertyChoices() {
-        final ManagedObject[] choiceAdapters =
-                objectMember.getChoices(
-                        objectAdapter,
-                        getInteractionInitiatedBy());
-        if (choiceAdapters == null || choiceAdapters.length == 0) {
+        val choiceAdapters = objectMember
+                .getChoices(objectAdapter, getInteractionInitiatedBy());
+        
+        if (choiceAdapters == null || choiceAdapters.isEmpty()) {
             return null;
         }
         final List<Object> list = _Lists.newArrayList();
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java
index b174f85..c500af9 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/ActionDescriptionReprRenderer.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.viewer.restfulobjects.rendering.domaintypes;
 
-import java.util.List;
-
 import org.apache.isis.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
@@ -27,9 +25,11 @@ import org.apache.isis.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
 import org.apache.isis.viewer.restfulobjects.applib.Rel;
 import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
+import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
 import org.apache.isis.viewer.restfulobjects.rendering.LinkBuilder;
 import org.apache.isis.viewer.restfulobjects.rendering.LinkFollowSpecs;
-import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
+
+import lombok.val;
 
 public class ActionDescriptionReprRenderer extends AbstractTypeMemberReprRenderer<ActionDescriptionReprRenderer, ObjectAction> {
 
@@ -53,7 +53,7 @@ public class ActionDescriptionReprRenderer extends AbstractTypeMemberReprRendere
 
     private void addParameters() {
         final JsonRepresentation parameterList = JsonRepresentation.newArray();
-        final List<ObjectActionParameter> parameters = getObjectFeature().getParameters();
+        val parameters = getObjectFeature().getParameters();
         for (final ObjectActionParameter parameter : parameters) {
             final LinkBuilder linkBuilder = ActionParameterDescriptionReprRenderer.newLinkToBuilder(getResourceContext(), Rel.ACTION_PARAM, objectSpecification, parameter);
             parameterList.arrayAdd(linkBuilder.build());
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
index c43200a..efdd9db 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/conneg/ContentNegotiationServiceForRestfulObjectsV1_0.java
@@ -36,6 +36,7 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.domain.DomainObjectList;
+import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.config.IsisConfiguration;
 import org.apache.isis.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.metamodel.facets.collections.modify.CollectionFacet;
@@ -241,12 +242,14 @@ public class ContentNegotiationServiceForRestfulObjectsV1_0 implements ContentNe
 
     private static String actionArgumentsFrom(final ObjectAndActionInvocation objectAndActionInvocation) {
         final StringBuilder buf = new StringBuilder();
-        final List<ObjectActionParameter> parameters = objectAndActionInvocation.getAction().getParameters();
-        final List<ManagedObject> argAdapters = objectAndActionInvocation.getArgAdapters();
+        val parameters = objectAndActionInvocation.getAction().getParameters();
+        val argAdapters = objectAndActionInvocation.getArgAdapters();
         if(parameters.size() == argAdapters.size()) {
             for (int i = 0; i < parameters.size(); i++) {
-                final ObjectActionParameter param = parameters.get(i);
-                final ManagedObject argAdapter = argAdapters.get(i);
+                
+                val paramIndex = i;
+                val param = parameters.getOrThrow(paramIndex);
+                val argAdapter = argAdapters.getOrThrow(paramIndex);
 
                 if(buf.length() > 0) {
                     buf.append(",");
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/ClassExcluderAbstract.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/ClassExcluderAbstract.java
index b5aaef4..d2d0b65 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/ClassExcluderAbstract.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/ClassExcluderAbstract.java
@@ -18,13 +18,14 @@
  */
 package org.apache.isis.viewer.restfulobjects.rendering.service.swagger.internal;
 
-import java.util.List;
 import java.util.Set;
 
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.spec.feature.ObjectAction;
 
+import lombok.val;
+
 public abstract class ClassExcluderAbstract implements ClassExcluder {
 
     private final Set<String> packageNamesToIgnore = _Sets.newHashSet();
@@ -53,7 +54,7 @@ public abstract class ClassExcluderAbstract implements ClassExcluder {
             return true;
         }
 
-        final List<ObjectSpecification> parameterTypes = objectAction.getParameterTypes();
+        val parameterTypes = objectAction.getParameterTypes();
         for (ObjectSpecification parameterType : parameterTypes) {
             if(exclude(parameterType)) {
                 return true;
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java
index 43d2a5b..5a6acf3 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java
@@ -441,7 +441,7 @@ class Generation {
         final String serviceId = serviceIdFor(serviceSpec);
         final String actionId = serviceAction.getId();
 
-        final List<ObjectActionParameter> parameters = serviceAction.getParameters();
+        val parameters = serviceAction.getParameters();
         final Path path = new Path();
         swagger.path(String.format("/services/%s/actions/%s/invoke", serviceId, actionId), path);
 
@@ -550,7 +550,7 @@ class Generation {
         final String objectType = objectTypeFor(objectSpec);
         final String actionId = objectAction.getId();
 
-        final List<ObjectActionParameter> parameters = objectAction.getParameters();
+        val parameters = objectAction.getParameters();
         final Path path = new Path();
         swagger.path(String.format("/objects/%s/{objectId}/actions/%s/invoke", objectType, actionId), path);
 
diff --git a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Util.java b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Util.java
index a5941b7..6869317 100644
--- a/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Util.java
+++ b/core/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Util.java
@@ -25,6 +25,7 @@ import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
 import org.apache.isis.applib.services.swagger.SwaggerService;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Casts;
 import org.apache.isis.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.metamodel.spec.ActionType;
@@ -56,7 +57,7 @@ public final class Util {
         return isVisibleForPublic(typeOfFacet.valueSpec());
     }
 
-    private static boolean isVisibleForPublic(List<ObjectSpecification> parameterTypes) {
+    private static boolean isVisibleForPublic(Can<ObjectSpecification> parameterTypes) {
 
         final boolean atLeastOneParamNotVisible =
                 parameterTypes.stream()
diff --git a/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java b/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
index 9dc3e4c..2f5c01b 100644
--- a/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
+++ b/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/DomainResourceHelper.java
@@ -18,8 +18,6 @@
  */
 package org.apache.isis.viewer.restfulobjects.viewer.resources;
 
-import java.util.List;
-
 import javax.ws.rs.core.Response;
 
 import org.apache.isis.applib.annotation.SemanticsOf;
@@ -45,6 +43,8 @@ import org.apache.isis.viewer.restfulobjects.rendering.domainobjects.ObjectAndPr
 import org.apache.isis.viewer.restfulobjects.rendering.service.RepresentationService;
 import org.apache.isis.viewer.restfulobjects.viewer.context.ResourceContext;
 
+import lombok.val;
+
 class DomainResourceHelper {
 
     private final IResourceContext resourceContext;
@@ -215,11 +215,9 @@ class DomainResourceHelper {
             final JsonRepresentation arguments,
             final ActionResultReprRenderer.SelfLink selfLink) {
 
-        final ManagedObject objectAdapter = this.objectAdapter;
-
-        final ObjectActionArgHelper argHelper = new ObjectActionArgHelper(resourceContext, objectAdapter, action);
-
-        final List<ManagedObject> argAdapters = argHelper.parseAndValidateArguments(arguments);
+        val objectAdapter = this.objectAdapter;
+        val argHelper = new ObjectActionArgHelper(resourceContext, objectAdapter, action);
+        val argAdapters = argHelper.parseAndValidateArguments(arguments);
 
         if(resourceContext.isValidateOnly()) {
             // nothing more to do.
@@ -229,9 +227,8 @@ class DomainResourceHelper {
 
         // invoke
         final ManagedObject mixedInAdapter = null; // action will automatically fill in if a mixin
-        final ManagedObject[] argAdapterArr = argAdapters.toArray(new ManagedObject[argAdapters.size()]);
         final ManagedObject returnedAdapter = action.execute(
-                objectAdapter,  mixedInAdapter, argAdapterArr,
+                objectAdapter,  mixedInAdapter, argAdapters,
                 InteractionInitiatedBy.USER);
 
         final ObjectAndActionInvocation objectAndActionInvocation =
diff --git a/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectActionArgHelper.java b/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectActionArgHelper.java
index 38e50c6..6a5d030 100644
--- a/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectActionArgHelper.java
+++ b/core/viewers/restfulobjects/viewer/src/main/java/org/apache/isis/viewer/restfulobjects/viewer/resources/ObjectActionArgHelper.java
@@ -21,6 +21,7 @@ package org.apache.isis.viewer.restfulobjects.viewer.resources;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -33,6 +34,8 @@ import org.apache.isis.viewer.restfulobjects.applib.client.RestfulResponse;
 import org.apache.isis.viewer.restfulobjects.rendering.IResourceContext;
 import org.apache.isis.viewer.restfulobjects.rendering.RestfulObjectsApplicationException;
 
+import lombok.val;
+
 /**
  * Utility class that encapsulates the logic for parsing arguments to be invoked by an
  * {@link org.apache.isis.metamodel.spec.feature.ObjectAction}.
@@ -52,21 +55,21 @@ public class ObjectActionArgHelper {
         this.action = action;
     }
 
-    public List<ManagedObject> parseAndValidateArguments(final JsonRepresentation arguments) {
+    public Can<ManagedObject> parseAndValidateArguments(final JsonRepresentation arguments) {
         final List<JsonRepresentation> argList = argListFor(action, arguments);
 
         final List<ManagedObject> argAdapters = _Lists.newArrayList();
-        final List<ObjectActionParameter> parameters = action.getParameters();
+        val parameters = action.getParameters();
         boolean valid = true;
         for (int i = 0; i < argList.size(); i++) {
             final JsonRepresentation argRepr = argList.get(i);
-            final ObjectSpecification paramSpec = parameters.get(i).getSpecification();
+            final ObjectSpecification paramSpec = parameters.getOrThrow(i).getSpecification();
             try {
                 final ManagedObject argAdapter = new JsonParserHelper(resourceContext, paramSpec).objectAdapterFor(argRepr);
                 argAdapters.add(argAdapter);
 
                 // validate individual arg
-                final ObjectActionParameter parameter = parameters.get(i);
+                final ObjectActionParameter parameter = parameters.getOrThrow(i);
                 final Object argPojo = argAdapter!=null?argAdapter.getPojo():null;
                 final String reasonNotValid = parameter.isValid(objectAdapter, argPojo, InteractionInitiatedBy.USER);
                 if (reasonNotValid != null) {
@@ -80,8 +83,9 @@ public class ObjectActionArgHelper {
         }
 
         // validate entire argument set
-        final ManagedObject[] argArray = argAdapters.toArray(new ManagedObject[0]);
-        final Consent consent = action.isArgumentSetValid(objectAdapter, argArray, InteractionInitiatedBy.USER);
+        val args = Can.ofCollection(argAdapters);
+        final Consent consent = action.isArgumentSetValid(
+                objectAdapter, args, InteractionInitiatedBy.USER);
         if (consent.isVetoed()) {
             arguments.mapPut("x-ro-invalidReason", consent.getReason());
             valid = false;
@@ -94,7 +98,7 @@ public class ObjectActionArgHelper {
                     "Validation failed, see body for details");
         }
 
-        return argAdapters;
+        return args;
     }
 
     private static List<JsonRepresentation> argListFor(final ObjectAction action, final JsonRepresentation arguments) {
@@ -127,7 +131,7 @@ public class ObjectActionArgHelper {
 
         // ensure that an argument value has been provided for all non-optional
         // parameters
-        final List<ObjectActionParameter> parameters = action.getParameters();
+        val parameters = action.getParameters();
         for (final ObjectActionParameter param : parameters) {
             final String paramId = param.getId();
             final JsonRepresentation argRepr = arguments.getRepresentation(paramId);
diff --git a/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionParameterMemento.java b/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionParameterMemento.java
index 75d70f5..9138a75 100644
--- a/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionParameterMemento.java
+++ b/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/mementos/ActionParameterMemento.java
@@ -78,10 +78,10 @@ public class ActionParameterMemento implements Serializable {
 
     private static ObjectActionParameter actionParameterFor(
             final ActionMemento actionMemento,
-            final int number,
+            final int paramIndex,
             final SpecificationLoader specificationLoader) {
         final ObjectAction action = actionMemento.getAction(specificationLoader);
-        return action.getParameters().get(number);
+        return action.getParameters().getOrThrow(paramIndex);
     }
 
     /**
diff --git a/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index 0087c98..ee6a4b5 100644
--- a/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -22,11 +22,13 @@ package org.apache.isis.viewer.wicket.model.models;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import org.apache.wicket.request.IRequestHandler;
@@ -48,8 +50,8 @@ import org.apache.isis.applib.value.Blob;
 import org.apache.isis.applib.value.Clob;
 import org.apache.isis.applib.value.LocalResourcePath;
 import org.apache.isis.applib.value.NamedWithMimeType;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._NullSafe;
-import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Maps;
 import org.apache.isis.metamodel.adapter.oid.Oid;
 import org.apache.isis.metamodel.adapter.oid.RootOid;
@@ -187,14 +189,12 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
     @Override
     public PageParameters getPageParametersWithoutUiHints() {
         val adapter = getTargetAdapter();
-        final ObjectAction objectAction = getAction();
-        final PageParameters pageParameters = createPageParameters(
-                adapter, objectAction);
+        val objectAction = getAction();
+        val pageParameters = createPageParameters(adapter, objectAction);
 
         // capture argument values
-        final ManagedObject[] argumentsAsArray = getArgumentsAsArray();
-        for(val argumentAdapter: argumentsAsArray) {
-            final String encodedArg = encodeArg(argumentAdapter);
+        for(val argumentAdapter: getArgumentsAsImmutable()) {
+            val encodedArg = encodeArg(argumentAdapter);
             PageParameterNames.ACTION_ARGS.addStringTo(pageParameters, encodedArg);
         }
 
@@ -213,8 +213,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
         final ObjectAction objectAction = getAction();
 
         final StringBuilder buf = new StringBuilder();
-        final ManagedObject[] argumentsAsArray = getArgumentsAsArray();
-        for(val argumentAdapter: argumentsAsArray) {
+        for(val argumentAdapter: getArgumentsAsImmutable()) {
             if(buf.length() > 0) {
                 buf.append(",");
             }
@@ -318,16 +317,16 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
         }
     }
 
-    private void setArgumentsIfPossible(
-            final PageParameters pageParameters) {
+    private void setArgumentsIfPossible(final PageParameters pageParameters) {
+        
         final List<String> args = PageParameterNames.ACTION_ARGS.getListFrom(pageParameters);
 
-        final ObjectAction action = actionMemento.getAction(getSpecificationLoader());
-        final List<ObjectSpecification> parameterTypes = action.getParameterTypes();
+        val action = actionMemento.getAction(getSpecificationLoader());
+        val parameterTypes = action.getParameterTypes();
 
         for (int paramNum = 0; paramNum < args.size(); paramNum++) {
             final String encoded = args.get(paramNum);
-            setArgument(paramNum, parameterTypes.get(paramNum), encoded);
+            setArgument(paramNum, parameterTypes.getOrThrow(paramNum), encoded);
         }
     }
 
@@ -346,8 +345,8 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
             return false;
         }
 
-        final ObjectAction action = actionMemento.getAction(getSpecificationLoader());
-        final List<ObjectSpecification> parameterTypes = action.getParameterTypes();
+        val action = actionMemento.getAction(getSpecificationLoader());
+        val parameterTypes = action.getParameterTypes();
         final int parameterCount = parameterTypes.size();
 
         final Map.Entry<Integer, String> mapEntry = parse(paramContext);
@@ -358,7 +357,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
         }
 
         final String encoded = mapEntry.getValue();
-        setArgument(paramNum, parameterTypes.get(paramNum), encoded);
+        setArgument(paramNum, parameterTypes.getOrThrow(paramNum), encoded);
 
         return true;
     }
@@ -403,7 +402,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
     private void setArgument(int paramNum, ManagedObject argumentAdapter) {
         
         final ObjectAction action = actionMemento.getAction(getSpecificationLoader());
-        final ObjectActionParameter actionParam = action.getParameters().get(paramNum);
+        final ObjectActionParameter actionParam = action.getParameters().getOrThrow(paramNum);
         final ActionParameterMemento apm = new ActionParameterMemento(actionParam);
         final ActionArgumentModel actionArgumentModel = getArgumentModel(apm);
         actionArgumentModel.setObject(argumentAdapter);
@@ -451,7 +450,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
     private ManagedObject executeAction() {
 
         val targetAdapter = getTargetAdapter();
-        final ManagedObject[] arguments = getArgumentsAsArray();
+        val arguments = getArgumentsAsImmutable();
         final ObjectAction action = getAction();
 
         // if this action is a mixin, then it will fill in the details automatically.
@@ -510,7 +509,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
 
     public String getReasonInvalidIfAny() {
         val targetAdapter = getTargetAdapter();
-        final ManagedObject[] proposedArguments = getArgumentsAsArray();
+        val proposedArguments = getArgumentsAsImmutable();
         final ObjectAction objectAction = getAction();
         final Consent validity = objectAction
                 .isProposedArgumentSetValid(targetAdapter, proposedArguments, InteractionInitiatedBy.USER);
@@ -522,7 +521,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
         throw new UnsupportedOperationException("target adapter for ActionModel cannot be changed");
     }
 
-    public ManagedObject[] getArgumentsAsArray() {
+    public Can<ManagedObject> getArgumentsAsImmutable() {
         if(this.arguments.size() < getAction().getParameterCount()) {
             primeArgumentModels();
         }
@@ -533,7 +532,7 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
             final ActionArgumentModel actionArgumentModel = this.arguments.get(i);
             arguments[i] = actionArgumentModel.getObject();
         }
-        return arguments;
+        return Can.ofArray(arguments);
     }
 
     @Override
@@ -636,22 +635,24 @@ public class ActionModel extends BookmarkableModel<ManagedObject> implements For
     public List<ActionParameterMemento> primeArgumentModels() {
         final ObjectAction objectAction = getAction();
 
-        final List<ObjectActionParameter> parameters = objectAction.getParameters();
-        final List<ActionParameterMemento> mementos = buildParameterMementos(parameters);
-        for (final ActionParameterMemento apm : mementos) {
-            getArgumentModel(apm);
+        val parameters = objectAction.getParameters();
+        val actionParameterMementos = buildParameterMementos(parameters);
+        for (val actionParameterMemento : actionParameterMementos) {
+            getArgumentModel(actionParameterMemento);
         }
 
-        return mementos;
+        return actionParameterMementos;
     }
 
 
-    private static List<ActionParameterMemento> buildParameterMementos(final List<ObjectActionParameter> parameters) {
-        final List<ActionParameterMemento> parameterMementoList =
-                _Lists.map(parameters, ActionParameterMemento::new);
+    private static List<ActionParameterMemento> buildParameterMementos(
+            final Can<ObjectActionParameter> parameters) {
+
         // we copy into a new array list otherwise we get lazy evaluation =
         // reference to a non-serializable object
-        return _Lists.newArrayList(parameterMementoList);
+        return parameters.stream()
+                .map(ActionParameterMemento::new)
+                .collect(Collectors.toCollection(ArrayList::new));
     }
 
 
diff --git a/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java b/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
index f11e6c8..d549117 100644
--- a/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
+++ b/core/viewers/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ScalarModel.java
@@ -23,8 +23,6 @@ import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import org.apache.isis.applib.annotation.PromptStyle;
 import org.apache.isis.applib.annotation.Where;
@@ -217,11 +215,11 @@ implements LinksProvider, FormExecutorContext, ActionArgumentModel {
                 final OneToOneAssociation property = propertyMemento
                         .getProperty(scalarModel.getSpecificationLoader());
                 ManagedObject parentAdapter = scalarModel.getParentEntityModel().load();
-                final ManagedObject[] choices = property.getChoices(
+                final Can<ManagedObject> choices = property.getChoices(
                         parentAdapter,
                         InteractionInitiatedBy.USER);
 
-                return choicesAsList(choices);
+                return choices.toList();
             }
 
             @Override
@@ -242,12 +240,12 @@ implements LinksProvider, FormExecutorContext, ActionArgumentModel {
                 final OneToOneAssociation property = propertyMemento.getProperty(scalarModel.getSpecificationLoader());
                 final ManagedObject parentAdapter =
                         scalarModel.getParentEntityModel().load();
-                final ManagedObject[] choices =
+                final Can<ManagedObject> choices =
                         property.getAutoComplete(
                                 parentAdapter, 
                                 searchArg,
                                 InteractionInitiatedBy.USER);
-                return choicesAsList(choices);
+                return choices.toList();
             }
 
             @Override
@@ -455,12 +453,12 @@ implements LinksProvider, FormExecutorContext, ActionArgumentModel {
                 //XXX lombok issue, no val
                 ManagedObject parentAdapter = scalarModel.getParentEntityModel().load();
 
-                final ManagedObject[] choices =
+                final Can<ManagedObject> choices =
                         actionParameter.getChoices(
                                 parentAdapter, 
                                 pendingArgs,
                                 InteractionInitiatedBy.USER);
-                return choicesAsList(choices);
+                return choices.toList();
             }
 
             @Override
@@ -480,12 +478,12 @@ implements LinksProvider, FormExecutorContext, ActionArgumentModel {
                 final ObjectActionParameter actionParameter = parameterMemento.getActionParameter(scalarModel.getSpecificationLoader());
 
                 ManagedObject parentAdapter = scalarModel.getParentEntityModel().load();
-                final ManagedObject[] choices = actionParameter.getAutoComplete(
+                final Can<ManagedObject> choices = actionParameter.getAutoComplete(
                         parentAdapter,
                         pendingArgs,
                         searchArg,
                         InteractionInitiatedBy.USER);
-                return choicesAsList(choices);
+                return choices.toList();
             }
 
             @Override
@@ -599,14 +597,6 @@ implements LinksProvider, FormExecutorContext, ActionArgumentModel {
 
         };
 
-        private static List<ManagedObject> choicesAsList(final ManagedObject[] choices) {
-            if (choices != null && choices.length > 0) {
-                return Stream.of(choices)
-                        .collect(Collectors.toList());
-            }
-            return Collections.emptyList();
-        }
-
         public abstract String getName(ScalarModel scalarModel);
 
         public abstract ObjectSpecification getScalarTypeSpec(ScalarModel scalarModel);
diff --git a/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java b/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java
index 7bb807e..aadc638 100644
--- a/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java
+++ b/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actions/ActionParametersForm.java
@@ -29,7 +29,6 @@ import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.repeater.RepeatingView;
 
 import org.apache.isis.applib.annotation.SemanticsOf;
-import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.metamodel.consent.Consent;
 import org.apache.isis.metamodel.consent.InteractionInitiatedBy;
@@ -80,7 +79,7 @@ class ActionParametersForm extends PromptFormAbstract<ActionModel> {
             rv.add(container);
 
             final ActionArgumentModel actionArgumentModel = actionModel.getArgumentModel(apm);
-            actionArgumentModel.setActionArgsHint(Can.ofArray(actionModel.getArgumentsAsArray()));
+            actionArgumentModel.setActionArgsHint(actionModel.getArgumentsAsImmutable());
             final ScalarPanelAbstract2 paramPanel = newParamPanel(container, actionArgumentModel);
             paramPanels.add(paramPanel);
 
@@ -164,7 +163,7 @@ class ActionParametersForm extends PromptFormAbstract<ActionModel> {
 
         final int numParams = action.getParameterCount();
 
-        // only updates subsequent parameter panels to this one.
+        // only updates subsequent parameter panels starting from [paramNumberUpdated + 1] 
         for (int i = paramNumberUpdated + 1; i < numParams; i++) {
 
             val paramNumToUpdate = i;
diff --git a/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java b/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
index 53a536b..c8d6726 100644
--- a/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
+++ b/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelAbstract2.java
@@ -39,7 +39,6 @@ import org.apache.wicket.model.Model;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.PromptStyle;
 import org.apache.isis.applib.services.metamodel.MetaModelService;
-import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.ioc.BeanSort;
@@ -134,12 +133,10 @@ implements ScalarModelSubscriber2 {
             final AjaxRequestTarget target) {
 
         final ObjectAction action = actionModel.getActionMemento().getAction(getSpecificationLoader());
-        val pendingArgumentArray = actionModel.getArgumentsAsArray();
-        val pendingArguments = Can.ofArray(pendingArgumentArray);
-
+        val pendingArguments = actionModel.getArgumentsAsImmutable();
 
         // could almost certainly simplify this... (used by visibility and usability checks)
-        final ObjectActionParameter actionParameter = action.getParameters().get(paramNumToPossiblyUpdate);
+        final ObjectActionParameter actionParameter = action.getParameters().getOrThrow(paramNumToPossiblyUpdate);
         val targetAdapter = actionModel.getTargetAdapter();
         val realTargetAdapter = action.realTargetAdapter(targetAdapter);
 
@@ -176,7 +173,7 @@ implements ScalarModelSubscriber2 {
         val actionParameterMemento = new ActionParameterMemento(actionParameter);
         val actionArgumentModel = actionModel.getArgumentModel(actionParameterMemento);
 
-        val pendingArg = pendingArgumentArray[paramNumToPossiblyUpdate];
+        val pendingArg = pendingArguments.getOrThrow(paramNumToPossiblyUpdate);
         
         if (defaultIfAny != null) {
             scalarModel.setObject(defaultIfAny);
diff --git a/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java b/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java
index e9615f6..e43a4fe 100644
--- a/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java
+++ b/core/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/ScalarPanelSelect2Abstract.java
@@ -181,7 +181,7 @@ public abstract class ScalarPanelSelect2Abstract extends ScalarPanelAbstract2 {
             final int paramNumToPossiblyUpdate,
             final AjaxRequestTarget target) {
 
-        val arguments = Can.ofArray(actionModel.getArgumentsAsArray());
+        val arguments = actionModel.getArgumentsAsImmutable();
 
         val repaint = super.updateIfNecessary(actionModel, paramNumUpdated, paramNumToPossiblyUpdate, target);
 
diff --git a/examples/demo/src/main/java/demoapp/dom/actions/depargs/DemoItem.java b/examples/demo/src/main/java/demoapp/dom/actions/depargs/DemoItem.java
index 836a5ae..a4a62fc 100644
--- a/examples/demo/src/main/java/demoapp/dom/actions/depargs/DemoItem.java
+++ b/examples/demo/src/main/java/demoapp/dom/actions/depargs/DemoItem.java
@@ -36,7 +36,7 @@ import lombok.Setter;
 @Named("depargs.DemoItem")
 @NoArgsConstructor 
 @AllArgsConstructor(staticName="of")
-@EqualsAndHashCode
+@EqualsAndHashCode // required for the Dependent Arguments demo to work properly
 public class DemoItem {
 
     public String title() {
diff --git a/incubator/core/model/src/main/java/org/apache/isis/incubator/model/metamodel/facets/SupportingMethodValidatorRefinerFactory.java b/incubator/core/model/src/main/java/org/apache/isis/incubator/model/metamodel/facets/SupportingMethodValidatorRefinerFactory.java
index f0b772f..463c7ed 100644
--- a/incubator/core/model/src/main/java/org/apache/isis/incubator/model/metamodel/facets/SupportingMethodValidatorRefinerFactory.java
+++ b/incubator/core/model/src/main/java/org/apache/isis/incubator/model/metamodel/facets/SupportingMethodValidatorRefinerFactory.java
@@ -64,18 +64,18 @@ implements MetaModelRefiner {
             val type = spec.getCorrespondingClass();
 
 //XXX for debugging ...            
-//            if(spec.getSpecId().asString().contains("ProperActionSupport")) {
-//                
-//                val sb = new StringBuffer();
-//                
-//                sb.append("\n### debug " + spec.getSpecId().asString()).append("\n");
-//                
-//                spec.streamFacetHolders()
-//                .flatMap(FacetHolder::streamFacets)
-//                .forEach(facet->sb.append("facet: " + facet).append("\n"));
-//                
-//                System.out.println(sb);
-//            }
+            if(spec.getSpecId().asString().contains("DependentArgsActionDemo_useDisable")) {
+                
+                val sb = new StringBuffer();
+                
+                sb.append("\n### debug " + spec.getSpecId().asString()).append("\n");
+                
+                spec.streamFacetHolders()
+                .flatMap(FacetHolder::streamFacets)
+                .forEach(facet->sb.append("facet: " + facet).append("\n"));
+                
+                System.out.println(sb);
+            }
 
             // methods known to the meta-model
             val recognizedMethods = spec.streamFacetHolders()