You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/10/14 09:44:01 UTC

[11/14] isis git commit: ISIS-1213: renamed metamodel classes ("...Impl" to "...Default"); derive name of ObjectActionMixedIn from mixin type (if "_"); simplified logic of #getParameters; also...

ISIS-1213: renamed metamodel classes ("...Impl" to "...Default"); derive name of ObjectActionMixedIn from mixin type (if "_"); simplified logic of #getParameters; also...

renamed:
- ObjectActionImpl to ObjectActionDefault
- OneToOneAssociationImpl to OneToOneAssociationDefault
- OneToManyAssociationImpl to OneToManyAssociationDefault
- OneToOneActionParameterImpl to OneToOneActionParameterDefault

also:
- reduced number of methods subclassed under ObjectMemberAbstract by introducing overridable getFacetHolder()
  - OneToOneAssociationContributee
  -  OneToManyAssociationContributee
- similarly for ObjectActionParameterAbstract


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/6c888136
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/6c888136
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/6c888136

Branch: refs/heads/master
Commit: 6c888136560b8648df110498cf5eb69f591095ed
Parents: 9f251d9
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Oct 13 21:34:29 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Oct 13 21:34:29 2015 +0100

----------------------------------------------------------------------
 .../core/commons/lang/StringExtensions.java     |   4 +-
 .../specimpl/ObjectActionContributee.java       |  17 +-
 .../specimpl/ObjectActionDefault.java           | 531 ++++++++++++++++++
 .../specloader/specimpl/ObjectActionImpl.java   | 535 -------------------
 .../specimpl/ObjectActionMixedIn.java           |  46 +-
 .../specimpl/ObjectActionParameterAbstract.java |  44 +-
 .../specimpl/ObjectMemberAbstract.java          |  34 +-
 .../specimpl/ObjectSpecificationAbstract.java   |  20 +-
 .../OneToManyAssociationContributee.java        |  65 +--
 .../specimpl/OneToManyAssociationDefault.java   | 298 +++++++++++
 .../specimpl/OneToManyAssociationImpl.java      | 298 -----------
 .../OneToOneActionParameterContributee.java     |   2 +-
 .../OneToOneActionParameterDefault.java         |  35 ++
 .../specimpl/OneToOneActionParameterImpl.java   |  35 --
 .../OneToOneActionParameterMixedIn.java         |   3 +-
 .../OneToOneAssociationContributee.java         |  56 +-
 .../specimpl/OneToOneAssociationDefault.java    | 345 ++++++++++++
 .../specimpl/OneToOneAssociationImpl.java       | 356 ------------
 .../dflt/ObjectSpecificationDefault.java        |  12 +-
 .../specimpl/ObjectActionMixedInTest.java       |  44 ++
 ...ParameterAbstractTest_getId_and_getName.java |   5 +-
 .../runtime/system/ObjectActionDefaultTest.java | 107 ++++
 .../runtime/system/ObjectActionImplTest.java    | 107 ----
 .../system/OneToManyAssociationDefaultTest.java | 188 +++++++
 .../system/OneToManyAssociationImplTest.java    | 188 -------
 ...WrapperFactoryDefaultTest_wrappedObject.java |   4 +-
 26 files changed, 1692 insertions(+), 1687 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringExtensions.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringExtensions.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringExtensions.java
index 76b7f2d..8c3dfb7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringExtensions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringExtensions.java
@@ -560,7 +560,9 @@ public final class StringExtensions {
     }
 
     public static String asCapitalizedName(final String extendee) {
-        return Character.toUpperCase(extendee.charAt(0)) + extendee.substring(1);
+
+        return Character.toUpperCase(extendee.charAt(0)) +
+                extendee.substring(1);
     }
 
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
index fe1a5df..117d2e4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
@@ -19,13 +19,15 @@ package org.apache.isis.core.metamodel.specloader.specimpl;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+
 import com.google.common.collect.Lists;
+
 import org.apache.isis.applib.Identifier;
-import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
 import org.apache.isis.applib.annotation.Bulk;
 import org.apache.isis.applib.annotation.InvokedOn;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.applib.services.actinvoc.ActionInvocationContext;
 import org.apache.isis.applib.services.bookmark.Bookmark;
 import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.Command.Executor;
@@ -39,8 +41,8 @@ import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetHolderImpl;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
-import org.apache.isis.core.metamodel.facets.actions.bulk.BulkFacet;
 import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
+import org.apache.isis.core.metamodel.facets.actions.bulk.BulkFacet;
 import org.apache.isis.core.metamodel.interactions.InteractionUtils;
 import org.apache.isis.core.metamodel.interactions.UsabilityContext;
 import org.apache.isis.core.metamodel.interactions.VisibilityContext;
@@ -49,10 +51,10 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMemberDependencies;
 
