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 2021/05/06 06:26:27 UTC

[isis] branch master updated: ISIS-2648: some MM housekeeping

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


The following commit(s) were added to refs/heads/master by this push:
     new 523fbf2  ISIS-2648: some MM housekeeping
523fbf2 is described below

commit 523fbf277c615c9c85d11c577b73bffe6c9b4d6c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu May 6 08:26:09 2021 +0200

    ISIS-2648: some MM housekeeping
---
 ...reteTypeToBeIncludedWithMetamodelValidator.java |  2 +-
 ...jectSpecIdFacetDerivedFromClassNameFactory.java | 18 ++--
 .../ApplicationFeatureRepositoryDefault.java       | 34 ++++----
 .../services/grid/GridSystemServiceAbstract.java   |  2 +-
 .../bootstrap3/GridSystemServiceBootstrap.java     |  2 +-
 .../services/metamodel/MetaModelExporter.java      |  2 +-
 .../metamodel/MetaModelServiceDefault.java         | 12 +--
 .../core/metamodel/spec/ObjectSpecification.java   |  6 +-
 .../spec/feature/ObjectActionContainer.java        | 99 ++++++++++++++--------
 .../spec/feature/ObjectAssociationContainer.java   | 31 +++----
 .../specimpl/ObjectSpecificationAbstract.java      | 13 +--
 .../specimpl/dflt/ObjectSpecificationDefault.java  | 45 ++++------
 .../ApplicationFeatureRepositoryDefaultTest.java   | 33 ++++----
 .../testspec/ObjectSpecificationStub.java          | 26 ++++--
 .../wrapper/WrapperFactoryDefault.java             | 18 ++--
 .../handlers/DomainObjectInvocationHandler.java    |  8 +-
 .../DomainModelTest_usingGoodDomain.java           | 48 +++++------
 .../domainobjects/DomainObjectReprRenderer.java    | 40 ++++-----
 .../domaintypes/DomainTypeReprRenderer.java        | 12 +--
 .../service/swagger/internal/Generation.java       |  2 +-
 .../collection/AssociatedWithActionsHelper.java    | 33 +++-----
 .../ui/components/collection/CollectionPanel.java  | 12 +--
 22 files changed, 253 insertions(+), 245 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java
