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 2013/08/19 18:16:22 UTC

[2/2] git commit: ISIS-210: refactoring contributed actions

ISIS-210: refactoring contributed actions

- ObjectActionImpl#isContributed removed
- ObjectActionImpl#realTarget and #realParameters similarly removed

instead:
- ObjectActionContributee and ObjectActionParameterContributee act as wrappers around underlying ObjectActionImpl


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

Branch: refs/heads/master
Commit: fd132d641a6a24b2d614c5d3a8d159ac206a1159
Parents: 3bbaaab
Author: Dan Haywood <da...@apache.org>
Authored: Mon Aug 19 17:15:39 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Mon Aug 19 17:15:39 2013 +0100

----------------------------------------------------------------------
 .../viewer/dnd/view/action/ActionHelper.java    |   3 +-
 .../viewer/dnd/view/action/OptionFactory.java   |   2 +-
 .../domainobjects/ObjectActionReprRenderer.java |   6 +-
 .../dispatcher/view/action/ActionButton.java    |  16 +-
 .../dispatcher/view/action/ActionForm.java      |   4 +-
 .../dispatcher/view/action/ActionLink.java      |  17 +-
 .../scimpi/dispatcher/view/action/Methods.java  |  32 ++--
 .../dispatcher/view/action/RunAction.java       |   2 +-
 .../viewer/wicket/model/models/ActionModel.java |  36 ++--
 .../ajaxtable/BulkActionsLinkFactory.java       |   2 +-
 .../widgets/cssmenu/CssMenuBuilder.java         |  50 ++---
 .../core/metamodel/spec/ObjectActionSet.java    |  21 +--
 .../metamodel/spec/feature/ObjectAction.java    |  20 +-
 .../spec/feature/ObjectActionFilters.java       |  22 +--
 .../spec/feature/ObjectAssociations.java        |   4 +-
 .../specloader/specimpl/ContributedMember.java  |  30 ---
 .../specloader/specimpl/ContributeeMember.java  |  30 +++
 .../specimpl/ObjectActionContributee.java       | 175 +++++++++++++++++
 .../specloader/specimpl/ObjectActionImpl.java   | 186 ++++++++-----------
 .../specimpl/ObjectActionParameterAbstract.java |  15 +-
 .../ObjectActionParameterContributee.java       |  24 +++
 ...jectActionParameterParseableContributee.java |  66 +++++++
 .../specimpl/ObjectSpecificationAbstract.java   |  47 ++---
 .../OneToManyAssociationContributed.java        | 105 -----------
 .../OneToManyAssociationContributee.java        | 105 +++++++++++
 .../OneToOneActionParameterContributee.java     |  60 ++++++
 .../specimpl/OneToOneActionParameterImpl.java   |   1 +
 .../OneToOneAssociationContributed.java         |  75 --------
 .../OneToOneAssociationContributee.java         |  75 ++++++++
 ...acetDerivedFromChoicesFacetFacetFactory.java |  12 +-
 .../ActionParameterChoicesFacetFactory.java     |  27 ++-
 .../ActionParameterDefaultsFacetFactory.java    |  23 ++-
 32 files changed, 807 insertions(+), 486 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