-public class ObjectActionContributee extends ObjectActionImpl implements ContributeeMember2 {
+public class ObjectActionContributee extends ObjectActionDefault implements ContributeeMember2 {
 
     private final Object servicePojo;
-    private final ObjectActionImpl serviceAction;
+    private final ObjectActionDefault serviceAction;
     private final int contributeeParam;
     private final ObjectSpecification contributeeType;
     
@@ -75,7 +77,7 @@ public class ObjectActionContributee extends ObjectActionImpl implements Contrib
      */
     public ObjectActionContributee(
             final Object servicePojo,
-            final ObjectActionImpl serviceAction,
+            final ObjectActionDefault serviceAction,
             final int contributeeParam,
             final ObjectSpecification contributeeType,
             final ObjectMemberDependencies objectMemberDependencies) {
@@ -132,9 +134,10 @@ public class ObjectActionContributee extends ObjectActionImpl implements Contrib
                     // skip so is omitted from the Contributed action
                     continue;
                 }
-                
-                final ObjectActionParameterAbstract serviceParameter = 
+
+                final ObjectActionParameterAbstract serviceParameter =
                         (ObjectActionParameterAbstract) serviceParameters.get(serviceParamNum);
+
                 final ObjectActionParameterContributee contributedParam;
                 contributedParam = new OneToOneActionParameterContributee(
                         getServiceAdapter(), serviceParameter,

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java
new file mode 100644
index 0000000..7060cf1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionDefault.java
@@ -0,0 +1,531 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.specloader.specimpl;
+
+import java.util.List;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Lists;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.RecoverableException;
+import org.apache.isis.applib.annotation.ActionSemantics;
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.applib.filter.Filter;
+import org.apache.isis.core.commons.debug.DebugString;
+import org.apache.isis.core.commons.exceptions.UnknownTypeException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
+import org.apache.isis.core.metamodel.consent.InteractionResultSet;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.FacetedMethodParameter;
+import org.apache.isis.core.metamodel.facets.TypedHolder;
+import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacet;
+import org.apache.isis.core.metamodel.facets.actions.debug.DebugFacet;
+import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacet;
+import org.apache.isis.core.metamodel.facets.actions.exploration.ExplorationFacet;
+import org.apache.isis.core.metamodel.facets.actions.prototype.PrototypeFacet;
+import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacet;
+import org.apache.isis.core.metamodel.facets.param.choices.ActionChoicesFacet;
+import org.apache.isis.core.metamodel.facets.param.choices.ActionParameterChoicesFacet;
+import org.apache.isis.core.metamodel.facets.param.defaults.ActionParameterDefaultsFacet;
+import org.apache.isis.core.metamodel.interactions.ActionInvocationContext;
+import org.apache.isis.core.metamodel.interactions.ActionUsabilityContext;
+import org.apache.isis.core.metamodel.interactions.ActionVisibilityContext;
+import org.apache.isis.core.metamodel.interactions.InteractionUtils;
+import org.apache.isis.core.metamodel.interactions.UsabilityContext;
+import org.apache.isis.core.metamodel.interactions.ValidityContext;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.DomainModelException;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMemberDependencies;
+
+public class ObjectActionDefault extends ObjectMemberAbstract implements ObjectAction {
+
+    private final static Logger LOG = LoggerFactory.getLogger(ObjectActionDefault.class);
+
+    public static ActionType getType(final String typeStr) {
+        final ActionType type = ActionType.valueOf(typeStr);
+        if (type == null) {
+            throw new IllegalArgumentException();
+        }
+        return type;
+    }
+
+    //region > fields
+
+    /**
+     * Lazily initialized by {@link #getParameters()} (so don't use directly!)
+     */
+    private List<ObjectActionParameter> parameters;
+
+    //endregion
+
+    //region > constructors
+
+    public ObjectActionDefault(
+            final FacetedMethod facetedMethod,
+            final ObjectMemberDependencies objectMemberDependencies) {
+        super(facetedMethod, FeatureType.ACTION, objectMemberDependencies);
+    }
+
+    //endregion
+
+    //region > ReturnType, OnType, Actions (set)
+    /**
+     * Always returns <tt>null</tt>.
+     */
+    @Override
+    public ObjectSpecification getSpecification() {
+        return null;
+    }
+
+    @Override
+    public ObjectSpecification getReturnType() {
+        final ActionInvocationFacet facet = getActionInvocationFacet();
+        return facet.getReturnType();
+    }
+
+    /**
+     * Returns true if the represented action returns something, else returns
+     * false.
+     */
+    @Override
+    public boolean hasReturn() {
+        if(getReturnType() == null) {
+            // this shouldn't happen; return Type always defined, even if represents void.class
+            return false;
+        }
+        return getReturnType() != getSpecificationLoader().loadSpecification(void.class);
+    }
+
+
+    @Override
+    public ObjectSpecification getOnType() {
+        final ActionInvocationFacet facet = getActionInvocationFacet();
+        return facet.getOnType();
+    }
+
+    @Override
+    public ActionSemantics.Of getSemantics() {
+        final ActionSemanticsFacet facet = getFacet(ActionSemanticsFacet.class);
+        return facet != null? facet.value(): ActionSemantics.Of.NON_IDEMPOTENT;
+    }
+
+    //endregion
+
+    //region > Type
+    @Override
+    public ActionType getType() {
+        return getType(this);
+    }
+
+    private static ActionType getType(final FacetHolder facetHolder) {
+        Facet facet = facetHolder.getFacet(DebugFacet.class);
+        if (facet != null) {
+            return ActionType.DEBUG;
+        }
+        facet = facetHolder.getFacet(ExplorationFacet.class);
+        if (facet != null) {
+            return ActionType.EXPLORATION;
+        }
+        facet = facetHolder.getFacet(PrototypeFacet.class);
+        if (facet != null) {
+            return ActionType.PROTOTYPE;
+        }
+        return ActionType.USER;
+    }
+    //endregion
+
+    //region > Parameters
+
+    @Override
+    public int getParameterCount() {
+        return getFacetedMethod().getParameters().size();
+    }
+
+    @Override
+    public boolean promptForParameters(final ObjectAdapter target) {
+        return getParameterCount() != 0;
+    }
+
+    /**
+     * 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 synchronized List<ObjectActionParameter> getParameters() {
+        if (this.parameters == null) {
+            final int parameterCount = getParameterCount();
+            final List<ObjectActionParameter> parameters = Lists.newArrayList();
+            final List<FacetedMethodParameter> paramPeers = getFacetedMethod().getParameters();
+            for (int i = 0; i < parameterCount; i++) {
+                final TypedHolder paramPeer = paramPeers.get(i);
+                final ObjectSpecification specification = ObjectMemberAbstract.getSpecification(getSpecificationLoader(), paramPeer.getType());
+                
+                if (!specification.isNotCollection()) {
+                    throw new UnknownTypeException("collections not supported as parameters: " + getIdentifier());
+                }
+                final ObjectActionParameter parameter = new OneToOneActionParameterDefault(i, this, paramPeer);
+                parameters.add(parameter);
+            }
+            this.parameters = parameters;
+        }
+        return parameters;
+    }
+
+    @Override
+    public synchronized List<ObjectSpecification> getParameterTypes() {
+        final List<ObjectSpecification> parameterTypes = Lists.newArrayList();
+        final List<ObjectActionParameter> parameters = getParameters();
+        for (final ObjectActionParameter parameter : parameters) {
+            parameterTypes.add(parameter.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.equal(paramId, param.getId())) {
+                return param;
+            }
+        }
+        return 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.equal(paramName, param.getName())) {
+                return param;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public List<ObjectActionParameter> getParameters(final Filter<ObjectActionParameter> filter) {
+        final List<ObjectActionParameter> allParameters = getParameters();
+        final List<ObjectActionParameter> selectedParameters = Lists.newArrayList();
+        for (int i = 0; i < allParameters.size(); i++) {
+            if (filter.accept(allParameters.get(i))) {
+                selectedParameters.add(allParameters.get(i));
+            }
+        }
+        return selectedParameters;
+    }
+
+    private ObjectActionParameter getParameter(final int position) {
+        final List<ObjectActionParameter> parameters = getParameters();
+        if (position >= parameters.size()) {
+            throw new IllegalArgumentException("getParameter(int): only " + parameters.size() + " parameters, position=" + position);
+        }
+        return parameters.get(position);
+    }
+
+    //endregion
+
+    //region > visable, usable
+
+    @Override
+    public VisibilityContext<?> createVisibleInteractionContext(
+            final ObjectAdapter targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy,
+            Where where) {
+        return new ActionVisibilityContext(targetObjectAdapter, getIdentifier(), interactionInitiatedBy, where);
+    }
+
+    @Override
+    public UsabilityContext<?> createUsableInteractionContext(
+            final ObjectAdapter targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy,
+            Where where) {
+        return new ActionUsabilityContext(targetObjectAdapter, getIdentifier(), interactionInitiatedBy, where);
+    }
+    //endregion
+
+    //region > validate
+
+    @Override
+    public Consent isProposedArgumentSetValid(
+            final ObjectAdapter target,
+            final ObjectAdapter[] proposedArguments,
+            final InteractionInitiatedBy interactionInitiatedBy) {
+        return isProposedArgumentSetValidResultSet(target, proposedArguments, interactionInitiatedBy).createConsent();
+    }
+
+    private InteractionResultSet isProposedArgumentSetValidResultSet(
+            final ObjectAdapter objectAdapter,
+            final ObjectAdapter[] proposedArguments,
+            final InteractionInitiatedBy interactionInitiatedBy) {
+
+        final InteractionResultSet resultSet = new InteractionResultSet();
+        final List<ObjectActionParameter> actionParameters = getParameters();
+        if (proposedArguments != null) {
+            for (int i = 0; i < proposedArguments.length; i++) {
+                final ValidityContext<?> ic =
+                        actionParameters.get(i).createProposedArgumentInteractionContext(
+                                objectAdapter, proposedArguments, i, interactionInitiatedBy
+                        );
+                InteractionUtils.isValidResultSet(getParameter(i), ic, resultSet);
+            }
+        }
+        // only check the action's own validity if all the arguments are OK.
+        if (resultSet.isAllowed()) {
+            final ValidityContext<?> ic = createActionInvocationInteractionContext(
+                    objectAdapter, proposedArguments, interactionInitiatedBy);
+            InteractionUtils.isValidResultSet(this, ic, resultSet);
+        }
+        return resultSet;
+    }
+
+    private ActionInvocationContext createActionInvocationInteractionContext(
+            final ObjectAdapter targetObject,
+            final ObjectAdapter[] proposedArguments,
+            final InteractionInitiatedBy interactionInitiatedBy) {
+        return new ActionInvocationContext(targetObject, getIdentifier(), proposedArguments,
+                interactionInitiatedBy);
+    }
+
+    //endregion
+
+    //region > executeWithRuleChecking, execute
+
+    @Override
+    public ObjectAdapter executeWithRuleChecking(
+            final ObjectAdapter target,
+            final ObjectAdapter[] arguments,
+            final InteractionInitiatedBy interactionInitiatedBy,
+            final Where where) {
+
+        // see it?
+        final Consent visibility = isVisible(target, interactionInitiatedBy, where);
+        if (visibility.isVetoed()) {
+            throw new AuthorizationException();
+        }
+
+        // use it?
+        final Consent usability = isUsable(target, interactionInitiatedBy, where);
+        if(usability.isVetoed()) {
+            throw new AuthorizationException();
+        }
+
+        // do it?
+        final Consent validity = isProposedArgumentSetValid(target, arguments, interactionInitiatedBy);
+        if(validity.isVetoed()) {
+            throw new RecoverableException(validity.getReason());
+        }
+
+        return execute(target, arguments, interactionInitiatedBy);
+    }
+
+    @Override
+    public ObjectAdapter execute(
+            final ObjectAdapter target,
+            final ObjectAdapter[] arguments,
+            final InteractionInitiatedBy interactionInitiatedBy) {
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("execute action " + target + "." + getId());
+        }
+        final ActionInvocationFacet facet = getFacet(ActionInvocationFacet.class);
+        return facet.invoke(this, target, arguments,
+                interactionInitiatedBy);
+    }
+
+    protected ActionInvocationFacet getActionInvocationFacet() {
+        return getFacetedMethod().getFacet(ActionInvocationFacet.class);
+    }
+
+
+    //endregion
+
+    //region > defaults
+
+    @Override
+    public ObjectAdapter[] getDefaults(final ObjectAdapter target) {
+
+        final int parameterCount = getParameterCount();
+        final List<ObjectActionParameter> parameters = getParameters();
+
+        final Object[] parameterDefaultPojos;
+
+        final ActionDefaultsFacet facet = getFacet(ActionDefaultsFacet.class);
+        if (!facet.isNoop()) {
+            // use the old defaultXxx approach
+            parameterDefaultPojos = facet.getDefaults(target);
+            if (parameterDefaultPojos.length != parameterCount) {
+                throw new DomainModelException("Defaults array of incompatible size; expected " + parameterCount + " elements, but was " + parameterDefaultPojos.length + " for " + facet);
+            }
+            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();
+                    if (!componentSpec.isOfType(parameterSpec)) {
+                        throw new DomainModelException("Defaults type incompatible with parameter " + (i + 1) + " type; expected " + parameterSpec.getFullIdentifier() + ", but was " + componentSpec.getFullIdentifier());
+                    }
+                }
+            }
+        } else {
+            // use the new defaultNXxx approach for each param in turn
+            // (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);
+                if (paramFacet != null && !paramFacet.isNoop()) {
+                    parameterDefaultPojos[i] = paramFacet.getDefault(target, null);
+                } else {
+                    parameterDefaultPojos[i] = null;
+                }
+            }
+        }
+
+        final ObjectAdapter[] parameterDefaultAdapters = new ObjectAdapter[parameterCount];
+        if (parameterDefaultPojos != null) {
+            for (int i = 0; i < parameterCount; i++) {
+                parameterDefaultAdapters[i] = adapterFor(parameterDefaultPojos[i]);
+            }
+        }
+
+        return parameterDefaultAdapters;
+    }
+
+    private ObjectAdapter adapterFor(final Object pojo) {
+        return pojo == null ? null : getPersistenceSessionService().adapterFor(pojo);
+    }
+
+    //endregion
+
+    //region > choices
+
+    @Override
+    public ObjectAdapter[][] getChoices(
+            final ObjectAdapter target,
+            final InteractionInitiatedBy interactionInitiatedBy) {
+
+        final int parameterCount = getParameterCount();
+        Object[][] parameterChoicesPojos;
+
+        final ActionChoicesFacet facet = getFacet(ActionChoicesFacet.class);
+        final List<ObjectActionParameter> parameters = getParameters();
+
+        if (!facet.isNoop()) {
+            // using the old choicesXxx() approach
+            parameterChoicesPojos = facet.getChoices(target,
+                    interactionInitiatedBy);
+
+            // if no options, or not the right number of pojos, then default
+            if (parameterChoicesPojos == null) {
+                parameterChoicesPojos = new Object[parameterCount][];
+            } else if (parameterChoicesPojos.length != parameterCount) {
+                throw new DomainModelException(
+                        String.format("Choices array of incompatible size; expected %d elements, but was %d for %s",
+                                parameterCount, parameterChoicesPojos.length, facet));
+            }
+        } else {
+            // use the new choicesNXxx approach for each param in turn
+            // (the reflector will have made sure both aren't installed).
+
+            parameterChoicesPojos = new Object[parameterCount][];
+            for (int i = 0; i < parameterCount; i++) {
+                final ActionParameterChoicesFacet paramFacet = parameters.get(i).getFacet(ActionParameterChoicesFacet.class);
+                if (paramFacet != null && !paramFacet.isNoop()) {
+                    parameterChoicesPojos[i] = paramFacet.getChoices(target, null,
+                            interactionInitiatedBy);
+                } else {
+                    parameterChoicesPojos[i] = new Object[0];
+                }
+            }
+        }
+
+        final ObjectAdapter[][] parameterChoicesAdapters = new ObjectAdapter[parameterCount][];
+        for (int i = 0; i < parameterCount; i++) {
+            final ObjectSpecification paramSpec = parameters.get(i).getSpecification();
+
+            if (parameterChoicesPojos[i] != null && parameterChoicesPojos[i].length > 0) {
+                ObjectActionParameterAbstract.checkChoicesOrAutoCompleteType(
+                        getSpecificationLoader(), parameterChoicesPojos[i], paramSpec);
+                parameterChoicesAdapters[i] = new ObjectAdapter[parameterChoicesPojos[i].length];
+                for (int j = 0; j < parameterChoicesPojos[i].length; j++) {
+                    parameterChoicesAdapters[i][j] = adapterFor(parameterChoicesPojos[i][j]);
+                }
+            } else if (paramSpec.isNotCollection()) {
+                parameterChoicesAdapters[i] = new ObjectAdapter[0];
+            } else {
+                throw new UnknownTypeException(paramSpec);
+            }
+
+            if (parameterChoicesAdapters[i].length == 0) {
+                parameterChoicesAdapters[i] = null;
+            }
+        }
+
+        return parameterChoicesAdapters;
+    }
+
+    //endregion
+
+    //region > debug, toString
+
+    @Override
+    public String debugData() {
+        final DebugString debugString = new DebugString();
+        getFacetedMethod().debugData(debugString);
+        return debugString.toString();
+    }
+
+    @Override
+    public String toString() {
+        final StringBuffer sb = new StringBuffer();
+        sb.append("Action [");
+        sb.append(super.toString());
+        sb.append(",type=");
+        sb.append(getType());
+        sb.append(",returns=");
+        sb.append(getReturnType());
+        sb.append(",parameters={");
+        for (int i = 0; i < getParameterCount(); i++) {
+            if (i > 0) {
+                sb.append(",");
+            }
+            sb.append(getParameters().get(i).getSpecification().getShortIdentifier());
+        }
+        sb.append("}]");
+        return sb.toString();
+    }
+
+    //endregion
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
deleted file mode 100644
index ae38776..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionImpl.java
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.isis.core.metamodel.specloader.specimpl;
-
-import java.util.List;
-
-import com.google.common.base.Objects;
-import com.google.common.collect.Lists;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.annotation.ActionSemantics;
-import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.filter.Filter;
-import org.apache.isis.core.commons.debug.DebugString;
-import org.apache.isis.core.commons.exceptions.UnknownTypeException;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.consent.Consent;
-import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.consent.InteractionResultSet;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FeatureType;
-import org.apache.isis.core.metamodel.facets.FacetedMethod;
-import org.apache.isis.core.metamodel.facets.FacetedMethodParameter;
-import org.apache.isis.core.metamodel.facets.TypedHolder;
-import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacet;
-import org.apache.isis.core.metamodel.facets.actions.debug.DebugFacet;
-import org.apache.isis.core.metamodel.facets.actions.defaults.ActionDefaultsFacet;
-import org.apache.isis.core.metamodel.facets.actions.exploration.ExplorationFacet;
-import org.apache.isis.core.metamodel.facets.actions.prototype.PrototypeFacet;
-import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacet;
-import org.apache.isis.core.metamodel.facets.param.choices.ActionChoicesFacet;
-import org.apache.isis.core.metamodel.facets.param.choices.ActionParameterChoicesFacet;
-import org.apache.isis.core.metamodel.facets.param.defaults.ActionParameterDefaultsFacet;
-import org.apache.isis.core.metamodel.interactions.ActionInvocationContext;
-import org.apache.isis.core.metamodel.interactions.ActionUsabilityContext;
-import org.apache.isis.core.metamodel.interactions.ActionVisibilityContext;
-import org.apache.isis.core.metamodel.interactions.InteractionUtils;
-import org.apache.isis.core.metamodel.interactions.UsabilityContext;
-import org.apache.isis.core.metamodel.interactions.ValidityContext;
-import org.apache.isis.core.metamodel.interactions.VisibilityContext;
-import org.apache.isis.core.metamodel.spec.ActionType;
-import org.apache.isis.core.metamodel.spec.DomainModelException;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
-import org.apache.isis.core.metamodel.spec.feature.ObjectMemberDependencies;
-
-public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectAction {
-
-    private final static Logger LOG = LoggerFactory.getLogger(ObjectActionImpl.class);
-
-    public static ActionType getType(final String typeStr) {
-        final ActionType type = ActionType.valueOf(typeStr);
-        if (type == null) {
-            throw new IllegalArgumentException();
-        }
-        return type;
-    }
-
-    //region > fields
-
-    /**
-     * Lazily initialized by {@link #getParameters()} (so don't use directly!)
-     */
-    private List<ObjectActionParameter> parameters;
-
-    //endregion
-
-    //region > constructors
-
-    public ObjectActionImpl(final FacetedMethod facetedMethod, final ObjectMemberDependencies objectMemberDependencies) {
-        super(facetedMethod, FeatureType.ACTION, objectMemberDependencies);
-    }
-
-    //endregion
-
-    //region > ReturnType, OnType, Actions (set)
-    /**
-     * Always returns <tt>null</tt>.
-     */
-    @Override
-    public ObjectSpecification getSpecification() {
-        return null;
-    }
-
-    @Override
-    public ObjectSpecification getReturnType() {
-        final ActionInvocationFacet facet = getActionInvocationFacet();
-        return facet.getReturnType();
-    }
-
-    /**
-     * Returns true if the represented action returns something, else returns
-     * false.
-     */
-    @Override
-    public boolean hasReturn() {
-        if(getReturnType() == null) {
-            // this shouldn't happen; return Type always defined, even if represents void.class
-            return false;
-        }
-        return getReturnType() != getSpecificationLoader().loadSpecification(void.class);
-    }
-
-
-    @Override
-    public ObjectSpecification getOnType() {
-        final ActionInvocationFacet facet = getActionInvocationFacet();
-        return facet.getOnType();
-    }
-
-    @Override
-    public ActionSemantics.Of getSemantics() {
-        final ActionSemanticsFacet facet = getFacet(ActionSemanticsFacet.class);
-        return facet != null? facet.value(): ActionSemantics.Of.NON_IDEMPOTENT;
-    }
-
-    //endregion
-
-    //region > Type
-    @Override
-    public ActionType getType() {
-        return getType(this);
-    }
-
-    private static ActionType getType(final FacetHolder facetHolder) {
-        Facet facet = facetHolder.getFacet(DebugFacet.class);
-        if (facet != null) {
-            return ActionType.DEBUG;
-        }
-        facet = facetHolder.getFacet(ExplorationFacet.class);
-        if (facet != null) {
-            return ActionType.EXPLORATION;
-        }
-        facet = facetHolder.getFacet(PrototypeFacet.class);
-        if (facet != null) {
-            return ActionType.PROTOTYPE;
-        }
-        return ActionType.USER;
-    }
-    //endregion
-
-    //region > Parameters
-
-    @Override
-    public int getParameterCount() {
-        return getFacetedMethod().getParameters().size();
-    }
-
-    @Override
-    public boolean promptForParameters(final ObjectAdapter target) {
-        return getParameterCount() != 0;
-    }
-
-    /**
-     * 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 synchronized List<ObjectActionParameter> getParameters() {
-        if (this.parameters == null) {
-            final int parameterCount = getParameterCount();
-            final List<ObjectActionParameter> parameters = Lists.newArrayList();
-            final List<FacetedMethodParameter> paramPeers = getFacetedMethod().getParameters();
-            for (int i = 0; i < parameterCount; i++) {
-                final TypedHolder paramPeer = paramPeers.get(i);
-                final ObjectSpecification specification = ObjectMemberAbstract.getSpecification(getSpecificationLoader(), paramPeer.getType());
-                
-                final ObjectActionParameter parameter;
-                if (specification.isParseable()) {
-                    parameter = new OneToOneActionParameterImpl(i, this, paramPeer);
-                } else if (specification.isNotCollection()) {
-                    parameter = new OneToOneActionParameterImpl(i, this, paramPeer);
-                } else if (specification.isParentedOrFreeCollection()) {
-                    throw new UnknownTypeException("collections not supported as parameters: " + getIdentifier());
-                } else {
-                    throw new UnknownTypeException(specification);
-                }
-                parameters.add(parameter);
-            }
-            this.parameters = parameters;
-        }
-        return parameters;
-    }
-
-    @Override
-    public synchronized List<ObjectSpecification> getParameterTypes() {
-        final List<ObjectSpecification> parameterTypes = Lists.newArrayList();
-        final List<ObjectActionParameter> parameters = getParameters();
-        for (final ObjectActionParameter parameter : parameters) {
-            parameterTypes.add(parameter.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.equal(paramId, param.getId())) {
-                return param;
-            }
-        }
-        return 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.equal(paramName, param.getName())) {
-                return param;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public List<ObjectActionParameter> getParameters(final Filter<ObjectActionParameter> filter) {
-        final List<ObjectActionParameter> allParameters = getParameters();
-        final List<ObjectActionParameter> selectedParameters = Lists.newArrayList();
-        for (int i = 0; i < allParameters.size(); i++) {
-            if (filter.accept(allParameters.get(i))) {
-                selectedParameters.add(allParameters.get(i));
-            }
-        }
-        return selectedParameters;
-    }
-
-    private ObjectActionParameter getParameter(final int position) {
-        final List<ObjectActionParameter> parameters = getParameters();
-        if (position >= parameters.size()) {
-            throw new IllegalArgumentException("getParameter(int): only " + parameters.size() + " parameters, position=" + position);
-        }
-        return parameters.get(position);
-    }
-
-    //endregion
-
-    //region > visable, usable
-
-    @Override
-    public VisibilityContext<?> createVisibleInteractionContext(
-            final ObjectAdapter targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy,
-            Where where) {
-        return new ActionVisibilityContext(targetObjectAdapter, getIdentifier(), interactionInitiatedBy, where);
-    }
-
-    @Override
-    public UsabilityContext<?> createUsableInteractionContext(
-            final ObjectAdapter targetObjectAdapter, final InteractionInitiatedBy interactionInitiatedBy,
-            Where where) {
-        return new ActionUsabilityContext(targetObjectAdapter, getIdentifier(), interactionInitiatedBy, where);
-    }
-    //endregion
-
-    //region > validate
-
-    @Override
-    public Consent isProposedArgumentSetValid(
-            final ObjectAdapter target,
-            final ObjectAdapter[] proposedArguments,
-            final InteractionInitiatedBy interactionInitiatedBy) {
-        return isProposedArgumentSetValidResultSet(target, proposedArguments, interactionInitiatedBy).createConsent();
-    }
-
-    private InteractionResultSet isProposedArgumentSetValidResultSet(
-            final ObjectAdapter objectAdapter,
-            final ObjectAdapter[] proposedArguments,
-            final InteractionInitiatedBy interactionInitiatedBy) {
-
-        final InteractionResultSet resultSet = new InteractionResultSet();
-        final List<ObjectActionParameter> actionParameters = getParameters();
-        if (proposedArguments != null) {
-            for (int i = 0; i < proposedArguments.length; i++) {
-                final ValidityContext<?> ic =
-                        actionParameters.get(i).createProposedArgumentInteractionContext(
-                                objectAdapter, proposedArguments, i, interactionInitiatedBy
-                        );
-                InteractionUtils.isValidResultSet(getParameter(i), ic, resultSet);
-            }
-        }
-        // only check the action's own validity if all the arguments are OK.
-        if (resultSet.isAllowed()) {
-            final ValidityContext<?> ic = createActionInvocationInteractionContext(
-                    objectAdapter, proposedArguments, interactionInitiatedBy);
-            InteractionUtils.isValidResultSet(this, ic, resultSet);
-        }
-        return resultSet;
-    }
-
-    private ActionInvocationContext createActionInvocationInteractionContext(
-            final ObjectAdapter targetObject,
-            final ObjectAdapter[] proposedArguments,
-            final InteractionInitiatedBy interactionInitiatedBy) {
-        return new ActionInvocationContext(targetObject, getIdentifier(), proposedArguments,
-                interactionInitiatedBy);
-    }
-
-    //endregion
-
-    //region > executeWithRuleChecking, execute
-
-    @Override
-    public ObjectAdapter executeWithRuleChecking(
-            final ObjectAdapter target,
-            final ObjectAdapter[] arguments,
-            final InteractionInitiatedBy interactionInitiatedBy,
-            final Where where) {
-
-        // see it?
-        final Consent visibility = isVisible(target, interactionInitiatedBy, where);
-        if (visibility.isVetoed()) {
-            throw new AuthorizationException();
-        }
-
-        // use it?
-        final Consent usability = isUsable(target, interactionInitiatedBy, where);
-        if(usability.isVetoed()) {
-            throw new AuthorizationException();
-        }
-
-        // do it?
-        final Consent validity = isProposedArgumentSetValid(target, arguments, interactionInitiatedBy);
-        if(validity.isVetoed()) {
-            throw new RecoverableException(validity.getReason());
-        }
-
-        return execute(target, arguments, interactionInitiatedBy);
-    }
-
-    @Override
-    public ObjectAdapter execute(
-            final ObjectAdapter target,
-            final ObjectAdapter[] arguments,
-            final InteractionInitiatedBy interactionInitiatedBy) {
-        if(LOG.isDebugEnabled()) {
-            LOG.debug("execute action " + target + "." + getId());
-        }
-        final ActionInvocationFacet facet = getFacet(ActionInvocationFacet.class);
-        return facet.invoke(this, target, arguments,
-                interactionInitiatedBy);
-    }
-
-    protected ActionInvocationFacet getActionInvocationFacet() {
-        return getFacetedMethod().getFacet(ActionInvocationFacet.class);
-    }
-
-
-    //endregion
-
-    //region > defaults
-
-    @Override
-    public ObjectAdapter[] getDefaults(final ObjectAdapter target) {
-
-        final int parameterCount = getParameterCount();
-        final List<ObjectActionParameter> parameters = getParameters();
-
-        final Object[] parameterDefaultPojos;
-
-        final ActionDefaultsFacet facet = getFacet(ActionDefaultsFacet.class);
-        if (!facet.isNoop()) {
-            // use the old defaultXxx approach
-            parameterDefaultPojos = facet.getDefaults(target);
-            if (parameterDefaultPojos.length != parameterCount) {
-                throw new DomainModelException("Defaults array of incompatible size; expected " + parameterCount + " elements, but was " + parameterDefaultPojos.length + " for " + facet);
-            }
-            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();
-                    if (!componentSpec.isOfType(parameterSpec)) {
-                        throw new DomainModelException("Defaults type incompatible with parameter " + (i + 1) + " type; expected " + parameterSpec.getFullIdentifier() + ", but was " + componentSpec.getFullIdentifier());
-                    }
-                }
-            }
-        } else {
-            // use the new defaultNXxx approach for each param in turn
-            // (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);
-                if (paramFacet != null && !paramFacet.isNoop()) {
-                    parameterDefaultPojos[i] = paramFacet.getDefault(target, null);
-                } else {
-                    parameterDefaultPojos[i] = null;
-                }
-            }
-        }
-
-        final ObjectAdapter[] parameterDefaultAdapters = new ObjectAdapter[parameterCount];
-        if (parameterDefaultPojos != null) {
-            for (int i = 0; i < parameterCount; i++) {
-                parameterDefaultAdapters[i] = adapterFor(parameterDefaultPojos[i]);
-            }
-        }
-
-        return parameterDefaultAdapters;
-    }
-
-    private ObjectAdapter adapterFor(final Object pojo) {
-        return pojo == null ? null : getPersistenceSessionService().adapterFor(pojo);
-    }
-
-    //endregion
-
-    //region > choices
-
-    @Override
-    public ObjectAdapter[][] getChoices(
-            final ObjectAdapter target,
-            final InteractionInitiatedBy interactionInitiatedBy) {
-
-        final int parameterCount = getParameterCount();
-        Object[][] parameterChoicesPojos;
-
-        final ActionChoicesFacet facet = getFacet(ActionChoicesFacet.class);
-        final List<ObjectActionParameter> parameters = getParameters();
-
-        if (!facet.isNoop()) {
-            // using the old choicesXxx() approach
-            parameterChoicesPojos = facet.getChoices(target,
-                    interactionInitiatedBy);
-
-            // if no options, or not the right number of pojos, then default
-            if (parameterChoicesPojos == null) {
-                parameterChoicesPojos = new Object[parameterCount][];
-            } else if (parameterChoicesPojos.length != parameterCount) {
-                throw new DomainModelException(
-                        String.format("Choices array of incompatible size; expected %d elements, but was %d for %s",
-                                parameterCount, parameterChoicesPojos.length, facet));
-            }
-        } else {
-            // use the new choicesNXxx approach for each param in turn
-            // (the reflector will have made sure both aren't installed).
-
-            parameterChoicesPojos = new Object[parameterCount][];
-            for (int i = 0; i < parameterCount; i++) {
-                final ActionParameterChoicesFacet paramFacet = parameters.get(i).getFacet(ActionParameterChoicesFacet.class);
-                if (paramFacet != null && !paramFacet.isNoop()) {
-                    parameterChoicesPojos[i] = paramFacet.getChoices(target, null,
-                            interactionInitiatedBy);
-                } else {
-                    parameterChoicesPojos[i] = new Object[0];
-                }
-            }
-        }
-
-        final ObjectAdapter[][] parameterChoicesAdapters = new ObjectAdapter[parameterCount][];
-        for (int i = 0; i < parameterCount; i++) {
-            final ObjectSpecification paramSpec = parameters.get(i).getSpecification();
-
-            if (parameterChoicesPojos[i] != null && parameterChoicesPojos[i].length > 0) {
-                ObjectActionParameterAbstract.checkChoicesOrAutoCompleteType(
-                        getSpecificationLoader(), parameterChoicesPojos[i], paramSpec);
-                parameterChoicesAdapters[i] = new ObjectAdapter[parameterChoicesPojos[i].length];
-                for (int j = 0; j < parameterChoicesPojos[i].length; j++) {
-                    parameterChoicesAdapters[i][j] = adapterFor(parameterChoicesPojos[i][j]);
-                }
-            } else if (paramSpec.isNotCollection()) {
-                parameterChoicesAdapters[i] = new ObjectAdapter[0];
-            } else {
-                throw new UnknownTypeException(paramSpec);
-            }
-
-            if (parameterChoicesAdapters[i].length == 0) {
-                parameterChoicesAdapters[i] = null;
-            }
-        }
-
-        return parameterChoicesAdapters;
-    }
-
-    //endregion
-
-    //region > debug, toString
-
-    @Override
-    public String debugData() {
-        final DebugString debugString = new DebugString();
-        getFacetedMethod().debugData(debugString);
-        return debugString.toString();
-    }
-
-    @Override
-    public String toString() {
-        final StringBuffer sb = new StringBuffer();
-        sb.append("Action [");
-        sb.append(super.toString());
-        sb.append(",type=");
-        sb.append(getType());
-        sb.append(",returns=");
-        sb.append(getReturnType());
-        sb.append(",parameters={");
-        for (int i = 0; i < getParameterCount(); i++) {
-            if (i > 0) {
-                sb.append(",");
-            }
-            sb.append(getParameters().get(i).getSpecification().getShortIdentifier());
-        }
-        sb.append("}]");
-        return sb.toString();
-    }
-
-    //endregion
-
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
index 64b48e7..3f68d8e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionMixedIn.java
@@ -19,6 +19,7 @@ package org.apache.isis.core.metamodel.specloader.specimpl;
 import java.util.Collections;
 import java.util.List;
 
+import com.google.common.base.Objects;
 import com.google.common.collect.Lists;
 
 import org.apache.isis.applib.Identifier;
@@ -32,6 +33,7 @@ import org.apache.isis.applib.services.command.Command;
 import org.apache.isis.applib.services.command.Command.Executor;
 import org.apache.isis.applib.services.command.CommandContext;
 import org.apache.isis.core.commons.lang.ObjectExtensions;
+import org.apache.isis.core.commons.lang.StringExtensions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
@@ -42,6 +44,7 @@ import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.actions.action.invocation.CommandUtil;
 import org.apache.isis.core.metamodel.facets.actions.bulk.BulkFacet;
+import org.apache.isis.core.metamodel.facets.all.named.NamedFacetInferred;
 import org.apache.isis.core.metamodel.facets.object.mixin.MixinFacet;
 import org.apache.isis.core.metamodel.interactions.InteractionUtils;
 import org.apache.isis.core.metamodel.interactions.UsabilityContext;
@@ -50,7 +53,7 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMemberDependencies;
 
-public class ObjectActionMixedIn extends ObjectActionImpl implements MixedInMember {
+public class ObjectActionMixedIn extends ObjectActionDefault implements MixedInMember {
 
     /**
      * The type of the mixin (providing the action), eg annotated with {@link org.apache.isis.applib.annotation.Mixin}.
@@ -58,9 +61,9 @@ public class ObjectActionMixedIn extends ObjectActionImpl implements MixedInMemb
     private final Class<?> mixinType;
 
     /**
-     * The {@link ObjectActionImpl} for the action being mixed in (ie on the {@link #mixinType}.
+     * The {@link ObjectActionDefault} for the action being mixed in (ie on the {@link #mixinType}.
      */
-    private final ObjectActionImpl mixinAction;
+    private final ObjectActionDefault mixinAction;
 
     /**
      * The domain object type being mixed in to (being supplemented).
@@ -81,7 +84,7 @@ public class ObjectActionMixedIn extends ObjectActionImpl implements MixedInMemb
 
     public ObjectActionMixedIn(
             final Class<?> mixinType,
-            final ObjectActionImpl mixinAction,
+            final ObjectActionDefault mixinAction,
             final ObjectSpecification mixedInType,
             final ObjectMemberDependencies objectMemberDependencies) {
         super(mixinAction.getFacetedMethod(), objectMemberDependencies);
@@ -90,16 +93,47 @@ public class ObjectActionMixedIn extends ObjectActionImpl implements MixedInMemb
         this.mixinAction = mixinAction;
         this.mixedInType = mixedInType;
 
-        // copy over facets from mixin type to own.
+        // copy over facets from mixin action to self
         FacetUtil.copyFacets(mixinAction.getFacetedMethod(), facetHolder);
 
+        // adjust name if necessary
+        final String name = getName();
+
+        String memberName = null;
+        if(Objects.equal(name, "_")) {
+            memberName = determineNameFrom(mixinAction);
+            FacetUtil.addFacet(new NamedFacetInferred(memberName, facetHolder));
+        }
+
         // calculate the identifier
         final Identifier mixinIdentifier = mixinAction.getFacetedMethod().getIdentifier();
-        final String memberName = mixinIdentifier.getMemberName();
+        memberName = memberName != null? memberName : mixinIdentifier.getMemberName();
         List<String> memberParameterNames = mixinIdentifier.getMemberParameterNames();
         identifier = Identifier.actionIdentifier(getOnType().getCorrespondingClass().getName(), memberName, memberParameterNames);
     }
 
+    private static String determineNameFrom(final ObjectActionDefault mixinAction) {
+        return suffixAfterUnderscore(mixinAction.getOnType().getSingularName());
+    }
+
+    static String suffixAfterUnderscore(final String singularName) {
+        return StringExtensions.asCapitalizedName(suffix(singularName));
+    }
+
+    private static String suffix(final String singularName) {
+        if (singularName.endsWith("_")) {
+            if (Objects.equal(singularName, "_")) {
+                return singularName;
+            }
+            return singularName;
+        }
+        final int indexOfUnderscore = singularName.lastIndexOf('_');
+        if (indexOfUnderscore == -1) {
+            return singularName;
+        }
+        return singularName.substring(indexOfUnderscore + 1);
+    }
+
     @Override
     public ObjectSpecification getOnType() {
         return mixedInType;

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
index 81bff3d..ec23dab 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterAbstract.java
@@ -39,6 +39,7 @@ import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.consent.InteractionResultSet;
 import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.TypedHolder;
@@ -64,10 +65,10 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 public abstract class ObjectActionParameterAbstract implements ObjectActionParameter {
 
     private final int number;
-    private final ObjectActionImpl parentAction;
+    private final ObjectActionDefault parentAction;
     private final TypedHolder peer;
 
-    protected ObjectActionParameterAbstract(final int number, final ObjectActionImpl objectAction, final TypedHolder peer) {
+    protected ObjectActionParameterAbstract(final int number, final ObjectActionDefault objectAction, final TypedHolder peer) {
         this.number = number;
         this.parentAction = objectAction;
         this.peer = peer;
@@ -198,57 +199,70 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
 
     //region > FacetHolder
 
+    protected FacetHolder getFacetHolder() {
+        return peer;
+    }
+
     @Override
     public boolean containsFacet(final Class<? extends Facet> facetType) {
-        return peer != null && peer.containsFacet(facetType);
+        final FacetHolder facetHolder = getFacetHolder();
+        return facetHolder != null && facetHolder.containsFacet(facetType);
     }
 
     @Override
     public boolean containsDoOpFacet(final Class<? extends Facet> facetType) {
-        return peer != null && peer.containsDoOpFacet(facetType);
+        final FacetHolder facetHolder = getFacetHolder();
+        return facetHolder != null && facetHolder.containsDoOpFacet(facetType);
     }
 
     @Override
     public <T extends Facet> T getFacet(final Class<T> cls) {
-        return peer != null ? peer.getFacet(cls) : null;
+        final FacetHolder facetHolder = getFacetHolder();
+        return facetHolder != null ? facetHolder.getFacet(cls) : null;
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public Class<? extends Facet>[] getFacetTypes() {
-        return peer != null ? peer.getFacetTypes() : new Class[] {};
+        final FacetHolder facetHolder = getFacetHolder();
+        return facetHolder != null ? facetHolder.getFacetTypes() : new Class[] {};
     }
 
     @Override
     public List<Facet> getFacets(final Filter<Facet> filter) {
-        return peer != null ? peer.getFacets(filter) : Lists.<Facet> newArrayList();
+        final FacetHolder facetHolder = getFacetHolder();
+        return facetHolder != null ? facetHolder.getFacets(filter) : Lists.<Facet> newArrayList();
     }
 
     @Override
     public void addFacet(final Facet facet) {
-        if (peer != null) {
-            peer.addFacet(facet);
+        final FacetHolder facetHolder = getFacetHolder();
+        if (facetHolder != null) {
+            facetHolder.addFacet(facet);
         }
     }
 
     @Override
     public void addFacet(final MultiTypedFacet facet) {
-        if (peer != null) {
-            peer.addFacet(facet);
+        final FacetHolder facetHolder = getFacetHolder();
+        if (facetHolder != null) {
+            facetHolder.addFacet(facet);
         }
     }
 
     @Override
     public void removeFacet(final Facet facet) {
-        if (peer != null) {
-            peer.removeFacet(facet);
+        final FacetHolder facetHolder = getFacetHolder();
+        if (facetHolder != null) {
+            facetHolder.removeFacet(facet);
         }
     }
 
     @Override
     public void removeFacet(final Class<? extends Facet> facetType) {
-        if (peer != null) {
-            peer.removeFacet(facetType);
+        final FacetHolder facetHolder = getFacetHolder();
+        if (facetHolder != null) {
+            facetHolder.removeFacet(facetType);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
index 57eb6fb..85ba2f3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectMemberAbstract.java
@@ -31,6 +31,7 @@ import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
 import org.apache.isis.core.metamodel.consent.InteractionResult;
 import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.FacetedMethod;
@@ -96,13 +97,6 @@ public abstract class ObjectMemberAbstract implements ObjectMember {
         return id;
     }
 
-    /**
-     * @return the facetedMethod
-     */
-    public FacetedMethod getFacetedMethod() {
-        return facetedMethod;
-    }
-
     @Override
     public Identifier getIdentifier() {
         return getFacetedMethod().getIdentifier();
@@ -117,49 +111,57 @@ public abstract class ObjectMemberAbstract implements ObjectMember {
 
     //region > Facets
 
+    public FacetedMethod getFacetedMethod() {
+        return facetedMethod;
+    }
+
+    protected FacetHolder getFacetHolder() {
+        return getFacetedMethod();
+    }
+
     @Override
     public boolean containsFacet(final Class<? extends Facet> facetType) {
-        return getFacetedMethod().containsFacet(facetType);
+        return getFacetHolder().containsFacet(facetType);
     }
 
     @Override
     public boolean containsDoOpFacet(final Class<? extends Facet> facetType) {
-        return getFacetedMethod().containsDoOpFacet(facetType);
+        return getFacetHolder().containsDoOpFacet(facetType);
     }
 
     @Override
     public <T extends Facet> T getFacet(final Class<T> cls) {
-        return getFacetedMethod().getFacet(cls);
+        return getFacetHolder().getFacet(cls);
     }
 
     @Override
     public Class<? extends Facet>[] getFacetTypes() {
-        return getFacetedMethod().getFacetTypes();
+        return getFacetHolder().getFacetTypes();
     }
 
     @Override
     public List<Facet> getFacets(final Filter<Facet> filter) {
-        return getFacetedMethod().getFacets(filter);
+        return getFacetHolder().getFacets(filter);
     }
 
     @Override
     public void addFacet(final Facet facet) {
-        getFacetedMethod().addFacet(facet);
+        getFacetHolder().addFacet(facet);
     }
 
     @Override
     public void addFacet(final MultiTypedFacet facet) {
-        getFacetedMethod().addFacet(facet);
+        getFacetHolder().addFacet(facet);
     }
 
     @Override
     public void removeFacet(final Facet facet) {
-        getFacetedMethod().removeFacet(facet);
+        getFacetHolder().removeFacet(facet);
     }
 
     @Override
     public void removeFacet(final Class<? extends Facet> facetType) {
-        getFacetedMethod().removeFacet(facetType);
+        getFacetHolder().removeFacet(facetType);
     }
 
     //endregion

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
----------------------------------------------------------------------
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 7d60490..f7968a3 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
@@ -870,7 +870,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         final List<ObjectAction> serviceActions = specification.getObjectActions(ActionType.USER, Contributed.INCLUDED, Filters
                 .<ObjectAction>any());
 
-        final List<ObjectActionImpl> contributedActions = Lists.newArrayList();
+        final List<ObjectActionDefault> contributedActions = Lists.newArrayList();
         for (final ObjectAction serviceAction : serviceActions) {
             if (isAlwaysHidden(serviceAction)) {
                 continue;
@@ -885,25 +885,25 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if (serviceAction.getParameterCount() != 1 || contributeeParameterMatchOf(serviceAction) == -1) {
                 continue;
             }
-            if(!(serviceAction instanceof ObjectActionImpl)) {
+            if(!(serviceAction instanceof ObjectActionDefault)) {
                 continue;
             }
             if(!serviceAction.getSemantics().isSafeInNature()) {
                 continue;
             }
-            contributedActions.add((ObjectActionImpl) serviceAction);
+            contributedActions.add((ObjectActionDefault) serviceAction);
         }
 
         return Lists.newArrayList(Iterables.transform(contributedActions, createContributeeAssociationFunctor(
                 servicePojo, this)));
     }
 
-    private Function<ObjectActionImpl, ObjectAssociation> createContributeeAssociationFunctor(
+    private Function<ObjectActionDefault, ObjectAssociation> createContributeeAssociationFunctor(
             final Object servicePojo,
             final ObjectSpecification contributeeType) {
-        return new Function<ObjectActionImpl, ObjectAssociation>(){
+        return new Function<ObjectActionDefault, ObjectAssociation>(){
             @Override
-            public ObjectAssociation apply(ObjectActionImpl input) {
+            public ObjectAssociation apply(ObjectActionDefault input) {
                 final ObjectSpecification returnType = input.getReturnType();
                 final ObjectAssociationAbstract association = returnType.isNotCollection()
                         ? new OneToOneAssociationContributee(servicePojo, input, contributeeType,
@@ -957,10 +957,10 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if(notContributed != null && notContributed.toActions()) {
                 continue;
             }
-            if(!(serviceAction instanceof ObjectActionImpl)) {
+            if(!(serviceAction instanceof ObjectActionDefault)) {
                 continue;
             }
-            final ObjectActionImpl contributedAction = (ObjectActionImpl) serviceAction;
+            final ObjectActionDefault contributedAction = (ObjectActionDefault) serviceAction;
 
             // see if qualifies by inspecting all parameters
             final int contributeeParam = contributeeParameterMatchOf(contributedAction);
@@ -1044,10 +1044,10 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if (isAlwaysHidden(mixinTypeAction)) {
                 continue;
             }
-            if(!(mixinTypeAction instanceof ObjectActionImpl)) {
+            if(!(mixinTypeAction instanceof ObjectActionDefault)) {
                 continue;
             }
-            final ObjectActionImpl mixinAction = (ObjectActionImpl) mixinTypeAction;
+            final ObjectActionDefault mixinAction = (ObjectActionDefault) mixinTypeAction;
 
             ObjectActionMixedIn mixedInAction =
                     new ObjectActionMixedIn(mixinType, mixinAction, this, objectMemberDependencies);

http://git-wip-us.apache.org/repos/asf/isis/blob/6c888136/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributee.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
index 953d4bc..98ed793 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
@@ -21,15 +21,12 @@ import java.util.List;
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.annotation.When;
 import org.apache.isis.applib.annotation.Where;
-import org.apache.isis.applib.filter.Filter;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.consent.Consent;
 import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
-import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetHolderImpl;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
-import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacetAbstract;
 import org.apache.isis.core.metamodel.facets.members.disabled.DisabledFacet;
@@ -44,7 +41,7 @@ import org.apache.isis.core.metamodel.spec.SpecificationLoader;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMemberDependencies;
 
-public class OneToManyAssociationContributee extends OneToManyAssociationImpl implements ContributeeMember2 {
+public class OneToManyAssociationContributee extends OneToManyAssociationDefault implements ContributeeMember2 {
 
     private final Object servicePojo;
     private final ObjectAction serviceAction;
@@ -58,9 +55,12 @@ public class OneToManyAssociationContributee extends OneToManyAssociationImpl im
     
     private final Identifier identifier;
 
-    private static ObjectSpecification typeOfSpec(final ObjectActionImpl objectAction, ObjectMemberDependencies objectMemberDependencies) {
+    private static ObjectSpecification typeOfSpec(
+            final ObjectActionDefault objectAction,
+            final ObjectMemberDependencies objectMemberDependencies) {
+
         final TypeOfFacet actionTypeOfFacet = objectAction.getFacet(TypeOfFacet.class);
-        SpecificationLoader specificationLookup = objectMemberDependencies.getSpecificationLoader();
+        final SpecificationLoader specificationLookup = objectMemberDependencies.getSpecificationLoader();
         // TODO: a bit of a hack; ought really to set up a fallback TypeOfFacetDefault which ensures that there is always
         // a TypeOfFacet for any contributee associations created from contributed actions.
         Class<? extends Object> cls = actionTypeOfFacet != null? actionTypeOfFacet.value(): Object.class;
@@ -69,10 +69,11 @@ public class OneToManyAssociationContributee extends OneToManyAssociationImpl im
     
     public OneToManyAssociationContributee(
             final Object servicePojo,
-            final ObjectActionImpl serviceAction,
+            final ObjectActionDefault serviceAction,
             final ObjectSpecification contributeeType,
             final ObjectMemberDependencies objectMemberDependencies) {
-        super(serviceAction.getFacetedMethod(), typeOfSpec(serviceAction, objectMemberDependencies),
+        super(serviceAction.getFacetedMethod(),
+                typeOfSpec(serviceAction, objectMemberDependencies),
                 objectMemberDependencies);
         this.servicePojo = servicePojo;
         this.serviceAction = serviceAction;
@@ -164,54 +165,18 @@ public class OneToManyAssociationContributee extends OneToManyAssociationImpl im
     //region > FacetHolder
 
     @Override
-    public Class<? extends Facet>[] getFacetTypes() {
-        return facetHolder.getFacetTypes();
-    }
-
-    @Override
-    public <T extends Facet> T getFacet(Class<T> cls) {
-        return facetHolder.getFacet(cls);
-    }
-    
-    @Override
-    public boolean containsFacet(Class<? extends Facet> facetType) {
-        return facetHolder.containsFacet(facetType);
-    }
-
-    @Override
-    public boolean containsDoOpFacet(java.lang.Class<? extends Facet> facetType) {
-        return facetHolder.containsDoOpFacet(facetType);
-    }
-
-    @Override
-    public List<Facet> getFacets(Filter<Facet> filter) {
-        return facetHolder.getFacets(filter);
+    protected FacetHolder getFacetHolder() {
+        return facetHolder;
     }
 
-    @Override
-    public void addFacet(Facet facet) {
-        facetHolder.addFacet(facet);
-    }
-
-    @Override
-    public void addFacet(MultiTypedFacet facet) {
-        facetHolder.addFacet(facet);
-    }
-    
-    @Override
-    public void removeFacet(Facet facet) {
-        facetHolder.removeFacet(facet);
-    }
-
-    @Override
-    public void removeFacet(Class<? extends Facet> facetType) {
-        facetHolder.removeFacet(facetType);
-    }
+    //endregion
 
-    public ObjectAdapter getServiceAdapter() {
+    private ObjectAdapter getServiceAdapter() {
         return getPersistenceSessionService().adapterFor(servicePojo);
     }
 
+    //region > ContributeeMember2 impl (getServiceContributedBy)
+
     @Override
     public ObjectSpecification getServiceContributedBy() {
         return getServiceAdapter().getSpecification();