index cf5aed7..579acaa 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationShouldEnforceConcreteTypeToBeIncludedWithMetamodelValidator.java
@@ -39,7 +39,7 @@ extends MetaModelVisitingValidatorAbstract {
         if(spec.getBeanSort()==BeanSort.UNKNOWN
                 && !spec.isAbstract()) {
 
-            val actions = spec.streamActions(MixedIn.EXCLUDED).collect(Collectors.toList());
+            val actions = spec.streamAnyActions(MixedIn.EXCLUDED).collect(Collectors.toList());
 
             final int numActions = actions.size();
             if (numActions > 0) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
index 93486d1..48fa5c9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
@@ -81,9 +81,9 @@ implements MetaModelRefiner, ObjectSpecIdFacetFactory {
     }
 
     private static ObjectSpecIdFacet createObjectSpecIdFacet(
-            final FacetHolder facetHolder, 
+            final FacetHolder facetHolder,
             final Class<?> substitutedClass) {
-        
+
         val serviceId = getServiceId(facetHolder);
         val isService = serviceId!=null;
 
@@ -112,11 +112,11 @@ implements MetaModelRefiner, ObjectSpecIdFacetFactory {
         }
 
         programmingModel.addVisitingValidatorSkipManagedBeans(objectSpec-> {
-                    
+
             if(!check(objectSpec)) {
                 return;
             }
-            
+
             val objectSpecIdFacet = objectSpec.getFacet(ObjectSpecIdFacet.class);
             if(objectSpecIdFacet instanceof ObjectSpecIdFacetDerivedFromClassName) {
                 ValidationFailure.raiseFormatted(
@@ -129,15 +129,15 @@ implements MetaModelRefiner, ObjectSpecIdFacetFactory {
                                 + "@PersistenceCapable(schema=...) to specify explicitly.",
                         objectSpec.getFullIdentifier(),
                         "isis.core.meta-model.validator.explicit-object-type");
-            } 
-                
+            }
+
             });
 
     }
 
     public static boolean check(final ObjectSpecification objectSpec) {
             //TODO
-            // as a special case, don't enforce this for fixture scripts... 
+            // as a special case, don't enforce this for fixture scripts...
             // we never invoke actions on fixture scripts anyway
 
         if(objectSpec.isAbstract()) {
@@ -163,9 +163,9 @@ implements MetaModelRefiner, ObjectSpecIdFacetFactory {
             if(!DomainServiceFacet.getNatureOfService(objectSpec).isPresent()) {
                 return false; //skip validation
             }
-            
+
             // don't check if domain service has only programmatic methods
-            return objectSpec.streamActions(MixedIn.INCLUDED).count()>0L;
+            return objectSpec.streamAnyActions(MixedIn.INCLUDED).count()>0L;
 
         }
         return false; //skip validation
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
index ddf6d8e..50bc768 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefault.java
@@ -68,7 +68,7 @@ import lombok.extern.log4j.Log4j2;
 @Service
 @Named("isis.metamodel.ApplicationFeatureRepositoryDefault")
 @Log4j2
-public class ApplicationFeatureRepositoryDefault 
+public class ApplicationFeatureRepositoryDefault
 implements ApplicationFeatureRepository {
 
     // -- caches
@@ -101,9 +101,9 @@ implements ApplicationFeatureRepository {
     }
 
     private boolean isEagerInitialize() {
-        ApplicationFeaturesInitConfiguration setting = 
+        ApplicationFeaturesInitConfiguration setting =
                 configuration.getCore().getRuntimeServices().getApplicationFeatures().getInit();
-        return setting == ApplicationFeaturesInitConfiguration.EAGER 
+        return setting == ApplicationFeaturesInitConfiguration.EAGER
                 || setting == ApplicationFeaturesInitConfiguration.EAGERLY;
     }
 
@@ -120,20 +120,20 @@ implements ApplicationFeatureRepository {
             return;
         }
         initializationState = InitializationState.INITIALIZED;
-        
+
         for (val spec : specificationLoader.snapshotSpecifications()) {
             createApplicationFeaturesFor(spec);
         }
-        
+
         val featuresByName = new HashMap<String, ApplicationFeatureId>();
         visitFeatureIdentifierByName(namespaceFeatures, featuresByName::put);
         visitFeatureIdentifierByName(typeFeatures, featuresByName::put);
         visitFeatureIdentifierByName(memberFeatures, featuresByName::put);
         this.featureIdentifiersByName = Collections.unmodifiableMap(featuresByName);
     }
-    
+
     private void visitFeatureIdentifierByName(
-            final Map<ApplicationFeatureId, ApplicationFeature> map, 
+            final Map<ApplicationFeatureId, ApplicationFeature> map,
             final BiConsumer<String, ApplicationFeatureId> onEntry) {
         map.forEach((k, v)->onEntry.accept(k.getFullyQualifiedName(), k));
     }
@@ -148,14 +148,14 @@ implements ApplicationFeatureRepository {
                 .collect(Collectors.toList());
         final List<ObjectAssociation> collections = spec.streamCollections(MixedIn.INCLUDED)
                 .collect(Collectors.toList());
-        final List<ObjectAction> actions = spec.streamActions(MixedIn.INCLUDED)
+        final List<ObjectAction> actions = spec.streamAnyActions(MixedIn.INCLUDED)
                 .collect(Collectors.toList());
 
         if (properties.isEmpty() && collections.isEmpty() && actions.isEmpty()) {
             return;
         }
 
-        
+
         final String logicalTypeName = spec.getLogicalTypeName();
         final ApplicationFeatureId typeFeatureId = ApplicationFeatureId.newType(logicalTypeName);
 
@@ -298,7 +298,7 @@ implements ApplicationFeatureRepository {
             final @Nullable SemanticsOf actionSemantics) {
         final ApplicationFeatureId featureId = ApplicationFeatureId.newMember(typeFeatureId.getFullyQualifiedName(), memberId);
 
-        final ApplicationFeatureDefault memberFeature = 
+        final ApplicationFeatureDefault memberFeature =
                 (ApplicationFeatureDefault)newApplicationFeature(featureId);
         memberFeature.setMemberSort(Optional.of(memberSort));
 
@@ -330,11 +330,11 @@ implements ApplicationFeatureRepository {
 
     protected boolean exclude(final ObjectSpecification spec) {
 
-        val excluded = spec.isMixin() 
-                || spec.isAbstract() 
+        val excluded = spec.isMixin()
+                || spec.isAbstract()
                 || spec.getBeanSort().isVetoed()
-                || spec.getBeanSort().isUnknown() 
-                || isBuiltIn(spec) 
+                || spec.getBeanSort().isUnknown()
+                || isBuiltIn(spec)
                 || isHidden(spec);
 
         if(excluded && log.isDebugEnabled()) {
@@ -364,12 +364,12 @@ implements ApplicationFeatureRepository {
     }
 
     // -- FACTORY
-    
+
     @Override
     public ApplicationFeature newApplicationFeature(ApplicationFeatureId featId) {
         return new ApplicationFeatureDefault(featId); // value type
     }
-    
+
     // -- packageFeatures, classFeatures, memberFeatures
 
     @Override
@@ -465,6 +465,6 @@ implements ApplicationFeatureRepository {
         initializeIfRequired();
         return featureIdentifiersByName;
     }
-    
+
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
index 4024dd1..9e16b10 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/GridSystemServiceAbstract.java
@@ -177,7 +177,7 @@ implements GridSystemService<G> {
 
         val oneToOneAssociationById = ObjectMember.mapById(objectSpec.streamProperties(MixedIn.INCLUDED));
         val oneToManyAssociationById = ObjectMember.mapById(objectSpec.streamCollections(MixedIn.INCLUDED));
-        val objectActionById = ObjectMember.mapById(objectSpec.streamActions(MixedIn.INCLUDED));
+        val objectActionById = ObjectMember.mapById(objectSpec.streamRuntimeActions(MixedIn.INCLUDED));
 
         final AtomicInteger propertySequence = new AtomicInteger(0);
         fcGrid.visit(new Grid.VisitorAdapter() {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBootstrap.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBootstrap.java
index 555b49c..e1466f9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBootstrap.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap3/GridSystemServiceBootstrap.java
@@ -176,7 +176,7 @@ public class GridSystemServiceBootstrap extends GridSystemServiceAbstract<BS3Gri
 
         val oneToOneAssociationById = ObjectMember.mapById(objectSpec.streamProperties(MixedIn.INCLUDED));
         val oneToManyAssociationById = ObjectMember.mapById(objectSpec.streamCollections(MixedIn.INCLUDED));
-        val objectActionById = ObjectMember.mapById(objectSpec.streamActions(MixedIn.INCLUDED));
+        val objectActionById = ObjectMember.mapById(objectSpec.streamRuntimeActions(MixedIn.INCLUDED));
 
         val propertyLayoutDataById = bs3Grid.getAllPropertiesById();
         val collectionLayoutDataById = bs3Grid.getAllCollectionsById();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
index 1a26ecc..7521da4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
@@ -267,7 +267,7 @@ class MetaModelExporter {
         }
 
         final List<Action> actions = domainClass.getActions().getAct();
-        specification.streamActions(MixedIn.INCLUDED)
+        specification.streamAnyActions(MixedIn.INCLUDED)
         .map(action->asXsdType(action, domainClassByObjectSpec, config))
         .forEach(actions::add);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index fe09bf7..34bf1c8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -79,7 +79,7 @@ public class MetaModelServiceDefault implements MetaModelService {
         if(domainType == null) {
             return null;
         }
-        
+
         return specificationLoader.specForType(domainType)
         .flatMap(spec->spec.lookupFacet(ObjectSpecIdFacet.class))
         .map(ObjectSpecIdFacet::value)
@@ -116,7 +116,7 @@ public class MetaModelServiceDefault implements MetaModelService {
             .filter(otma->!exclude(otma))
             .forEach(otma->rows.add(new DomainMemberDefault(spec, otma)));
 
-            spec.streamActions(MixedIn.INCLUDED)
+            spec.streamAnyActions(MixedIn.INCLUDED)
             .filter(action->!exclude(action))
             .forEach(action->rows.add(new DomainMemberDefault(spec, action)));
         }
@@ -161,19 +161,19 @@ public class MetaModelServiceDefault implements MetaModelService {
         if(objectSpec == null) {
             return BeanSort.UNKNOWN;
         }
-        
+
         if(objectSpec.getBeanSort().isUnknown()
                 && !(mode == Mode.RELAXED)) {
-        
+
             throw new IllegalArgumentException(String.format(
                     "Unable to determine what sort of domain object this is: '%s'. Originating domainType: '%s'",
                     objectSpec.getFullIdentifier(),
                     domainType.getName()
                     ));
         }
-        
+
         return objectSpec.getBeanSort();
-        
+
     }
 
     @Override
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
index d2bc4b0..b431e37 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
@@ -130,7 +130,7 @@ extends
      * @since 2.0
      */
     public default Optional<MixedInMember> getMixedInMember(ObjectSpecification onType) {
-        return streamActions(MixedIn.INCLUDED)
+        return streamAnyActions(MixedIn.INCLUDED)
                 .filter(MixedInMember.class::isInstance)
                 .map(MixedInMember.class::cast)
                 .filter(member->member.getMixinType() == onType)
@@ -439,8 +439,8 @@ extends
     default Stream<FacetHolder> streamFacetHolders(){
 
         val self = Stream.of(this);
-        val actions = streamActions(MixedIn.EXCLUDED);
-        val actionParameters = streamActions(MixedIn.EXCLUDED)
+        val actions = streamAnyActions(MixedIn.EXCLUDED);
+        val actionParameters = streamAnyActions(MixedIn.EXCLUDED)
                 .flatMap(action->action.getParameterCount()>0
                         ? action.getParameters().stream()
                         : Stream.empty());
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
index 6084ac1..62a5139 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
@@ -31,45 +31,45 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ActionType;
 
 public interface ObjectActionContainer {
-    
+
     // -- ACTION LOOKUP (INHERITANCE CONSIDERED)
-    
+
     /**
-     * Similar to {@link #getDeclaredAction(String, ActionType)}, 
+     * Similar to {@link #getDeclaredAction(String, ActionType)},
      * but also considering any inherited object members. (mixed-in included)
      * @param id
      * @param type
-     * 
-     * @implSpec If not found on the current 'type' search for the 'nearest' match in super-types, 
+     *
+     * @implSpec If not found on the current 'type' search for the 'nearest' match in super-types,
      * and if nothing found there, search the interfaces. Special care needs to be taken, as the
      * {@link ActionType} might be redeclared when inheriting from a super-type or interface.
      */
     Optional<ObjectAction> getAction(String id, @Nullable ActionType type);
-    
+
     default ObjectAction getActionElseFail(String id, @Nullable ActionType type) {
         return getAction(id, type)
-                .orElseThrow(()->_Exceptions.noSuchElement("id=%s type=%s", 
-                        id, 
+                .orElseThrow(()->_Exceptions.noSuchElement("id=%s type=%s",
+                        id,
                         type==null ? "any" : type.name()));
     }
 
     default Optional<ObjectAction> getAction(String id) {
         return getAction(id, null);
     }
-    
+
     default ObjectAction getActionElseFail(String id) {
         return getActionElseFail(id, null);
     }
-    
-    
+
+
     // -- ACTION LOOKUP, DECLARED ACTIONS (NO INHERITANCE CONSIDERED)
-    
+
     /**
      * Get the action object represented by the specified identity string. (mixed-in included)
      * <p>
      * The identity string can be either fully specified with parameters (as per
-     * {@link Identifier#toNameParmsIdentityString()} or in abbreviated form (
-     * {@link Identifier#toNameIdentityString()}).
+     * {@link Identifier#getMemberNameAndParameterClassNamesIdentityString()} or in abbreviated form (
+     * {@link Identifier#getMemberName()}).
      *
      * @see #getDeclaredAction(String)
      */
@@ -84,42 +84,69 @@ public interface ObjectActionContainer {
         return getDeclaredAction(id, null);
     }
 
-    // -- ACTION STREAM (W/ INHERITANCE)
-    
+    // -- ACTION STREAM (WITH INHERITANCE)
+
+    /**
+     * Returns a Stream of all actions of given {@code actionTypes}, with inheritance considered.
+     * @param actionTypes
+     * @param mixedIn - whether to include mixed in actions
+     * @param onActionOverloaded - callback on overloaded action detected
+     */
     Stream<ObjectAction> streamActions(
-            ImmutableEnumSet<ActionType> types, 
-            MixedIn contributed,
+            ImmutableEnumSet<ActionType> actionTypes,
+            MixedIn mixedIn,
             Consumer<ObjectAction> onActionOverloaded);
-    
+
+    /**
+     * Returns a Stream of all actions of given {@code actionTypes}, with inheritance considered.
+     * @param actionTypes
+     * @param mixedIn - whether to include mixed in actions
+     */
     default Stream<ObjectAction> streamActions(
-            ImmutableEnumSet<ActionType> types, 
-            MixedIn contributed) {
-        return streamActions(types, contributed, __->{});
+            ImmutableEnumSet<ActionType> actionTypes,
+            MixedIn mixedIn) {
+        return streamActions(actionTypes, mixedIn, __->{});
     }
-    
-    default Stream<ObjectAction> streamActions(ActionType type, MixedIn contributed) {
-        return streamActions(ImmutableEnumSet.of(type), contributed);
+
+    /**
+     * Returns a Stream of all actions of given {@code actionType}, with inheritance considered.
+     * @param actionType
+     * @param mixedIn - whether to include mixed in actions
+     */
+    default Stream<ObjectAction> streamActions(ActionType actionType, MixedIn mixedIn) {
+        return streamActions(ImmutableEnumSet.of(actionType), mixedIn);
     }
-    
-    default Stream<ObjectAction> streamActions(MixedIn contributed) {
-        return streamActions(ActionType.ANY, contributed);
+
+    /**
+     * Returns a Stream of all actions of any type, with inheritance considered.
+     * @param mixedIn - whether to include mixed in actions
+     */
+    default Stream<ObjectAction> streamAnyActions(MixedIn mixedIn) {
+        return streamActions(ActionType.ANY, mixedIn);
     }
-    
+
+    /**
+     * Returns a Stream of all actions enabled for the current runtime environment,
+     * with inheritance considered.
+     * @param mixedIn - whether to include mixed in actions
+     */
+    Stream<ObjectAction> streamRuntimeActions(MixedIn mixedIn);
+
     // -- ACTION STREAM (NO INHERITANCE)
 
     /**
      * Returns an array of actions of the specified type, including or excluding
      * contributed actions as required.
      */
-    Stream<ObjectAction> streamDeclaredActions(ImmutableEnumSet<ActionType> types, MixedIn contributed);
+    Stream<ObjectAction> streamDeclaredActions(ImmutableEnumSet<ActionType> actionTypes, MixedIn mixedIn);
 
-    default Stream<ObjectAction> streamDeclaredActions(ActionType type, MixedIn contributed) {
-        return streamDeclaredActions(ImmutableEnumSet.of(type), contributed);
+    default Stream<ObjectAction> streamDeclaredActions(ActionType type, MixedIn mixedIn) {
+        return streamDeclaredActions(ImmutableEnumSet.of(type), mixedIn);
     }
-    
-    default Stream<ObjectAction> streamDeclaredActions(MixedIn contributed) {
-        return streamDeclaredActions(ActionType.ANY, contributed);
+
+    default Stream<ObjectAction> streamDeclaredActions(MixedIn mixedIn) {
+        return streamDeclaredActions(ActionType.ANY, mixedIn);
     }
 
-    
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
index 7862914..33ff0f9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociationContainer.java
@@ -26,30 +26,30 @@ import org.apache.isis.commons.internal.exceptions._Exceptions;
 import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
 
 public interface ObjectAssociationContainer {
-    
+
     // -- ASSOCIATION LOOKUP, PROPERTIES/COLLECTIONS (INHERITANCE CONSIDERED)
-    
+
     /**
      * Same as {@link #getDeclaredAssociation(String)}, but also considering any inherited object members.
      * @param id
-     * 
-     * @implSpec If not found on the current 'type' search for the 'nearest' match in super-types, 
-     * and if nothing found there, search the interfaces.  
+     *
+     * @implSpec If not found on the current 'type' search for the 'nearest' match in super-types,
+     * and if nothing found there, search the interfaces.
      */
     Optional<ObjectAssociation> getAssociation(String id);
-    
+
     default ObjectAssociation getAssociationElseFail(String id) {
         return getAssociation(id)
                 .orElseThrow(()->_Exceptions.noSuchElement("id=%s", id));
     }
-    
+
     default OneToOneAssociation getPropertyElseFail(String id) {
         return getAssociation(id)
                 .filter(ObjectAssociation.Predicates.PROPERTIES)
                 .map(OneToOneAssociation.class::cast)
                 .orElseThrow(()->_Exceptions.noSuchElement("id=%s", id));
     }
-    
+
     default OneToManyAssociation getCollectionElseFail(String id) {
         return getAssociation(id)
                 .filter(ObjectAssociation.Predicates.COLLECTIONS)
@@ -61,24 +61,25 @@ public interface ObjectAssociationContainer {
 
     /**
      * Get the field object representing the field with the specified field
-     * identifier.
+     * identifier, that is the association with the given
+     * {@link ObjectAssociation#getId() id}.
      *
      * Throw a {@link ObjectSpecificationException} if no such association
      * exists.
      */
     Optional<ObjectAssociation> getDeclaredAssociation(String id);
-    
+
     // -- ASSOCIATION STREAMS (INHERITANCE CONSIDERED)
 
     /**
      * Same as {@link #streamDeclaredAssociations(MixedIn)}, but also considering any inherited object members.
      * @param contributed
-     * 
-     * @implSpec Walk through the type hierarchy nearest to farthest and add any ObjectAssociation to the stream, 
+     *
+     * @implSpec Walk through the type hierarchy nearest to farthest and add any ObjectAssociation to the stream,
      * except don't add ObjectAssociations that already have been added (due to inheritance).
      */
     Stream<ObjectAssociation> streamAssociations(MixedIn contributed);
-    
+
 
     /**
      * All {@link ObjectAssociation association}s that represent
@@ -99,9 +100,9 @@ public interface ObjectAssociationContainer {
                 .filter(ObjectAssociation.Predicates.COLLECTIONS)
                 .map(OneToManyAssociation.class::cast);
     }
-    
+
     // -- ASSOCIATION STREAMS (INHERITANCE NOT CONSIDERED)
-    
+
     /**
      * Return all the fields that exist in an object of this specification,
      * although they need not all be accessible or visible.
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index 455cd8f..7273e07 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -698,11 +698,6 @@ implements ObjectSpecification {
         return Optional.empty();
     }
 
-
-
-    /**
-     * The association with the given {@link ObjectAssociation#getId() id}.
-     */
     @Override
     public Optional<ObjectAssociation> getDeclaredAssociation(final String id) {
         introspectUpTo(IntrospectionState.FULLY_INTROSPECTED);
@@ -711,7 +706,13 @@ implements ObjectSpecification {
                 .findFirst();
     }
 
-
+    @Override
+    public Stream<ObjectAction> streamRuntimeActions(MixedIn mixedIn) {
+        val actionTypes = getMetaModelContext().getSystemEnvironment().isPrototyping()
+                ? ActionType.USER_AND_PROTOTYPE
+                : ActionType.USER_ONLY;
+        return streamActions(actionTypes, mixedIn);
+    }
 
     @Override
     public Stream<ObjectAction> streamDeclaredActions(
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 5459595..45aeb1a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -24,9 +24,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.function.BiConsumer;
-import java.util.stream.Stream;
 
-import org.apache.isis.applib.Identifier;
+import javax.annotation.Nullable;
+
 import org.apache.isis.applib.services.metamodel.BeanSort;
 import org.apache.isis.commons.collections.ImmutableEnumSet;
 import org.apache.isis.commons.internal.base._Lazy;
@@ -270,39 +270,24 @@ implements FacetHolder {
     // -- getObjectAction
 
     @Override
-    public Optional<ObjectAction> getDeclaredAction(final String id, final ActionType type) {
+    public Optional<ObjectAction> getDeclaredAction(
+            final @Nullable String id,
+            final @Nullable ActionType type) {
+
         introspectUpTo(IntrospectionState.FULLY_INTROSPECTED);
 
-        final Stream<ObjectAction> actions =
-                streamDeclaredActions(
+        return id == null
+                ? Optional.empty()
+                : streamDeclaredActions(
                         type==null
                             ? ActionType.ANY
                             : ImmutableEnumSet.of(type),
-                        MixedIn.INCLUDED);
-        return firstAction(actions, id);
-    }
-
-    private static Optional<ObjectAction> firstAction(
-            final Stream<ObjectAction> candidateActions,
-            final String id) {
-
-        if (id == null) {
-            return Optional.empty();
-        }
-
-        return candidateActions
-                .filter(action->{
-                    final Identifier identifier = action.getIdentifier();
-
-                    if (id.equals(identifier.getMemberNameAndParameterClassNamesIdentityString())) {
-                        return true;
-                    }
-                    if (id.equals(identifier.getMemberName())) {
-                        return true;
-                    }
-                    return false;
-                })
-                .findFirst();
+                        MixedIn.INCLUDED)
+                    .filter(action->
+                        id.equals(action.getIdentifier().getMemberNameAndParameterClassNamesIdentityString())
+                                || id.equals(action.getIdentifier().getMemberName())
+                    )
+                    .findFirst();
     }
 
     @Override
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
index 3f048fe..04f34b6 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/appfeat/ApplicationFeatureRepositoryDefaultTest.java
@@ -30,6 +30,13 @@ import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.services.appfeat.ApplicationFeature;
@@ -54,13 +61,6 @@ import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsInAnyOrder;
-
 public class ApplicationFeatureRepositoryDefaultTest {
 
     @Rule
@@ -70,7 +70,7 @@ public class ApplicationFeatureRepositoryDefaultTest {
     @Mock OneToOneAssociation mockProp;
     @Mock OneToManyAssociation mockColl;
     @Mock ObjectAction mockAct;
-    
+
     ObjectAction mockActThatIsHidden;
 
     @Mock FactoryService mockFactoryService;
@@ -78,12 +78,12 @@ public class ApplicationFeatureRepositoryDefaultTest {
     @Mock SpecificationLoader mockSpecificationLoader;
 
     protected ApplicationFeatureRepositoryDefault applicationFeatureRepository;
-    
+
     @Before
     public void setUp() throws Exception {
 
         applicationFeatureRepository = new ApplicationFeatureRepositoryDefault(
-                /*configuration*/ null, 
+                /*configuration*/ null,
                 mockSpecificationLoader);
 
         mockActThatIsHidden = context.mock(ObjectAction.class, "mockActThatIsHidden");
@@ -92,7 +92,7 @@ public class ApplicationFeatureRepositoryDefaultTest {
     public static class Load extends ApplicationFeatureRepositoryDefaultTest {
 
         public static class Bar {}
-        
+
         private static ApplicationFeature newApplicationFeature(ApplicationFeatureId featId) {
             return new ApplicationFeatureDefault(featId);
         }
@@ -131,8 +131,11 @@ public class ApplicationFeatureRepositoryDefaultTest {
 
                 allowing(mockSpec).streamDeclaredActions(with(MixedIn.INCLUDED));
                 will(returnValue(actions.stream()));
-                
-                allowing(mockSpec).streamActions(with(MixedIn.INCLUDED));
+
+                allowing(mockSpec).streamAnyActions(with(MixedIn.INCLUDED));
+                will(returnValue(actions.stream()));
+
+                allowing(mockSpec).streamRuntimeActions(with(MixedIn.INCLUDED));
                 will(returnValue(actions.stream()));
 
                 allowing(mockProp).getId();
@@ -261,7 +264,7 @@ public class ApplicationFeatureRepositoryDefaultTest {
         private static ApplicationFeature newApplicationFeature(ApplicationFeatureId featId) {
             return new ApplicationFeatureDefault(featId);
         }
-        
+
         @Override
         @Before
         public void setUp() throws Exception {
@@ -290,7 +293,7 @@ public class ApplicationFeatureRepositoryDefaultTest {
 
 
             // when
-            final ApplicationFeatureId applicationFeatureId = 
+            final ApplicationFeatureId applicationFeatureId =
                     applicationFeatureRepository.addClassParent(classFeatureId);
 
             // then
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
index c4d97c3..3149634 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
@@ -52,7 +52,7 @@ import org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState;
 import lombok.Synchronized;
 import lombok.val;
 
-public class ObjectSpecificationStub 
+public class ObjectSpecificationStub
 extends FacetHolderImpl
 implements ObjectSpecification {
 
@@ -60,7 +60,7 @@ implements ObjectSpecification {
     public List<ObjectAssociation> fields = _Lists.newArrayList();
     private String title;
     /**
-     * lazily derived, see {@link #getLogicalType()} 
+     * lazily derived, see {@link #getLogicalType()}
      */
     private LogicalType logicalType;
 
@@ -163,17 +163,17 @@ implements ObjectSpecification {
     public Optional<ObjectAction> getDeclaredAction(final String id, final ActionType type) {
         val nameParmsIdentityString = id.substring(0, id.indexOf('('));
         val action = lookupObjectAction(nameParmsIdentityString);
-        
+
         if(type==null) {
             return action;
         }
-        
+
         if (action.isPresent()
                 && action.get().getType() == type) {
             return action;
         }
         return Optional.empty();
-        
+
     }
 
     @Override
@@ -304,7 +304,7 @@ implements ObjectSpecification {
     public Stream<ObjectAction> streamDeclaredActions(ImmutableEnumSet<ActionType> types, MixedIn contributed) {
         return null;
     }
-    
+
     // /////////////////////////////////////////////////////////
     // view models and wizards
     // /////////////////////////////////////////////////////////
@@ -355,16 +355,16 @@ implements ObjectSpecification {
         // poorly implemented, inheritance not supported
         return getDeclaredAction(id, type);
     }
-    
+
     @Override
     public Stream<ObjectAction> streamActions(
-            ImmutableEnumSet<ActionType> types, 
+            ImmutableEnumSet<ActionType> types,
             MixedIn contributed,
             final Consumer<ObjectAction> onActionOverloaded) {
         // poorly implemented, inheritance not supported
         return streamDeclaredActions(contributed);
     }
-    
+
     @Override
     public Optional<ObjectAssociation> getAssociation(String id) {
         // poorly implemented, inheritance not supported
@@ -377,4 +377,12 @@ implements ObjectSpecification {
         return streamDeclaredAssociations(contributed);
     }
 
+    @Override
+    public Stream<ObjectAction> streamRuntimeActions(MixedIn mixedIn) {
+        val actionTypes = getMetaModelContext().getSystemEnvironment().isPrototyping()
+                ? ActionType.USER_AND_PROTOTYPE
+                : ActionType.USER_ONLY;
+        return streamActions(actionTypes, mixedIn);
+    }
+
 }
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
index 4b063a8..7b371be 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/WrapperFactoryDefault.java
@@ -442,7 +442,7 @@ public class WrapperFactoryDefault implements WrapperFactory {
         // (contributed properties and collections are read-only).
         final ObjectActionMixedIn targetAction = specificationLoader
         .specForType(mixedInClass)
-        .flatMap(mixedInSpec->mixedInSpec.streamActions(MixedIn.INCLUDED)
+        .flatMap(mixedInSpec->mixedInSpec.streamAnyActions(MixedIn.INCLUDED)
                 .filter(ObjectActionMixedIn.class::isInstance)
                 .map(ObjectActionMixedIn.class::cast)
                 .filter(x -> x.hasMixinAction((ObjectAction) mixinMember))
@@ -606,18 +606,18 @@ public class WrapperFactoryDefault implements WrapperFactory {
             serviceInjector.injectServicesInto(this);
             return interactionFactory.callAuthenticated(authentication, this::updateDomainObjectHonoringTransactionalPropagation);
         }
-        
+
         private R updateDomainObjectHonoringTransactionalPropagation() {
             return transactionService.callTransactional(propagation, this::updateDomainObject)
                     .optionalElseFail()
-                    .orElse(null);            
+                    .orElse(null);
         }
-        
+
         private R updateDomainObject() {
-            
+
             val childCommand = interactionContextProvider.get().currentInteractionElseFail().getCommand();
             childCommand.updater().setParent(parentCommand);
-            
+
             val bookmark = commandExecutorService.executeCommand(commandDto, childCommand.updater());
             if (bookmark == null) {
                 return null;
@@ -627,9 +627,9 @@ public class WrapperFactoryDefault implements WrapperFactory {
                 domainObject = repositoryService.detach(domainObject);
             }
             return domainObject;
-                        
+
         }
-        
-        
+
+
     }
 }
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java
index 88e2d0a..0106a01 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/wrapper/handlers/DomainObjectInvocationHandler.java
@@ -128,8 +128,8 @@ extends DelegatingInvocationHandlerDefault<T> {
 
         entityFacet = targetAdapter.getSpecification()
                 .getFacet(EntityFacet.class);
-        
-        this.mixeeAdapter = mixeeAdapter; 
+
+        this.mixeeAdapter = mixeeAdapter;
     }
 
     /**
@@ -226,7 +226,7 @@ extends DelegatingInvocationHandlerDefault<T> {
 
                 if (mixeeAdapter == null) {
                     throw _Exceptions.illegalState(
-                            "Missing the required mixeeAdapter for action '%s'", 
+                            "Missing the required mixeeAdapter for action '%s'",
                             objectAction.getId());
                 }
                 final ObjectMember mixinMember = determineMixinMember(mixeeAdapter, objectAction);
@@ -262,7 +262,7 @@ extends DelegatingInvocationHandlerDefault<T> {
             return null;
         }
         val specification = domainObjectAdapter.getSpecification();
-        val objectActions = specification.streamActions(MixedIn.INCLUDED);
+        val objectActions = specification.streamAnyActions(MixedIn.INCLUDED);
         val objectAssociations = specification.streamAssociations(MixedIn.INCLUDED);
 
         final Stream<ObjectMember> objectMembers = Stream.concat(objectActions, objectAssociations);
diff --git a/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java b/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
index bcabb68..ce4505c 100644
--- a/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
+++ b/regressiontests/stable-domainmodel/src/test/java/org/apache/isis/testdomain/domainmodel/DomainModelTest_usingGoodDomain.java
@@ -119,13 +119,13 @@ class DomainModelTest_usingGoodDomain {
         val validateDomainModel = new DomainModelValidator(serviceRegistry);
         validateDomainModel.throwIfInvalid(); // should not throw
     }
-    
+
     @Test
     void reservedPrefixShouldBeAllowed_onExplicitAction() {
-     
+
         val holderSpec = specificationLoader.loadSpecification(ProperMemberSupport.class,
                 IntrospectionState.FULLY_INTROSPECTED);
-        
+
         val prefixed_action = holderSpec.getActionElseFail("hideMe");
         assertNotNull(prefixed_action);
         assertEquals("hideMe", prefixed_action.getId());
@@ -249,7 +249,7 @@ class DomainModelTest_usingGoodDomain {
         assertEquals("foo", super_action.getName());
         assertEquals("bar", super_action.getDescription());
 
-        assertEquals(1L, holderSpec.streamActions(MixedIn.EXCLUDED)
+        assertEquals(1L, holderSpec.streamAnyActions(MixedIn.EXCLUDED)
                 .filter(prop->prop.getId().equals("sampleActionOverride"))
                 .count());
 
@@ -278,77 +278,77 @@ class DomainModelTest_usingGoodDomain {
                 .count());
 
     }
-    
+
     @Test
     void elementTypes_shouldBeIntrospected_whenDiscoveredViaGenerics_usingNoWildcards() {
-        
+
         // when using generic type (no wild-cards)
-        
+
         val vmSpec = specificationLoader.loadSpecification(ProperElementTypeVm.class,
                 IntrospectionState.FULLY_INTROSPECTED);
-        
+
         val concreteColl = vmSpec.getCollectionElseFail("concreteColl");
         val concreteCollSpec = concreteColl.getSpecification();
-        
+
         assertEquals(ElementTypeConcrete.class, concreteCollSpec.getCorrespondingClass());
         assertEquals(BeanSort.VIEW_MODEL, concreteCollSpec.getBeanSort());
         assertHasAction(concreteCollSpec, "abstractAction");
         assertHasAction(concreteCollSpec, "interfaceAction");
         assertHasProperty(concreteCollSpec, "abstractProp");
         assertHasProperty(concreteCollSpec, "interfaceProp");
-        
+
         val interfaceColl = vmSpec.getCollectionElseFail("interfaceColl");
         val interfaceCollSpec = interfaceColl.getSpecification();
-        
+
         assertEquals(ElementTypeInterface.class, interfaceCollSpec.getCorrespondingClass());
         assertEquals(BeanSort.ABSTRACT, interfaceCollSpec.getBeanSort());
         assertHasAction(interfaceCollSpec, "interfaceAction");
         assertHasProperty(interfaceCollSpec, "interfaceProp");
-        
+
         val abstractColl = vmSpec.getCollectionElseFail("abstractColl");
         val abstractCollSpec = abstractColl.getSpecification();
-        
+
         assertEquals(ElementTypeAbstract.class, abstractCollSpec.getCorrespondingClass());
         assertEquals(BeanSort.ABSTRACT, abstractCollSpec.getBeanSort());
         assertHasAction(abstractCollSpec, "abstractAction");
         assertHasProperty(abstractCollSpec, "abstractProp");
-        
+
     }
-    
+
     @Test
     void elementTypes_shouldBeIntrospected_whenDiscoveredViaGenerics_usingWildcards() {
-        
+
         // when using generic type (w/ wild-cards)
-        
+
         val vmSpec = specificationLoader.loadSpecification(ProperElementTypeVm.class,
                 IntrospectionState.FULLY_INTROSPECTED);
-        
+
         val concreteColl = vmSpec.getCollectionElseFail("concreteColl2");
         val concreteCollSpec = concreteColl.getSpecification();
-        
+
         assertEquals(ElementTypeConcrete.class, concreteCollSpec.getCorrespondingClass());
         assertEquals(BeanSort.VIEW_MODEL, concreteCollSpec.getBeanSort());
         assertHasAction(concreteCollSpec, "abstractAction");
         assertHasAction(concreteCollSpec, "interfaceAction");
         assertHasProperty(concreteCollSpec, "abstractProp");
         assertHasProperty(concreteCollSpec, "interfaceProp");
-        
+
         val interfaceColl = vmSpec.getCollectionElseFail("interfaceColl2");
         val interfaceCollSpec = interfaceColl.getSpecification();
-        
+
         assertEquals(ElementTypeInterface.class, interfaceCollSpec.getCorrespondingClass());
         assertEquals(BeanSort.ABSTRACT, interfaceCollSpec.getBeanSort());
         assertHasAction(interfaceCollSpec, "interfaceAction");
         assertHasProperty(interfaceCollSpec, "interfaceProp");
-        
+
         val abstractColl = vmSpec.getCollectionElseFail("abstractColl2");
         val abstractCollSpec = abstractColl.getSpecification();
-        
+
         assertEquals(ElementTypeAbstract.class, abstractCollSpec.getCorrespondingClass());
         assertEquals(BeanSort.ABSTRACT, abstractCollSpec.getBeanSort());
         assertHasAction(abstractCollSpec, "abstractAction");
         assertHasProperty(abstractCollSpec, "abstractProp");
-        
+
     }
 
     // -- HELPER
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
index fbdf2fd..c265f73 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/DomainObjectReprRenderer.java
@@ -56,19 +56,19 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
     private static final String X_RO_DOMAIN_TYPE = "x-ro-domain-type";
 
     public static LinkBuilder newLinkToBuilder(
-            final IResourceContext resourceContext, 
-            final Rel rel, 
+            final IResourceContext resourceContext,
+            final Rel rel,
             final ManagedObject objectAdapter) {
-        
+
         final String objectRef = ManagedObjects.stringifyElseFail(objectAdapter, "/");
         final String url = "objects/" + objectRef;
         return LinkBuilder.newBuilder(resourceContext, rel.getName(), RepresentationType.DOMAIN_OBJECT, url).withTitle(objectAdapter.titleString(null));
     }
 
     public static LinkBuilder newLinkToObjectLayoutBuilder(
-            final IResourceContext resourceContext, 
+            final IResourceContext resourceContext,
             final ManagedObject objectAdapter) {
-        
+
         final Rel rel = Rel.OBJECT_LAYOUT;
         final String objectRef = ManagedObjects.stringifyElseFail(objectAdapter, "/");
         final String url = "objects/" + objectRef + "/object-layout";
@@ -76,9 +76,9 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
     }
 
     public static LinkBuilder newLinkToObjectIconBuilder(
-            final IResourceContext resourceContext, 
+            final IResourceContext resourceContext,
             final ManagedObject objectAdapter) {
-        
+
         final Rel rel = Rel.OBJECT_ICON;
         final String objectRef = ManagedObjects.stringifyElseFail(objectAdapter, "/");
         final String url = "objects/" + objectRef + "/image";
@@ -150,8 +150,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         this.objectAdapter = objectAdapter;
         String domainTypeHref = DomainTypeReprRenderer
                 .newLinkToBuilder(
-                        getResourceContext(), 
-                        Rel.DOMAIN_TYPE, 
+                        getResourceContext(),
+                        Rel.DOMAIN_TYPE,
                         objectAdapter.getSpecification())
                 .build()
                 .getString("href");
@@ -171,7 +171,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         if (!(mode.isArgs())) {
 
             val oidIfAny = objectAdapter.getBookmark();
-            
+
             // self, extensions.oid
             if (ManagedObjects.isIdentifiable(objectAdapter)) {
                 if (includesSelf) {
@@ -300,7 +300,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
 
             if (mode.isRegular()) {
                 final Stream<ObjectAction> actions = objectAdapter.getSpecification()
-                        .streamActions(MixedIn.INCLUDED);
+                        .streamAnyActions(MixedIn.INCLUDED);
 
                 addActions(objectAdapter, actions, appendTo);
             }
@@ -369,7 +369,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
                     new ObjectCollectionReprRenderer(getResourceContext(), linkFollowerForColl, collection.getId(), collectionRepresentation);
 
             val where = resourceContext.getWhere();
-            
+
             renderer.with(ManagedCollection.of(objectAdapter, collection, where)).usingLinkTo(linkToBuilder);
             if(mode.isEventSerialization()) {
                 renderer.asEventSerialization();
@@ -380,8 +380,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
     }
 
     private void addActions(
-            final ManagedObject objectAdapter, 
-            final Stream<ObjectAction> actions, 
+            final ManagedObject objectAdapter,
+            final Stream<ObjectAction> actions,
             final JsonRepresentation members) {
 
         actions
@@ -391,12 +391,12 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         })
         .forEach(action->{
             final LinkFollowSpecs linkFollowSpecs = getLinkFollowSpecs().follow("members["+action.getId()+"]");
-            final ObjectActionReprRenderer renderer = 
-                    new ObjectActionReprRenderer(getResourceContext(), linkFollowSpecs, action.getId(), 
+            final ObjectActionReprRenderer renderer =
+                    new ObjectActionReprRenderer(getResourceContext(), linkFollowSpecs, action.getId(),
                             JsonRepresentation.newMap());
 
             val where = resourceContext.getWhere();
-            
+
             renderer.with(ManagedAction.of(objectAdapter, action, where)).usingLinkTo(linkToBuilder);
             members.mapPut(action.getId(), renderer.render());
         });
@@ -458,7 +458,7 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
 
 
     public static Object valueOrRef(IResourceContext context, JsonValueEncoder jsonValueEncoder, ManagedObject adapter) {
-        
+
         val spec = adapter.getSpecification();
         if(spec.isValue()) {
             String format = null; // TODO
@@ -467,8 +467,8 @@ public class DomainObjectReprRenderer extends ReprRendererAbstract<DomainObjectR
         val titleFacet = spec.getFacet(TitleFacet.class);
         final String title = titleFacet.title(adapter);
         return DomainObjectReprRenderer.newLinkToBuilder(
-                context, 
-                Rel.VALUE, 
+                context,
+                Rel.VALUE,
                 adapter)
                 .withTitle(title)
                 .build();
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java
index 0515334..f06d1e4 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domaintypes/DomainTypeReprRenderer.java
@@ -18,14 +18,11 @@
  */
 package org.apache.isis.viewer.restfulobjects.rendering.domaintypes;
 
-import java.util.stream.Stream;
-
 import com.fasterxml.jackson.databind.node.NullNode;
 
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.MixedIn;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
@@ -96,7 +93,7 @@ public class DomainTypeReprRenderer extends ReprRendererAbstract<DomainTypeReprR
     private void addMembers() {
         final JsonRepresentation membersList = JsonRepresentation.newArray();
         representation.mapPut("members", membersList);
-        
+
         objectSpecification.streamAssociations(MixedIn.EXCLUDED)
         .forEach(association->{
             if (association.isOneToOneAssociation()) {
@@ -110,12 +107,11 @@ public class DomainTypeReprRenderer extends ReprRendererAbstract<DomainTypeReprR
             }
         });
 
-        final Stream<ObjectAction> actions = objectSpecification.streamActions(MixedIn.INCLUDED);
-
-        actions.forEach(action->{
+        objectSpecification.streamAnyActions(MixedIn.INCLUDED)
+        .forEach(action->{
             final LinkBuilder linkBuilder = ActionDescriptionReprRenderer
                     .newLinkToBuilder(getResourceContext(), Rel.ACTION, objectSpecification, action);
-            membersList.arrayAdd(linkBuilder.build());            
+            membersList.arrayAdd(linkBuilder.build());
         });
 
     }
diff --git a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java
index 39394a9..aa577ea 100644
--- a/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java
+++ b/viewers/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/service/swagger/internal/Generation.java
@@ -173,7 +173,7 @@ class Generation {
         for (final ObjectSpecification objectSpec :  allSpecs) {
             objectSpec.streamAssociations(MixedIn.INCLUDED)
             .collect(Collectors.toList());
-            objectSpec.streamActions(MixedIn.INCLUDED)
+            objectSpec.streamAnyActions(MixedIn.INCLUDED)
             .collect(Collectors.toList());
         }
     }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
index 40db444..2dff2bf 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
@@ -19,19 +19,13 @@
 package org.apache.isis.viewer.wicket.ui.components.collection;
 
 import java.io.Serializable;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
-import org.apache.isis.commons.collections.ImmutableEnumSet;
-import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.MixedIn;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
-import org.apache.isis.core.runtime.context.IsisAppCommonContext;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
 import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsProvider;
 
@@ -49,35 +43,28 @@ public class AssociatedWithActionsHelper implements Serializable {
         this.collectionModel = collectionModel;
     }
 
-    public List<ObjectAction> getAssociatedActions(final SpecificationLoader specLoader) {
+    //TODO refactor: move to EntityCollectionModel
+    public Can<ObjectAction> getAssociatedActions(final SpecificationLoader specLoader) {
 
         if(collectionModel.isStandalone()) {
-            return Collections.emptyList();
+            return Can.empty();
         }
         final OneToManyAssociation collection = collectionModel.getCollectionMemento()
                 .getCollection(specLoader);
 
-        final ObjectSpecification objectSpec = getObjectSpecification();
-
-        val actionTypes = inferActionTypes(collectionModel.getCommonContext());
-        final Stream<ObjectAction> objectActions = objectSpec.streamActions(actionTypes, MixedIn.INCLUDED);
-
-        return objectActions
+        return getObjectSpecification()
+                .streamRuntimeActions(MixedIn.INCLUDED)
                 .filter(ObjectAction.Predicates.associatedWithAndWithCollectionParameterFor(collection))
-                .collect(Collectors.toList());
+                .collect(Can.toCan());
     }
 
+    // -- HELPER
+
+    //TODO refactor: move to EntityCollectionModel
     private ObjectSpecification getObjectSpecification() {
         val parentMemento = collectionModel.getParentObjectAdapterMemento();
         val parentAdapter = collectionModel.getCommonContext().reconstructObject(parentMemento);
         return parentAdapter.getSpecification();
     }
 
-    private ImmutableEnumSet<ActionType> inferActionTypes(IsisAppCommonContext commonContext) {
-        if (commonContext.getSystemEnvironment().isPrototyping()) {
-            return ActionType.USER_AND_PROTOTYPE;
-        }
-        return ActionType.USER_ONLY;
-    }
-
 }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
index c2c3984..1728f5d 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -56,8 +56,8 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel
  * Panel for rendering entity collection; analogous to (any concrete subclass
  * of) {@link ScalarPanelAbstract}.
  */
-public class CollectionPanel 
-extends PanelAbstract<List<ManagedObject>, EntityCollectionModel> 
+public class CollectionPanel
+extends PanelAbstract<List<ManagedObject>, EntityCollectionModel>
 implements CollectionSelectorProvider, BulkActionsProvider {
 
     private static final long serialVersionUID = 1L;
@@ -138,7 +138,7 @@ implements CollectionSelectorProvider, BulkActionsProvider {
     public ObjectAdapterToggleboxColumn getToggleboxColumn() {
 
         if(toggleboxColumn == null) {
-            final List<ObjectAction> associatedActions =
+            val associatedActions =
                     associatedWithActionsHelper.getAssociatedActions(getSpecificationLoader());
 
             val entityCollectionModel = getModel();
@@ -147,7 +147,7 @@ implements CollectionSelectorProvider, BulkActionsProvider {
             }
 
             toggleboxColumn = new ObjectAdapterToggleboxColumn(super.getCommonContext());
-            
+
             val handler = new OnSelectionHandler() {
 
                 private static final long serialVersionUID = 1L;
@@ -157,9 +157,9 @@ implements CollectionSelectorProvider, BulkActionsProvider {
                         final Component context,
                         final ManagedObject selectedAdapter,
                         final AjaxRequestTarget ajaxRequestTarget) {
-                    
+
                     val togglePanel = (ContainedToggleboxPanel) context;
-                    
+
                     val isSelected = getModel().toggleSelectionOn(selectedAdapter);
                     togglePanel.setModel(isSelected); // sync the checkbox's model
                 }