index 7a39a93..6055598 100644
--- a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/ActionHelper.java
@@ -125,7 +125,8 @@ public class ActionHelper {
     }
 
     public ObjectAdapter getTarget() {
-        return action.realTarget(target);
+        return target;
+        //return action.realTarget(target);
     }
 
     public ObjectAdapter invoke() {

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/OptionFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/OptionFactory.java b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/OptionFactory.java
index 647fc0e..21f8a85 100644
--- a/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/OptionFactory.java
+++ b/component/viewer/dnd/impl/src/main/java/org/apache/isis/viewer/dnd/view/action/OptionFactory.java
@@ -77,7 +77,7 @@ public class OptionFactory {
                 final int noOfParameters = actions.get(i).getParameterCount();
                 if (noOfParameters == 0) {
                     option = ImmediateObjectOption.createOption(actions.get(i), target);
-                } else if (actions.get(i).isContributed() && noOfParameters == 1 && target != null && target.getSpecification().isOfType(actions.get(i).getParameters().get(0).getSpecification())) {
+                } else if (false /*actions.get(i).isContributed() && noOfParameters == 1 && target != null && target.getSpecification().isOfType(actions.get(i).getParameters().get(0).getSpecification())*/) {
                     option = ImmediateObjectOption.createServiceOption(actions.get(i), target);
                 } else {
                     option = DialoggedObjectOption.createOption(actions.get(i), target);

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
----------------------------------------------------------------------
diff --git a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
index fca5c8d..c36645c 100644
--- a/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
+++ b/component/viewer/restfulobjects/rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/domainobjects/ObjectActionReprRenderer.java
@@ -88,7 +88,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
 
     @Override
     protected ObjectAdapterLinkTo linkToForMutatorInvoke() {
-        if (!objectMember.isContributed()) {
+        if (true /*!objectMember.isContributed()*/) {
             return super.linkToForMutatorInvoke();
         }
         final DomainServiceLinkTo linkTo = new DomainServiceLinkTo();
@@ -118,7 +118,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
     }
 
     private Object argValueFor(final int i) {
-        if (objectMember.isContributed()) {
+        if (false /*objectMember.isContributed() */) {
             final ObjectActionParameter actionParameter = objectMember.getParameters().get(i);
             if (actionParameter.getSpecification().isOfType(objectAdapter.getSpecification())) {
                 return DomainObjectReprRenderer.newLinkToBuilder(rendererContext, Rel.VALUE, objectAdapter).build();
@@ -196,7 +196,7 @@ public class ObjectActionReprRenderer extends AbstractObjectMemberReprRenderer<O
 
     @Override
     protected void addLinksIsisProprietary() {
-        if (objectMember.isContributed()) {
+        if (false /*objectMember.isContributed() */) {
             final ObjectAdapter serviceAdapter = contributingServiceAdapter();
             final JsonRepresentation contributedByLink = DomainObjectReprRenderer.newLinkToBuilder(rendererContext, Rel.CONTRIBUTED_BY, serviceAdapter).build();
             getLinks().arrayAdd(contributedByLink);

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java
index c05fcd4..740de00 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionButton.java
@@ -76,14 +76,14 @@ public class ActionButton extends AbstractElementProcessor {
         final ObjectAdapter[] objectParameters;
         
         final ObjectAdapter target;
-        if (action.isContributed()) {
-            objectParameters= null;
-            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
-            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
-            target =  action.realTarget(object);
-            if (!action.hasReturn() && resultOverride == null) {
-                resultOverride = parameters[0];
-            }
+        if (false /*action.isContributed()*/) {
+//            objectParameters= null;
+//            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
+//            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
+//            target =  action.realTarget(object);
+//            if (!action.hasReturn() && resultOverride == null) {
+//                resultOverride = parameters[0];
+//            }
         } else {
             objectParameters = new ObjectAdapter[parameters.length];
             target = object;

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
index 5f47985..469b99d 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionForm.java
@@ -106,7 +106,7 @@ public class ActionForm extends AbstractElementProcessor {
         final String objectId = context.mapObject(object, Scope.INTERACTION);
         final String errorView = context.fullFilePath(parameterObject.forwardErrorTo == null ? context.getResourceFile() : parameterObject.forwardErrorTo);
         final String voidView = context.fullFilePath(parameterObject.forwardVoidTo == null ? context.getResourceFile() : parameterObject.forwardVoidTo);
-        if (action.isContributed() && !action.hasReturn() && parameterObject.resultOverride == null) {
+        if (false /* action.isContributed() && !action.hasReturn() && parameterObject.resultOverride == null */) {
             parameterObject.resultOverride = objectId;
         }
         final HiddenInputField[] hiddenFields = new HiddenInputField[] { new HiddenInputField("_" + OBJECT, objectId), new HiddenInputField("_" + VERSION, version), new HiddenInputField("_" + FORM_ID, parameterObject.formId), new HiddenInputField("_" + METHOD, parameterObject.methodName),
@@ -180,7 +180,7 @@ public class ActionForm extends AbstractElementProcessor {
         for (int i = 0; i < fields.length; i++) {
             final InputField field = fields[i];
             final ObjectActionParameter param = parameters.get(i);
-            if (action.isContributed() && i == 0) {
+            if (false /*action.isContributed() && i == 0*/) {
                 // fields[i].setValue(context.mapObject(object,
                 // Scope.INTERACTION));
                 fields[i].setType(InputField.REFERENCE);

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
index 9c41513..520e2bc 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/ActionLink.java
@@ -96,15 +96,14 @@ public class ActionLink extends AbstractElementProcessor {
         
         // TODO copied from ActionButton
         //final ObjectAdapter target;
-        if (action.isContributed()) {
-            objectParameters= null;
-            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
-            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
-         //   target =  action.realTarget(object);
-            target =  request.getContext().mapObject(action.realTarget(object), Scope.REQUEST);
-            if (!action.hasReturn() && resultOverride == null) {
-                resultOverride = parameters[0];
-            }
+        if (false /*action.isContributed() */) {
+//            objectParameters= null;
+//            System.arraycopy(parameters, 0, parameters, 1, parameters.length - 1);
+//            parameters[0] = request.getContext().mapObject(object, Scope.REQUEST);
+//            target =  request.getContext().mapObject(action.realTarget(object), Scope.REQUEST);
+//            if (!action.hasReturn() && resultOverride == null) {
+//                resultOverride = parameters[0];
+//            }
         } else {
             objectParameters = new ObjectAdapter[parameters.length];
             // target = object;

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
index a4f3c56..3823534 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/Methods.java
@@ -108,21 +108,21 @@ public class Methods extends AbstractElementProcessor {
                 request.appendHtml("<div class=\"actions\">");
                 writeMethods(request, adapter, action.getActions(), objectId, showForms, inclusionList, view, cancelTo);
                 request.appendHtml("</div>");
-            } else if (action.isContributed()) {
-                if (action.getParameterCount() == 1 && adapter.getSpecification().isOfType(action.getParameters().get(0).getSpecification())) {
-                    if (objectId != null) {
-                        final ObjectAdapter target = request.getContext().getMappedObject(objectId);
-                        final ObjectAdapter realTarget = action.realTarget(target);
-                        final String realTargetId = request.getContext().mapObject(realTarget, Scope.INTERACTION);
-                        writeMethod(request, adapter, new String[] { objectId }, action, realTargetId, showForms, view, cancelTo);
-                    } else {
-                        request.appendHtml("<div class=\"action\">");
-                        request.appendAsHtmlEncoded(action.getName());
-                        request.appendHtml("???</div>");
-                    }
-                } else if (!adapter.getSpecification().isService()) {
-                    writeMethod(request, adapter, new String[0], action, objectId, showForms, view, cancelTo);
-                }
+            } else if (false /*action.isContributed()*/) {
+//                if (action.getParameterCount() == 1 && adapter.getSpecification().isOfType(action.getParameters().get(0).getSpecification())) {
+//                    if (objectId != null) {
+//                        final ObjectAdapter target = request.getContext().getMappedObject(objectId);
+//                        final ObjectAdapter realTarget = action.realTarget(target);
+//                        final String realTargetId = request.getContext().mapObject(realTarget, Scope.INTERACTION);
+//                        writeMethod(request, adapter, new String[] { objectId }, action, realTargetId, showForms, view, cancelTo);
+//                    } else {
+//                        request.appendHtml("<div class=\"action\">");
+//                        request.appendAsHtmlEncoded(action.getName());
+//                        request.appendHtml("???</div>");
+//                    }
+//                } else if (!adapter.getSpecification().isService()) {
+//                    writeMethod(request, adapter, new String[0], action, objectId, showForms, view, cancelTo);
+//                }
             } else {
                 writeMethod(request, adapter, new String[0], action, objectId, showForms, view, cancelTo);
             }
@@ -160,7 +160,7 @@ public class Methods extends AbstractElementProcessor {
                 request.appendHtml("</span>");
             } else {
                 final String version = request.getContext().mapVersion(adapter);
-                if (action.getParameterCount() == 0 || (action.isContributed() && action.getParameterCount() == 1)) {
+                if (action.getParameterCount() == 0 || (false /*action.isContributed() && action.getParameterCount() == 1*/ )) {
                     ActionButton.write(request, adapter, action, parameters, version, "_generic." + Dispatcher.EXTENSION, null, null, null, null, null, null, null, null, null);
                 } else if (showForms) {
                     final CreateFormParameter params = new CreateFormParameter();

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
----------------------------------------------------------------------
diff --git a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
index 6aa2138..9610457 100644
--- a/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
+++ b/component/viewer/scimpi/dispatcher/src/main/java/org/apache/isis/viewer/scimpi/dispatcher/view/action/RunAction.java
@@ -64,7 +64,7 @@ public class RunAction extends AbstractElementProcessor {
         }
 
         // swap null parameter of the object's type to run a contributed method
-        if (action.isContributed()) {
+        if (false /*action.isContributed()*/) {
             final List<ObjectActionParameter> parameterSpecs = action.getParameters();
             for (int i = 0; i < parameters.length; i++) {
                 if (parameters[i] == null && object.getSpecification().isOfType(parameterSpecs.get(i).getSpecification())) {

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
index 8983e3f..8cab476 100644
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionModel.java
@@ -119,7 +119,7 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
         final Mode actionMode = determineActionMode(objectAction, contextAdapter);
         PageParameterNames.ACTION_MODE.addEnumTo(pageParameters, actionMode);
 
-        addActionParamContextIfPossible(objectAction, contextAdapter, pageParameters);
+        //addActionParamContextIfPossible(objectAction, contextAdapter, pageParameters);
         return pageParameters;
     }
 
@@ -247,23 +247,23 @@ public class ActionModel extends BookmarkableModel<ObjectAdapter> {
         return objectAction.promptForParameters(contextAdapter)?Mode.PARAMETERS:Mode.RESULTS;
     }
 
-	private static void addActionParamContextIfPossible(final ObjectAction objectAction, final ObjectAdapter contextAdapter, final PageParameters pageParameters) {
-        if (contextAdapter == null) {
-            return;
-        }
-        if(!objectAction.isContributed()) {
-            return;
-        }
-        int i = 0;
-        for (final ObjectActionParameter actionParam : objectAction.getParameters()) {
-            if (ObjectActionParameters.compatibleWith(contextAdapter, actionParam)) {
-                final String oidKeyValue = "" + i + "=" + contextAdapter.getOid().enString(getOidMarshaller());
-                PageParameterNames.ACTION_PARAM_CONTEXT.addStringTo(pageParameters, oidKeyValue);
-                return;
-            }
-            i++;
-        }
-    }
+//	private static void addActionParamContextIfPossible(final ObjectAction objectAction, final ObjectAdapter contextAdapter, final PageParameters pageParameters) {
+//        if (contextAdapter == null) {
+//            return;
+//        }
+//        if(!objectAction.isContributed()) {
+//            return;
+//        }
+//        int i = 0;
+//        for (final ObjectActionParameter actionParam : objectAction.getParameters()) {
+//            if (ObjectActionParameters.compatibleWith(contextAdapter, actionParam)) {
+//                final String oidKeyValue = "" + i + "=" + contextAdapter.getOid().enString(getOidMarshaller());
+//                PageParameterNames.ACTION_PARAM_CONTEXT.addStringTo(pageParameters, oidKeyValue);
+//                return;
+//            }
+//            i++;
+//        }
+//    }
 
     private static String determineActionId(final ObjectAction objectAction) {
         final Identifier identifier = objectAction.getIdentifier();

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
index b1e3757..957e415 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
@@ -67,7 +67,7 @@ final class BulkActionsLinkFactory implements CssMenuLinkFactory {
                     final ObjectAdapter entityAdapter = entityAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
 
                     int numParameters = objectAction.getParameterCount();
-                    if(objectAction.isContributed()) {
+                    if(false /*objectAction.isContributed() */) {
                         // a contributed action
                         if(numParameters != 1) {
                             return;

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
index 66c7832..3008a39 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
@@ -139,7 +139,7 @@ public class CssMenuBuilder {
 
         Builder subMenuItemBuilder = null;
         
-        final ObjectAdapterMemento targetAdapterMemento = determineAdapterFor(action);
+        final ObjectAdapterMemento targetAdapterMemento = adapterMemento; // determineAdapterFor(action);
         if(targetAdapterMemento != null) {
             // against an entity or a service (if a contributed action)
             subMenuItemBuilder = parent.newSubMenuItem(targetAdapterMemento, action, cssMenuLinkFactory);
@@ -157,30 +157,30 @@ public class CssMenuBuilder {
         }
     }
 
-    /**
-     * It's a bit hokey to have to do this, but the
-     * {@link ObjectSpecification#getServiceActionsReturning(ActionType...)
-     * method we call} on {@link ObjectSpecification}, while nicely traversing
-     * the services for us, unfortunately does not pass us back the service
-     * adapters also.
-     */
-    private ObjectAdapterMemento determineAdapterFor(final ObjectAction action) {
-        
-        if(getServiceAdapters() != null) {
-            // null check required because could be null.
-            
-            // search through service adapters first
-            final ObjectSpecification onType = action.getOnType();
-            for (final ObjectAdapter serviceAdapter : getServiceAdapters()) {
-                if (serviceAdapter.getSpecification() == onType) {
-                    return ObjectAdapterMemento.createOrNull(serviceAdapter);
-                }
-            }
-        }
-
-        // otherwise, specified adapter (could be null)
-        return adapterMemento;
-    }
+//    /**
+//     * It's a bit hokey to have to do this, but the
+//     * {@link ObjectSpecification#getServiceActionsReturning(ActionType...)
+//     * method we call} on {@link ObjectSpecification}, while nicely traversing
+//     * the services for us, unfortunately does not pass us back the service
+//     * adapters also.
+//     */
+//    private ObjectAdapterMemento determineAdapterFor(final ObjectAction action) {
+//        
+//        if(getServiceAdapters() != null) {
+//            // null check required because could be null.
+//            
+//            // search through service adapters first
+//            final ObjectSpecification onType = action.getOnType();
+//            for (final ObjectAdapter serviceAdapter : getServiceAdapters()) {
+//                if (serviceAdapter.getSpecification() == onType) {
+//                    return ObjectAdapterMemento.createOrNull(serviceAdapter);
+//                }
+//            }
+//        }
+//
+//        // otherwise, specified adapter (could be null)
+//        return adapterMemento;
+//    }
 
     protected List<ObjectAdapter> getServiceAdapters() {
         return serviceAdapters;

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectActionSet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectActionSet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectActionSet.java
index f299001..3bcac33 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectActionSet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectActionSet.java
@@ -114,11 +114,6 @@ public class ObjectActionSet implements ObjectAction {
         return false;
     }
 
-    @Override
-    public boolean isContributed() {
-        return false;
-    }
-
     /**
      * Always returns <tt>null</tt>.
      */
@@ -132,14 +127,14 @@ public class ObjectActionSet implements ObjectAction {
         return null;
     }
 
-    // /////////////////////////////////////////////////////////////
-    // target
-    // /////////////////////////////////////////////////////////////
-
-    @Override
-    public ObjectAdapter realTarget(final ObjectAdapter target) {
-        return null;
-    }
+//    // /////////////////////////////////////////////////////////////
+//    // target
+//    // /////////////////////////////////////////////////////////////
+//
+//    @Override
+//    public ObjectAdapter realTarget(final ObjectAdapter target) {
+//        return null;
+//    }
 
     // /////////////////////////////////////////////////////////////
     // execute

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
index 2a5b2ed..42f5bf0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
@@ -44,23 +44,19 @@ public interface ObjectAction extends ObjectMember {
     ActionSemantics.Of getSemantics();
 
     /**
-     * Determine the real target for this action. If this action represents an
-     * object action than the target is returned. If this action is on a service
-     * then that service will be returned.
-     */
-    ObjectAdapter realTarget(ObjectAdapter target);
-
-    /**
      * Returns the specification for the type of object that this action can be
      * invoked upon.
      */
     ObjectSpecification getOnType();
 
-    /**
-     * Return true if the action is run on a service object using the target
-     * object as a parameter.
-     */
-    boolean isContributed();
+    
+//    /**
+//     * Determine the real target for this action. If this action represents an
+//     * object action than the target is returned. If this action is on a service
+//     * then that service will be returned.
+//     */
+//    ObjectAdapter realTarget(ObjectAdapter target);
+
 
     boolean promptForParameters(ObjectAdapter target);
 

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
index 45d7de9..1114bd6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
@@ -68,17 +68,17 @@ public class ObjectActionFilters {
             }};
     }
 
-    public static Filter<ObjectAction> contributedAnd1ParamAndVoid() {
-        return new Filter<ObjectAction>(){
-            @Override
-            public boolean accept(final ObjectAction objectAction) {
-                boolean contributed = objectAction.isContributed();
-                boolean has1Param = objectAction.getParameterCount() == 1;
-                boolean hasReturn = objectAction.hasReturn();
-                return contributed && has1Param && !hasReturn;
-            }
-        };
-    }
+//    public static Filter<ObjectAction> contributedAnd1ParamAndVoid() {
+//        return new Filter<ObjectAction>(){
+//            @Override
+//            public boolean accept(final ObjectAction objectAction) {
+//                boolean contributed = objectAction.isContributed();
+//                boolean has1Param = objectAction.getParameterCount() == 1;
+//                boolean hasReturn = objectAction.hasReturn();
+//                return contributed && has1Param && !hasReturn;
+//            }
+//        };
+//    }
 
     public static Filter<ObjectAction> filterOfType(final ActionType type) {
         return new Filter<ObjectAction>(){

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociations.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociations.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociations.java
index 6c6e20a..18e4f75 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociations.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAssociations.java
@@ -30,7 +30,7 @@ import com.google.common.collect.Maps;
 
 import org.apache.isis.core.metamodel.facets.members.order.MemberOrderFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.specimpl.ContributedMember;
+import org.apache.isis.core.metamodel.specloader.specimpl.ContributeeMember;
 
 public final class ObjectAssociations {
 
@@ -98,7 +98,7 @@ public final class ObjectAssociations {
             @Override
             public boolean apply(final ObjectAssociation t) {
                 return contributed.isIncluded() || 
-                       !(t instanceof ContributedMember);
+                       !(t instanceof ContributeeMember);
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributedMember.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributedMember.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributedMember.java
deleted file mode 100644
index 6ebbed2..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributedMember.java
+++ /dev/null
@@ -1,30 +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 org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacet;
-import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacetAbstract;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
-
-/**
- * Marker interface indicating an a contributed association or action.
- */
-public interface ContributedMember { 
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributeeMember.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributeeMember.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributeeMember.java
new file mode 100644
index 0000000..34f2ce8
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ContributeeMember.java
@@ -0,0 +1,30 @@
+/**
+ *  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 org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacet;
+import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacetAbstract;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
+
+/**
+ * Marker interface indicating an a contributed association or action.
+ */
+public interface ContributeeMember { 
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/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
new file mode 100644
index 0000000..b95ce85
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
@@ -0,0 +1,175 @@
+/**
+ *  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.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.exceptions.UnknownTypeException;
+import org.apache.isis.core.commons.lang.CastUtils;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
+import org.apache.isis.core.metamodel.consent.InteractionResultSet;
+import org.apache.isis.core.metamodel.facets.FacetedMethodParameter;
+import org.apache.isis.core.metamodel.facets.TypedHolder;
+import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+import org.apache.isis.core.metamodel.facets.object.bounded.BoundedFacetUtils;
+import org.apache.isis.core.metamodel.facets.param.autocomplete.ActionParameterAutoCompleteFacet;
+import org.apache.isis.core.metamodel.interactions.InteractionUtils;
+import org.apache.isis.core.metamodel.interactions.ValidityContext;
+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.ObjectMemberContext;
+
+public class ObjectActionContributee extends ObjectActionImpl implements ContributeeMember {
+
+    private final ObjectAdapter serviceAdapter;
+    private final ObjectActionImpl serviceAction;
+    private int contributeeParam;
+    private final ObjectSpecification contributeeType;
+
+    /**
+     * Lazily initialized by {@link #getParameters()} (so don't use directly!)
+     */
+    private List<ObjectActionParameterContributee> parameters;
+
+    /**
+     * @param contributeeParam - the parameter number which corresponds to the contributee, and so should be suppressed.
+     */
+    public ObjectActionContributee(
+            final ObjectAdapter serviceAdapter,
+            final ObjectActionImpl serviceAction,
+            final int contributeeParam,
+            final ObjectSpecification contributeeType,
+            final ObjectMemberContext objectMemberContext) {
+        super(serviceAction.getFacetedMethod(), objectMemberContext, null);
+        
+        this.serviceAdapter = serviceAdapter;
+        this.serviceAction = serviceAction;
+        this.contributeeType = contributeeType;
+        this.contributeeParam = contributeeParam;
+    }
+
+    @Override
+    public ObjectSpecification getOnType() {
+        return contributeeType;
+    }
+
+    public int getParameterCount() {
+        return serviceAction.getParameterCount() - 1;
+    }
+
+    public synchronized List<ObjectActionParameter> getParameters() {
+        
+        if (this.parameters == null) {
+            final List<ObjectActionParameter> serviceParameters = serviceAction.getParameters();
+            
+            final List<ObjectActionParameterContributee> contributeeParameters = Lists.newArrayList();
+            
+            int contributeeParamNum = 0;
+            for (int serviceParamNum = 0; serviceParamNum < serviceParameters.size(); serviceParamNum++ ) {
+                if(serviceParamNum == contributeeParam) {
+                    // skip so is omitted from the Contributed action
+                    continue;
+                }
+                
+                final ObjectActionParameterAbstract serviceParameter = 
+                        (ObjectActionParameterAbstract) serviceParameters.get(serviceParamNum);
+                final ObjectActionParameterContributee contributedParam;
+                if(serviceParameter instanceof ObjectActionParameterParseable) {
+                    contributedParam = new ObjectActionParameterParseableContributee(
+                            serviceAdapter, serviceAction, serviceParameter, serviceParamNum, 
+                            contributeeParamNum, this);
+                } else if(serviceParameter instanceof OneToOneActionParameterImpl) {
+                    contributedParam = new OneToOneActionParameterContributee(
+                            serviceAdapter, serviceAction, serviceParameter, serviceParamNum, 
+                            contributeeParamNum, this);
+                } else {
+                    throw new RuntimeException("Unknown implementation of ObjectActionParameter; " + serviceParameter.getClass().getName());
+                }
+                contributeeParameters.add(contributedParam);
+                
+                contributeeParamNum++;
+            }
+            this.parameters = contributeeParameters;
+        }
+        return CastUtils.listOf(parameters, ObjectActionParameter.class);
+    }
+
+    
+    @Override
+    public Consent isVisible(final AuthenticationSession session, final ObjectAdapter contributee, Where where) {
+        return serviceAction.isVisible(session, serviceAdapter, where);
+    }
+
+    @Override
+    public Consent isUsable(final AuthenticationSession session, final ObjectAdapter contributee, Where where) {
+        return serviceAction.isUsable(session, serviceAdapter, where);
+    }
+
+    @Override
+    public ObjectAdapter[] getDefaults(final ObjectAdapter target) {
+        final ObjectAdapter[] contributorDefaults = serviceAction.getDefaults(serviceAdapter);
+        return removeElementFromArray(contributorDefaults, contributeeParam, new ObjectAdapter[]{});
+    }
+
+    @Override
+    public ObjectAdapter[][] getChoices(final ObjectAdapter target) {
+        final ObjectAdapter[][] serviceChoices = serviceAction.getChoices(serviceAdapter);
+        return removeElementFromArray(serviceChoices, contributeeParam, new ObjectAdapter[][]{});
+    }
+        
+    public Consent isProposedArgumentSetValid(final ObjectAdapter contributee, final ObjectAdapter[] proposedArguments) {
+        ObjectAdapter[] serviceArguments = argsPlusContributee(contributee, proposedArguments);
+        return serviceAction.isProposedArgumentSetValid(serviceAdapter, serviceArguments);
+    }
+
+    @Override
+    public ObjectAdapter execute(final ObjectAdapter contributee, final ObjectAdapter[] arguments) {
+        return serviceAction.execute(serviceAdapter, argsPlusContributee(contributee, arguments));
+    }
+
+    private ObjectAdapter[] argsPlusContributee(final ObjectAdapter contributee, final ObjectAdapter[] arguments) {
+        return addElementToArray(arguments, contributeeParam, contributee, new ObjectAdapter[]{});
+    }
+
+    // //////////////////////////////////////
+
+    private static <T> T[] addElementToArray(T[] array, final int n, final T element, final T[] type) {
+        List<T> list = Lists.newArrayList(Arrays.asList(array));
+        list.add(n, element);
+        return list.toArray(type);
+    }
+
+    private static <T> T[] removeElementFromArray(T[] array, int n, T[] t) {
+        List<T> list = Lists.newArrayList(Arrays.asList(array));
+        list.remove(n);
+        return list.toArray(t);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/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
index 594ea4d..adfe44c 100644
--- 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
@@ -90,17 +90,7 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
      */
     private List<ObjectActionParameter> parameters;
 
-    /**
-     * Controls the initialization of {@link #contributed}.
-     */
-    private boolean knownWhetherContributed = false;
-    /**
-     * Lazily initialized, controlled by {@link #knownWhetherContributed}
-     * 
-     * @see #isContributed()
-     */
-    private boolean contributed;
-
+    
     // //////////////////////////////////////////////////////////////////
     // Constructors
     // //////////////////////////////////////////////////////////////////
@@ -194,27 +184,6 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
         return ActionType.USER;
     }
 
-    @Override
-    public boolean isContributed() {
-        if (!knownWhetherContributed) {
-            contributed = determineWhetherContributed();
-            knownWhetherContributed = true;
-        }
-        return contributed;
-    }
-
-    private boolean determineWhetherContributed() {
-        if (getOnType().isService() && getParameterCount() > 0) {
-            final List<ObjectActionParameter> params = getParameters();
-            for (int i = 0; i < params.size(); i++) {
-                if (params.get(i).isObject()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     // /////////////////////////////////////////////////////////////
     // Parameters
     // /////////////////////////////////////////////////////////////
@@ -226,25 +195,26 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
 
     @Override
     public boolean promptForParameters(final ObjectAdapter target) {
-        switch(getParameterCount()) {
-            case 0:
-                return false;
-            case 1:
-                if(!isContributed()) {
-                    return true;
-                }
-                if(target == null) {
-                    return true;
-                }
-                if (target.getSpecification().isService()) {
-                    return true;
-                }
-                final ObjectSpecification targetSpec = target.getSpecification();
-                final ObjectSpecification param0Spec = getParameters().get(0).getSpecification();
-                return !targetSpec.isOfType(param0Spec);
-            default:
-                return true;
-        }
+        return getParameterCount() != 0;
+//        switch(getParameterCount()) {
+//            case 0:
+//                return false;
+//            case 1:
+//                if(!isContributed()) {
+//                    return true;
+//                }
+//                if(target == null) {
+//                    return true;
+//                }
+//                if (target.getSpecification().isService()) {
+//                    return true;
+//                }
+//                final ObjectSpecification targetSpec = target.getSpecification();
+//                final ObjectSpecification param0Spec = getParameters().get(0).getSpecification();
+//                return !targetSpec.isOfType(param0Spec);
+//            default:
+//                return true;
+//        }
     }
 
     /**
@@ -263,15 +233,18 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
             for (int i = 0; i < parameterCount; i++) {
                 final TypedHolder paramPeer = paramPeers.get(i);
                 final ObjectSpecification specification = ObjectMemberAbstract.getSpecification(getSpecificationLookup(), paramPeer.getType());
+                
+                final ObjectActionParameter parameter;
                 if (specification.isParseable()) {
-                    parameters.add(new ObjectActionParameterParseable(i, this, paramPeer));
+                    parameter = new ObjectActionParameterParseable(i, this, paramPeer);
                 } else if (specification.isNotCollection()) {
-                    parameters.add(new OneToOneActionParameterImpl(i, this, paramPeer));
+                    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;
         }
@@ -341,10 +314,10 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
         return new ActionVisibilityContext(getDeploymentCategory(), session, invocationMethod, targetObjectAdapter, getIdentifier(), where);
     }
 
-    @Override
-    public Consent isVisible(final AuthenticationSession session, final ObjectAdapter target, Where where) {
-        return super.isVisible(session, realTarget(target), where);
-    }
+//    @Override
+//    public Consent isVisible(final AuthenticationSession session, final ObjectAdapter target, Where where) {
+//        return super.isVisible(session, realTarget(target), where);
+//    }
 
     // /////////////////////////////////////////////////////////////
     // Usable (or disabled)
@@ -355,10 +328,10 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
         return new ActionUsabilityContext(getDeploymentCategory(), session, invocationMethod, targetObjectAdapter, getIdentifier(), where);
     }
 
-    @Override
-    public Consent isUsable(final AuthenticationSession session, final ObjectAdapter target, Where where) {
-        return super.isUsable(session, realTarget(target), where);
-    }
+//    @Override
+//    public Consent isUsable(final AuthenticationSession session, final ObjectAdapter target, Where where) {
+//        return super.isUsable(session, realTarget(target), where);
+//    }
 
     // //////////////////////////////////////////////////////////////////
     // validate
@@ -369,9 +342,9 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
      * initiated {@link InteractionInvocationMethod#BY_USER by user}.
      */
     @Override
-    public Consent isProposedArgumentSetValid(final ObjectAdapter object, final ObjectAdapter[] proposedArguments) {
-        final ObjectAdapter[] parameters = realParameters(object, proposedArguments);
-        return isProposedArgumentSetValidResultSet(realTarget(object), parameters).createConsent();
+    public Consent isProposedArgumentSetValid(final ObjectAdapter target, final ObjectAdapter[] proposedArguments) {
+        //final ObjectAdapter[] parameters = realParameters(target, proposedArguments);
+        return isProposedArgumentSetValidResultSet(target, proposedArguments).createConsent();
     }
 
     private InteractionResultSet isProposedArgumentSetValidResultSet(final ObjectAdapter object, final ObjectAdapter[] proposedArguments) {
@@ -403,54 +376,47 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
     // //////////////////////////////////////////////////////////////////
 
     @Override
-    public ObjectAdapter execute(final ObjectAdapter object, final ObjectAdapter[] parameters) {
+    public ObjectAdapter execute(final ObjectAdapter target, final ObjectAdapter[] arguments) {
         if(LOG.isDebugEnabled()) {
-            LOG.debug("execute action " + object + "." + getId());
+            LOG.debug("execute action " + target + "." + getId());
         }
-        final ObjectAdapter[] params = realParameters(object, parameters);
-        final ObjectAdapter target = realTarget(object);
+        //final ObjectAdapter[] params = realParameters(target, arguments);
         final ActionInvocationFacet facet = getFacet(ActionInvocationFacet.class);
-        return facet.invoke(target, params);
+        return facet.invoke(target, arguments);
     }
 
-    private ActionInvocationFacet getActionInvocationFacet() {
+    protected ActionInvocationFacet getActionInvocationFacet() {
         return getFacetedMethod().getFacet(ActionInvocationFacet.class);
     }
 
-    /**
-     * Previously (prior to 3.0.x) this method had a check to see if the action
-     * was on an instance. With the reflector redesign this has been removed,
-     * because NOF 3.x only supports instance methods, not class-level methods.
-     */
-    @Override
-    public ObjectAdapter realTarget(final ObjectAdapter target) {
-        if (target == null) {
-            return findService();
-        } else if (target.getSpecification().isService()) {
-            return target;
-        } else if (isContributed()) {
-            return findService();
-        } else {
-            return target;
-        }
-    }
-
-    private ObjectAdapter findService() {
-        final List<ObjectAdapter> services = getServicesProvider().getServices();
-        for (final ObjectAdapter serviceAdapter : services) {
-            if (serviceAdapter.getSpecification() == getOnType()) {
-                return serviceAdapter;
-            }
-        }
-        throw new IsisException("failed to find service for action " + this.getName());
-    }
-
-    private ObjectAdapter[] realParameters(final ObjectAdapter target, final ObjectAdapter[] parameters) {
-        if (parameters != null) {
-            return parameters;
-        }
-        return isContributed() ? new ObjectAdapter[] { target } : new ObjectAdapter[0];
-    }
+//    protected ObjectAdapter realTarget(final ObjectAdapter target) {
+//        if (target == null) {
+//            return findService();
+//        } else if (target.getSpecification().isService()) {
+//            return target;
+//        } else if (false /*isContributed()*/) {
+//            return findService();
+//        } else {
+//            return target;
+//        }
+//    }
+
+//    private ObjectAdapter findService() {
+//        final List<ObjectAdapter> services = getServicesProvider().getServices();
+//        for (final ObjectAdapter serviceAdapter : services) {
+//            if (serviceAdapter.getSpecification() == getOnType()) {
+//                return serviceAdapter;
+//            }
+//        }
+//        throw new IsisException("failed to find service for action " + this.getName());
+//    }
+
+//    protected ObjectAdapter[] realParameters(final ObjectAdapter target, final ObjectAdapter[] parameters) {
+//        if (parameters != null) {
+//            return parameters;
+//        }
+//        return false /*isContributed()*/ ? new ObjectAdapter[] { target } : new ObjectAdapter[0];
+//    }
 
     // //////////////////////////////////////////////////////////////////
     // defaults
@@ -458,7 +424,6 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
 
     @Override
     public ObjectAdapter[] getDefaults(final ObjectAdapter target) {
-        final ObjectAdapter realTarget = realTarget(target);
 
         final int parameterCount = getParameterCount();
         final List<ObjectActionParameter> parameters = getParameters();
@@ -472,7 +437,7 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
         final ActionDefaultsFacet facet = getFacet(ActionDefaultsFacet.class);
         if (!facet.isNoop()) {
             // use the old defaultXxx approach
-            parameterDefaultPojos = facet.getDefaults(realTarget);
+            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);
             }
@@ -492,7 +457,7 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
             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(realTarget);
+                    parameterDefaultPojos[i] = paramFacet.getDefault(target);
                 } else {
                     parameterDefaultPojos[i] = null;
                 }
@@ -507,7 +472,7 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
         }
 
         // set the target if contributed.
-        if (isContributed() && target != null) {
+        if (false /*isContributed()*/ && target != null) {
             for (int i = 0; i < parameterCount; i++) {
                 if (target.getSpecification().isOfType(parameters.get(i).getSpecification())) {
                     parameterDefaultAdapters[i] = target;
@@ -527,7 +492,6 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
 
     @Override
     public ObjectAdapter[][] getChoices(final ObjectAdapter target) {
-        final ObjectAdapter realTarget = realTarget(target);
 
         final int parameterCount = getParameterCount();
         Object[][] parameterChoicesPojos;
@@ -537,7 +501,7 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
 
         if (!facet.isNoop()) {
             // using the old choicesXxx() approach
-            parameterChoicesPojos = facet.getChoices(realTarget);
+            parameterChoicesPojos = facet.getChoices(target);
 
             // if no options, or not the right number of pojos, then default
             if (parameterChoicesPojos == null) {
@@ -553,7 +517,7 @@ public class ObjectActionImpl extends ObjectMemberAbstract implements ObjectActi
             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(realTarget);
+                    parameterChoicesPojos[i] = paramFacet.getChoices(target);
                 } else {
                     parameterChoicesPojos[i] = new Object[0];
                 }

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/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 8fac3b8..90f1d84 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
@@ -102,6 +102,13 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
         return parentAction;
     }
 
+    /**
+     * NOT API, but exposed for the benefit of {@link ObjectActionParameterContributee}.
+     */
+    public TypedHolder getPeer() {
+        return peer;
+    }
+
     @Override
     public ObjectSpecification getSpecification() {
         return ObjectMemberAbstract.getSpecification(getSpecificationLookup(), peer.getType());
@@ -260,7 +267,7 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
         final ActionParameterChoicesFacet choicesFacet = getFacet(ActionParameterChoicesFacet.class);
 
         if (choicesFacet != null) {
-            final Object[] choices = choicesFacet.getChoices(parentAction.realTarget(adapter));
+            final Object[] choices = choicesFacet.getChoices(adapter);
             checkChoicesOrAutoCompleteType(getSpecificationLookup(), choices, getSpecification());
             for (final Object choice : choices) {
                 parameterChoices.add(getAdapterMap().adapterFor(choice));
@@ -284,7 +291,7 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
         final ActionParameterAutoCompleteFacet facet = getFacet(ActionParameterAutoCompleteFacet.class);
 
         if (facet != null) {
-            final Object[] autoCompleteChoices = facet.autoComplete(parentAction.realTarget(adapter), searchArg);
+            final Object[] autoCompleteChoices = facet.autoComplete(adapter, searchArg);
             checkChoicesOrAutoCompleteType(getSpecificationLookup(), autoCompleteChoices, getSpecification());
             for (final Object autoCompleteChoice : autoCompleteChoices) {
                 autoCompleteChoiceAdapters.add(getAdapterMap().adapterFor(autoCompleteChoice));
@@ -321,14 +328,14 @@ public abstract class ObjectActionParameterAbstract implements ObjectActionParam
 
     @Override
     public ObjectAdapter getDefault(final ObjectAdapter adapter) {
-        if (parentAction.isContributed() && adapter != null) {
+        if (false /*parentAction.isContributed()*/ && adapter != null) {
             if (adapter.getSpecification().isOfType(getSpecification())) {
                 return adapter;
             }
         }
         final ActionParameterDefaultsFacet defaultsFacet = getFacet(ActionParameterDefaultsFacet.class);
         if (defaultsFacet != null) {
-            final Object dflt = defaultsFacet.getDefault(parentAction.realTarget(adapter));
+            final Object dflt = defaultsFacet.getDefault(adapter);
             if (dflt == null) {
                 // it's possible that even though there is a default facet, when
                 // invoked it

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterContributee.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterContributee.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterContributee.java
new file mode 100644
index 0000000..4930fa1
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterContributee.java
@@ -0,0 +1,24 @@
+/**
+ *  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 org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+
+
+public interface ObjectActionParameterContributee extends ObjectActionParameter {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseableContributee.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseableContributee.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseableContributee.java
new file mode 100644
index 0000000..69e4f53
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionParameterParseableContributee.java
@@ -0,0 +1,66 @@
+/**
+ *  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 org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+
+/**
+ * REVIEW: this is a bit hacky having 'Contributed' subtypes of both {@link ObjectActionParameterParseable} and also
+ * {@link OneToOneActionParameterImpl}.  However, the {@link ObjectActionParameterParseable parseable} version
+ * only seems to be used by the DnD viewer; Scimpi, Wicket and RO do not.  So, we could hopefully simplify the
+ * hierarchy at some point.
+ */
+public class ObjectActionParameterParseableContributee extends ObjectActionParameterParseable implements ObjectActionParameterContributee {
+
+    private final ObjectAdapter serviceAdapter;
+    @SuppressWarnings("unused")
+    private final ObjectActionImpl serviceAction;
+    private final ObjectActionParameter serviceActionParameter;
+    @SuppressWarnings("unused")
+    private final int serviceParamNumber;
+
+    public ObjectActionParameterParseableContributee(
+            final ObjectAdapter serviceAdapter,
+            final ObjectActionImpl serviceAction,
+            final ObjectActionParameterAbstract serviceActionParameter,
+            final int serviceParamNumber,
+            final int number,
+            final ObjectActionContributee objectAction) {
+        super(number, objectAction, serviceActionParameter.getPeer());
+        this.serviceAdapter = serviceAdapter;
+        this.serviceAction = serviceAction;
+        this.serviceActionParameter = serviceActionParameter;
+        this.serviceParamNumber = serviceParamNumber;
+    }
+
+    @Override
+    public ObjectAdapter[] getAutoComplete(ObjectAdapter adapter, String searchArg) {
+        return serviceActionParameter.getAutoComplete(serviceAdapter, searchArg);
+    }
+
+    @Override
+    public ObjectAdapter[] getChoices(final ObjectAdapter adapter) {
+        return serviceActionParameter.getChoices(serviceAdapter);
+    }
+
+    @Override
+    public ObjectAdapter getDefault(final ObjectAdapter adapter) {
+        return serviceActionParameter.getDefault(serviceAdapter);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/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 f5f9395..3b661b4 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
@@ -873,7 +873,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if(!serviceAction.hasReturn()) {
                 continue;
             }
-            if (serviceAction.getParameterCount() != 1 || !matchesParameterOf(serviceAction)) {
+            if (serviceAction.getParameterCount() != 1 || contributeeParameterMatchOf(serviceAction) == -1) {
                 continue;
             }
             if(!(serviceAction instanceof ObjectActionImpl)) {
@@ -888,9 +888,9 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             public ObjectAssociation apply(ObjectActionImpl input) {
                 final ObjectSpecification returnType = input.getReturnType();
                 if(returnType.isNotCollection()) {
-                    return new OneToOneAssociationContributed(serviceAdapter, input, objectMemberContext);
+                    return new OneToOneAssociationContributee(serviceAdapter, input, objectMemberContext);
                 } else {
-                    return new OneToManyAssociationContributed(serviceAdapter, input, objectMemberContext);
+                    return new OneToManyAssociationContributee(serviceAdapter, input, objectMemberContext);
                 }
             }
         }));
@@ -942,17 +942,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         if (specification == this) {
             return;
         }
-        final List<ObjectAction> contributedActions = findContributedActions(specification, actionType);
-        // only add if there are matching subactions.
-        if (contributedActions.isEmpty()) {
-            return;
-        }
-        final ObjectActionSet contributedActionSet = new ObjectActionSet("id", serviceAdapter.titleString(), contributedActions);
-        contributedActionSetsToAppendTo.add(contributedActionSet);
-    }
-
-    private List<ObjectAction> findContributedActions(final ObjectSpecification specification, final ActionType actionType) {
-        final List<ObjectAction> contributedActions = Lists.newArrayList();
+        final List<ObjectAction> contributeeActions = Lists.newArrayList();
         final List<ObjectAction> serviceActions = specification.getObjectActions(actionType, Contributed.INCLUDED, Filters.<ObjectAction>any());
         for (final ObjectAction serviceAction : serviceActions) {
             if (serviceAction.isAlwaysHidden()) {
@@ -962,23 +952,38 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if(notContributed != null && notContributed.toActions()) {
                 continue;
             }
-
+            if(!(serviceAction instanceof ObjectActionImpl)) {
+                continue;
+            }
+            ObjectActionImpl serviceActionImpl = (ObjectActionImpl) serviceAction;
+        
             // see if qualifies by inspecting all parameters
-            if (matchesParameterOf(serviceAction)) {
-                contributedActions.add(serviceAction);
+            final int contributeeParam = contributeeParameterMatchOf(serviceActionImpl);
+            if (contributeeParam != -1) {
+                ObjectActionContributee contributee = 
+                        new ObjectActionContributee(serviceAdapter, serviceActionImpl, contributeeParam, this, objectMemberContext);
+                contributeeActions.add(contributee);
             }
         }
-        return contributedActions;
+        // only add if there are matching subactions.
+        if (contributeeActions.isEmpty()) {
+            return;
+        }
+        final ObjectActionSet contributedActionSet = new ObjectActionSet("id", serviceAdapter.titleString(null), contributeeActions);
+        contributedActionSetsToAppendTo.add(contributedActionSet);
     }
 
-    private boolean matchesParameterOf(final ObjectAction serviceAction) {
+    /**
+     * @param the number of the parameter that matches, or -1 if none.
+     */
+    private int contributeeParameterMatchOf(final ObjectAction serviceAction) {
         final List<ObjectActionParameter> params = serviceAction.getParameters();
         for (final ObjectActionParameter param : params) {
             if (isOfType(param.getSpecification())) {
-                return true;
+                return param.getNumber();
             }
         }
-        return false;
+        return -1;
     }
 
     // //////////////////////////////////////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributed.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributed.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributed.java
deleted file mode 100644
index e7f6909..0000000
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributed.java
+++ /dev/null
@@ -1,105 +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 org.apache.isis.applib.annotation.Render;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.members.resolve.RenderFacet;
-import org.apache.isis.core.metamodel.facets.members.resolve.RenderFacetAbstract;
-import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacet;
-import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacetAbstract;
-import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacet;
-import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacetAbstract;
-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.ObjectMemberContext;
-
-public class OneToManyAssociationContributed extends OneToManyAssociationImpl implements ContributedMember {
-
-    private final ObjectAdapter serviceAdapter;
-    private final ObjectAction objectAction;
-    
-    private final RenderFacet renderFacet;
-    private final NotPersistedFacet notPersistedFacet;
-    private final TypeOfFacet typeOfFacet; 
-
-    private static ObjectSpecification typeOfSpec(final ObjectActionImpl objectAction, ObjectMemberContext objectMemberContext) {
-        final TypeOfFacet actionTypeOfFacet = objectAction.getFacet(TypeOfFacet.class);
-        return objectMemberContext.getSpecificationLookup().loadSpecification(actionTypeOfFacet.value());
-    }
-    
-    public OneToManyAssociationContributed(ObjectAdapter serviceAdapter, ObjectActionImpl objectAction, ObjectMemberContext objectMemberContext) {
-        super(objectAction.getFacetedMethod(), typeOfSpec(objectAction, objectMemberContext), objectMemberContext);
-        this.serviceAdapter = serviceAdapter;
-        this.objectAction = objectAction;
-        
-        renderFacet = new RenderFacetAbstract(Render.Type.EAGERLY, this) {};
-        notPersistedFacet = new NotPersistedFacetAbstract(this) {};
-        typeOfFacet = new TypeOfFacetAbstract(getSpecification().getCorrespondingClass(), this, objectMemberContext.getSpecificationLookup()) {};
-    }
-
-    
-    @Override
-    public ObjectAdapter get(final ObjectAdapter ownerAdapter) {
-        return objectAction.execute(serviceAdapter, new ObjectAdapter[]{ownerAdapter});
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T extends Facet> T getFacet(Class<T> facetType) {
-        if(facetType == RenderFacet.class) {
-            return (T) renderFacet;
-        }
-        if(facetType == NotPersistedFacet.class) {
-            return (T) notPersistedFacet;
-        }
-        if(facetType == TypeOfFacet.class) {
-            return (T) typeOfFacet;
-        }
-        return super.getFacet(facetType);
-    }
-    
-    @Override
-    public boolean containsFacet(Class<? extends Facet> facetType) {
-        if(facetType == RenderFacet.class) {
-            return true;
-        }
-        if(facetType == NotPersistedFacet.class) {
-            return true;
-        }
-        if(facetType == TypeOfFacet.class) {
-            return true;
-        }
-        return super.containsFacet(facetType);
-    }
-    
-    @Override
-    public boolean containsDoOpFacet(Class<? extends Facet> facetType) {
-        if(facetType == RenderFacet.class) {
-            return true;
-        }
-        if(facetType == NotPersistedFacet.class) {
-            return true;
-        }
-        if(facetType == TypeOfFacet.class) {
-            return true;
-        }
-        return super.containsDoOpFacet(facetType);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/fd132d64/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
new file mode 100644
index 0000000..0c0534c
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/OneToManyAssociationContributee.java
@@ -0,0 +1,105 @@
+/**
+ *  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 org.apache.isis.applib.annotation.Render;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.members.resolve.RenderFacet;
+import org.apache.isis.core.metamodel.facets.members.resolve.RenderFacetAbstract;
+import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacet;
+import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacetAbstract;
+import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacet;
+import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacetAbstract;
+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.ObjectMemberContext;
+
+public class OneToManyAssociationContributee extends OneToManyAssociationImpl implements ContributeeMember {
+
+    private final ObjectAdapter serviceAdapter;
+    private final ObjectAction objectAction;
+    
+    private final RenderFacet renderFacet;
+    private final NotPersistedFacet notPersistedFacet;
+    private final TypeOfFacet typeOfFacet; 
+
+    private static ObjectSpecification typeOfSpec(final ObjectActionImpl objectAction, ObjectMemberContext objectMemberContext) {
+        final TypeOfFacet actionTypeOfFacet = objectAction.getFacet(TypeOfFacet.class);
+        return objectMemberContext.getSpecificationLookup().loadSpecification(actionTypeOfFacet.value());
+    }
+    
+    public OneToManyAssociationContributee(ObjectAdapter serviceAdapter, ObjectActionImpl objectAction, ObjectMemberContext objectMemberContext) {
+        super(objectAction.getFacetedMethod(), typeOfSpec(objectAction, objectMemberContext), objectMemberContext);
+        this.serviceAdapter = serviceAdapter;
+        this.objectAction = objectAction;
+        
+        renderFacet = new RenderFacetAbstract(Render.Type.EAGERLY, this) {};
+        notPersistedFacet = new NotPersistedFacetAbstract(this) {};
+        typeOfFacet = new TypeOfFacetAbstract(getSpecification().getCorrespondingClass(), this, objectMemberContext.getSpecificationLookup()) {};
+    }
+
+    
+    @Override
+    public ObjectAdapter get(final ObjectAdapter ownerAdapter) {
+        return objectAction.execute(serviceAdapter, new ObjectAdapter[]{ownerAdapter});
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Facet> T getFacet(Class<T> facetType) {
+        if(facetType == RenderFacet.class) {
+            return (T) renderFacet;
+        }
+        if(facetType == NotPersistedFacet.class) {
+            return (T) notPersistedFacet;
+        }
+        if(facetType == TypeOfFacet.class) {
+            return (T) typeOfFacet;
+        }
+        return super.getFacet(facetType);
+    }
+    
+    @Override
+    public boolean containsFacet(Class<? extends Facet> facetType) {
+        if(facetType == RenderFacet.class) {
+            return true;
+        }
+        if(facetType == NotPersistedFacet.class) {
+            return true;
+        }
+        if(facetType == TypeOfFacet.class) {
+            return true;
+        }
+        return super.containsFacet(facetType);
+    }
+    
+    @Override
+    public boolean containsDoOpFacet(Class<? extends Facet> facetType) {
+        if(facetType == RenderFacet.class) {
+            return true;
+        }
+        if(facetType == NotPersistedFacet.class) {
+            return true;
+        }
+        if(facetType == TypeOfFacet.class) {
+            return true;
+        }
+        return super.containsDoOpFacet(facetType);
+    }
+
+}