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/01/30 08:14:30 UTC

[1/5] isis git commit: ISIS-928: tiny change to fixture script framework, making ExecutionContext#lookup(...) public and deprecating FixtureScript#lookup(...).

Repository: isis
Updated Branches:
  refs/heads/master ebf5c5c10 -> 63957e2e8


ISIS-928: tiny change to fixture script framework, making ExecutionContext#lookup(...) public and deprecating FixtureScript#lookup(...).


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

Branch: refs/heads/master
Commit: b919f2ad49b93f82563716d3490c9cf697c2e495
Parents: ebf5c5c
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Jan 26 23:01:02 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jan 29 19:00:10 2015 +0000

----------------------------------------------------------------------
 .../org/apache/isis/applib/fixturescripts/FixtureScript.java   | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b919f2ad/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScript.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScript.java b/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScript.java
index 3dd2cdf..74d3733 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScript.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/fixturescripts/FixtureScript.java
@@ -361,7 +361,7 @@ public abstract class FixtureScript
             return object;
         }
 
-        <T> T lookup(final String key, final Class<T> cls) {
+        public <T> T lookup(final String key, final Class<T> cls) {
             return fixtureResultList.lookup(key, cls);
         }
 
@@ -505,6 +505,10 @@ public abstract class FixtureScript
         return executionContext.getResults();
     }
 
+    /**
+     * Use instead {@link org.apache.isis.applib.fixturescripts.FixtureScript.ExecutionContext#lookup(String, Class)} directly.
+     */
+    @Deprecated
     public <T> T lookup(final String key, Class<T> cls) {
         if(executionContext == null) {
             throw new IllegalStateException("This fixture has not yet been run.");


[3/5] isis git commit: ISIS-968: adding unit tests, updates to the todo app.

Posted by da...@apache.org.
ISIS-968: adding unit tests, updates to the todo app.


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

Branch: refs/heads/master
Commit: b72dd11c90b1d98a3723ed0dffbf2eb92f108335
Parents: 2dc30cf
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jan 29 08:53:57 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jan 29 19:00:13 2015 +0000

----------------------------------------------------------------------
 .../isis/applib/annotation/NatureOfService.java |   4 +-
 .../applib/annotation/NotInServiceMenu.java     |   2 +-
 .../core/metamodel/facets/FacetedMethod.java    |  18 +-
 .../NotContributedFacetAbstract.java            |  13 +-
 ...butedFacetDerivedFromDomainServiceFacet.java |   6 +-
 ...cetDerivedFromDomainServiceFacetFactory.java |   2 +-
 .../NotInServiceMenuFacetAbstract.java          |  10 +-
 ...eMenuFacetDerivedFromDomainServiceFacet.java |   6 +-
 ...cetDerivedFromDomainServiceFacetFactory.java |   3 +-
 .../domainservice/DomainServiceFacet.java       |   4 +-
 ...erivedFromDomainServiceFacetFactoryTest.java | 197 +++++++++++++++++++
 ...epositoryMenuAnnotationFacetFactoryTest.java |  67 -------
 ...tInRepositoryMenuMethodFacetFactoryTest.java |  74 -------
 ...InServiceMenuAnnotationFacetFactoryTest.java |  65 ++++++
 ...erivedFromDomainServiceFacetFactoryTest.java | 197 +++++++++++++++++++
 .../NotInServiceMenuMethodFacetFactoryTest.java |  74 +++++++
 .../java/dom/todo/ToDoItemContributions.java    |   2 +-
 .../java/dom/todo/ToDoItemSubscriptions.java    |   2 +-
 18 files changed, 581 insertions(+), 165 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
index f8d71b6..36d271f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
@@ -35,7 +35,7 @@ public enum NatureOfService {
      * Equivalent to annotating all actions with {@link org.apache.isis.applib.annotation.NotContributed}).
      * </p>
      */
-    VIEW_MENU,
+    VIEW_MENU_ONLY,
     /**
      * The service's actions can be contributed to domain objects as actions, properties or collections but do not
      * appear on menus.
@@ -44,7 +44,7 @@ public enum NatureOfService {
      * Equivalent to annotating all actions with {@link org.apache.isis.applib.annotation.NotInServiceMenu).
      * </p>
      */
-    VIEW_CONTRIBUTIONS,
+    VIEW_CONTRIBUTIONS_ONLY,
     /**
      * The service's actions do not appear on menus and are not contributed.
      *

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
index 5f58124..f06c93b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
@@ -36,7 +36,7 @@ import java.lang.annotation.Target;
  * <p>
  * Has no meaning if annotated on an action of a regular entity.
  * 
- * @deprecated - instead move such actions into a separate domain service and specify nature of {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS contributions} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN domain} using {@link DomainService#nature()}.
+ * @deprecated - instead move such actions into a separate domain service and specify nature of {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS_ONLY contributions} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN domain} using {@link DomainService#nature()}.
  */
 @Deprecated
 @Inherited

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
index 494831c..906b732 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
@@ -48,9 +48,7 @@ public class FacetedMethod extends TypedHolderDefault implements IdentifiedHolde
         try {
             final Method method = declaringType.getMethod("get" + StringExtensions.asPascal(propertyName));
             return FacetedMethod.createForProperty(declaringType, method);
-        } catch (final SecurityException e) {
-            throw new RuntimeException(e);
-        } catch (final NoSuchMethodException e) {
+        } catch (final SecurityException | NoSuchMethodException e) {
             throw new RuntimeException(e);
         }
     }
@@ -62,9 +60,19 @@ public class FacetedMethod extends TypedHolderDefault implements IdentifiedHolde
         try {
             final Method method = declaringType.getMethod("get" + StringExtensions.asPascal(collectionName));
             return FacetedMethod.createForCollection(declaringType, method);
-        } catch (final SecurityException e) {
+        } catch (final SecurityException | NoSuchMethodException e) {
             throw new RuntimeException(e);
-        } catch (final NoSuchMethodException e) {
+        }
+    }
+
+    /**
+     * Principally for testing purposes.
+     */
+    public static FacetedMethod createForAction(final Class<?> declaringType, final String actionName, final Class<?>... parameterTypes) {
+        try {
+            final Method method = declaringType.getMethod(actionName, parameterTypes);
+            return FacetedMethod.createForAction(declaringType, method);
+        } catch (final SecurityException | NoSuchMethodException e) {
             throw new RuntimeException(e);
         }
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/NotContributedFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/NotContributedFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/NotContributedFacetAbstract.java
index aff34d4..c98815e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/NotContributedFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/NotContributedFacetAbstract.java
@@ -21,10 +21,10 @@ package org.apache.isis.core.metamodel.facets.actions.notcontributed;
 
 import org.apache.isis.applib.annotation.NotContributed.As;
 import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
 
-public abstract class NotContributedFacetAbstract extends MarkerFacetAbstract implements NotContributedFacet {
+public abstract class NotContributedFacetAbstract extends FacetAbstract implements NotContributedFacet {
 
     private final As as;
 
@@ -32,8 +32,12 @@ public abstract class NotContributedFacetAbstract extends MarkerFacetAbstract im
         return NotContributedFacet.class;
     }
 
-    public NotContributedFacetAbstract(As as, final FacetHolder holder) {
-        super(type(), holder);
+    public NotContributedFacetAbstract(final As as, final FacetHolder holder) {
+        this(as, holder, Derivation.NOT_DERIVED);
+    }
+
+    public NotContributedFacetAbstract(final As as, final FacetHolder holder, final Derivation derivation) {
+        super(type(), holder, derivation);
         this.as = as;
     }
 
@@ -42,7 +46,6 @@ public abstract class NotContributedFacetAbstract extends MarkerFacetAbstract im
         return as;
     }
 
-
     @Override
     public boolean toActions() {
         return value() == As.EITHER || value() == As.ACTION;

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
index 167a99a..3dd7ec4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
@@ -30,7 +30,11 @@ public class NotContributedFacetDerivedFromDomainServiceFacet extends NotContrib
     private final NatureOfService natureOfService;
 
     public NotContributedFacetDerivedFromDomainServiceFacet(final NatureOfService natureOfService, final FacetHolder holder) {
-        super(NotContributed.As.EITHER, holder);
+        super(NotContributed.As.EITHER, holder, Derivation.DERIVED);
         this.natureOfService = natureOfService;
     }
+
+    NatureOfService getNatureOfService() {
+        return natureOfService;
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
index cc346bd..bbdfd1a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
@@ -46,7 +46,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactory extends Fac
         }
 
         final NatureOfService natureOfService = domainServiceFacet.getNatureOfService();
-        if(natureOfService == NatureOfService.VIEW_CONTRIBUTIONS || natureOfService == NatureOfService.VIEW) {
+        if(natureOfService == NatureOfService.VIEW_CONTRIBUTIONS_ONLY || natureOfService == NatureOfService.VIEW) {
             return;
         }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/NotInServiceMenuFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/NotInServiceMenuFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/NotInServiceMenuFacetAbstract.java
index dff465c..d3c8aea 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/NotInServiceMenuFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/NotInServiceMenuFacetAbstract.java
@@ -20,17 +20,21 @@
 package org.apache.isis.core.metamodel.facets.actions.notinservicemenu;
 
 import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
 
-public abstract class NotInServiceMenuFacetAbstract extends MarkerFacetAbstract implements NotInServiceMenuFacet {
+public abstract class NotInServiceMenuFacetAbstract extends FacetAbstract implements NotInServiceMenuFacet {
 
     public static Class<? extends Facet> type() {
         return NotInServiceMenuFacet.class;
     }
 
     public NotInServiceMenuFacetAbstract(final FacetHolder holder) {
-        super(type(), holder);
+        this(holder, Derivation.NOT_DERIVED);
+    }
+
+    public NotInServiceMenuFacetAbstract(final FacetHolder holder, final Derivation derivation) {
+        super(type(), holder, derivation);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
index 10a8413..27ab5ec 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
@@ -32,7 +32,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacet extends NotInSer
 
     public NotInServiceMenuFacetDerivedFromDomainServiceFacet(
             final NatureOfService natureOfService, final FacetHolder holder) {
-        super(holder);
+        super(holder, Derivation.DERIVED);
         this.natureOfService = natureOfService;
     }
 
@@ -40,4 +40,8 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacet extends NotInSer
     public String hides(final VisibilityContext<? extends VisibilityEvent> ic) {
         return String.format("@DomainService(nature=%s) annotation present", natureOfService);
     }
+
+    NatureOfService getNatureOfService() {
+        return natureOfService;
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
index ceddccf..2ffb344 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
@@ -36,6 +36,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory extends F
 
     @Override
     public void process(final ProcessMethodContext processMethodContext) {
+
         final Method method = processMethodContext.getMethod();
         final Class<?> declaringClass = method.getDeclaringClass();
         final ObjectSpecification spec = getSpecificationLoader().loadSpecification(declaringClass);
@@ -46,7 +47,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory extends F
         }
         
         final NatureOfService natureOfService = domainServiceFacet.getNatureOfService();
-        if(natureOfService == NatureOfService.VIEW_MENU || natureOfService == NatureOfService.VIEW) {
+        if(natureOfService == NatureOfService.VIEW_MENU_ONLY || natureOfService == NatureOfService.VIEW) {
             return;
         }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
index e891308..b389767 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
@@ -41,12 +41,12 @@ public interface DomainServiceFacet extends Facet {
      * Corresponds to {@link org.apache.isis.applib.annotation.DomainService#nature()}.
      *
      * <p>
-     *     If set to {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_MENU} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}, then {@link org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet} is
+     *     If set to {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_MENU_ONLY} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}, then {@link org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet} is
      *     derived for all actions.
      * </p>
      *
      * <p>
-     *     If set to {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}, then {@link org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet} is
+     *     If set to {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS_ONLY} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}, then {@link org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet} is
      *     derived for all actions.
      * </p>
      */

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
new file mode 100644
index 0000000..5a05f12
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
@@ -0,0 +1,197 @@
+package org.apache.isis.core.metamodel.facets.actions.notcontributed.derived;
+
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
+import org.apache.isis.core.metamodel.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacetAbstract;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends AbstractFacetFactoryJUnit4TestCase {
+
+    private NotContributedFacetDerivedFromDomainServiceFacetFactory facetFactory;
+
+    @Before
+    public void setUp() throws Exception {
+        facetFactory = new NotContributedFacetDerivedFromDomainServiceFacetFactory();
+        facetFactory.setSpecificationLookup(mockSpecificationLoaderSpi);
+    }
+
+    @Test
+    public void whenMenu() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+        assertThat(facet, is(not(nullValue())));
+        assertThat(facet instanceof NotContributedFacetDerivedFromDomainServiceFacet, is(true));
+        final NotContributedFacetDerivedFromDomainServiceFacet facetDerivedFromDomainServiceFacet = (NotContributedFacetDerivedFromDomainServiceFacet) facet;
+        assertThat(facetDerivedFromDomainServiceFacet.getNatureOfService(), equalTo(NatureOfService.VIEW_MENU_ONLY));
+    }
+
+    @Test
+    public void whenDomain() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.DOMAIN)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+        assertThat(facet, is(not(nullValue())));
+        assertThat(facet instanceof NotContributedFacetDerivedFromDomainServiceFacet, is(true));
+        final NotContributedFacetDerivedFromDomainServiceFacet facetDerivedFromDomainServiceFacet = (NotContributedFacetDerivedFromDomainServiceFacet) facet;
+        assertThat(facetDerivedFromDomainServiceFacet.getNatureOfService(), equalTo(NatureOfService.DOMAIN));
+    }
+
+    @Test
+    public void whenView() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.VIEW)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+        assertThat(facet, is(nullValue()));
+    }
+
+    @Test
+    public void whenContributions() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+        assertThat(facet, is(nullValue()));
+    }
+
+    @Test
+    public void whenNone() throws Exception {
+
+        // given
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(null));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+        assertThat(facet, is(nullValue()));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuAnnotationFacetFactoryTest.java
deleted file mode 100644
index 577efbb..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuAnnotationFacetFactoryTest.java
+++ /dev/null
@@ -1,67 +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.facets.actions.notinrepositorymenu;
-
-import java.lang.reflect.Method;
-
-import org.apache.isis.applib.annotation.NotInServiceMenu;
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
-import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacetAbstract;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.annotation.NotInServiceMenuFacetAnnotationFactory;
-
-public class NotInRepositoryMenuAnnotationFacetFactoryTest extends AbstractFacetFactoryTest {
-
-    private NotInServiceMenuFacetAnnotationFactory facetFactory;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        facetFactory = new NotInServiceMenuFacetAnnotationFactory();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        facetFactory = null;
-        super.tearDown();
-    }
-
-    public void testAnnotationPickedUp() {
-        class CustomerRepository {
-            @SuppressWarnings("unused")
-            @NotInServiceMenu
-            public void someAction() {
-            }
-        }
-        final Method actionMethod = findMethod(CustomerRepository.class, "someAction");
-
-        facetFactory.process(new ProcessMethodContext(CustomerRepository.class, null, null, actionMethod, methodRemover, facetedMethod));
-
-        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof NotInServiceMenuFacetAbstract);
-
-        assertNoMethodsRemoved();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuMethodFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuMethodFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuMethodFacetFactoryTest.java
deleted file mode 100644
index e060f0e..0000000
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinrepositorymenu/NotInRepositoryMenuMethodFacetFactoryTest.java
+++ /dev/null
@@ -1,74 +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.facets.actions.notinrepositorymenu;
-
-import java.lang.reflect.Method;
-
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
-import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacetAbstract;
-import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.method.NotInServiceMenuFacetViaMethodFactory;
-
-public class NotInRepositoryMenuMethodFacetFactoryTest extends AbstractFacetFactoryTest {
-
-    private NotInServiceMenuFacetViaMethodFactory facetFactory;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        facetFactory = new NotInServiceMenuFacetViaMethodFactory();
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        facetFactory = null;
-        super.tearDown();
-    }
-
-    public void testSupportingMethodForActionPickedUp() {
-        // given
-        class CustomerRepository {
-            @SuppressWarnings("unused")
-            public void someAction() {
-            }
-
-            @SuppressWarnings("unused")
-            public boolean notInServiceMenuSomeAction() {
-                return true;
-            }
-        }
-        final Method actionMethod = findMethod(CustomerRepository.class, "someAction");
-
-        // when
-        facetFactory.process(new ProcessMethodContext(CustomerRepository.class, null, null, actionMethod, methodRemover, facetedMethod));
-
-        // then
-        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof NotInServiceMenuFacetAbstract);
-
-        // assertNoMethodsRemoved();
-        assertEquals(1, methodRemover.getRemovedMethodMethodCalls().size());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/annotation/NotInServiceMenuAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/annotation/NotInServiceMenuAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/annotation/NotInServiceMenuAnnotationFacetFactoryTest.java
new file mode 100644
index 0000000..6afa7fb
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/annotation/NotInServiceMenuAnnotationFacetFactoryTest.java
@@ -0,0 +1,65 @@
+/*
+ *  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.facets.actions.notinservicemenu.annotation;
+
+import java.lang.reflect.Method;
+import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
+import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacetAbstract;
+
+public class NotInServiceMenuAnnotationFacetFactoryTest extends AbstractFacetFactoryTest {
+
+    private NotInServiceMenuFacetAnnotationFactory facetFactory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        facetFactory = new NotInServiceMenuFacetAnnotationFactory();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        facetFactory = null;
+        super.tearDown();
+    }
+
+    public void testAnnotationPickedUp() {
+        class CustomerRepository {
+            @SuppressWarnings("unused")
+            @NotInServiceMenu
+            public void someAction() {
+            }
+        }
+        final Method actionMethod = findMethod(CustomerRepository.class, "someAction");
+
+        facetFactory.process(new ProcessMethodContext(CustomerRepository.class, null, null, actionMethod, methodRemover, facetedMethod));
+
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof NotInServiceMenuFacetAbstract);
+
+        assertNoMethodsRemoved();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
new file mode 100644
index 0000000..7d69a76
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
@@ -0,0 +1,197 @@
+package org.apache.isis.core.metamodel.facets.actions.notinservicemenu.derived;
+
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
+import org.apache.isis.core.metamodel.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacetAbstract;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest extends AbstractFacetFactoryJUnit4TestCase {
+
+    private NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory facetFactory;
+
+    @Before
+    public void setUp() throws Exception {
+        facetFactory = new NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory();
+        facetFactory.setSpecificationLookup(mockSpecificationLoaderSpi);
+    }
+
+    @Test
+    public void whenContributions() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertThat(facet, is(not(nullValue())));
+        assertThat(facet instanceof NotInServiceMenuFacetDerivedFromDomainServiceFacet, is(true));
+        final NotInServiceMenuFacetDerivedFromDomainServiceFacet facetDerivedFromDomainServiceFacet = (NotInServiceMenuFacetDerivedFromDomainServiceFacet) facet;
+        assertThat(facetDerivedFromDomainServiceFacet.getNatureOfService(), equalTo(NatureOfService.VIEW_CONTRIBUTIONS_ONLY));
+    }
+
+    @Test
+    public void whenDomain() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.DOMAIN)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertThat(facet, is(not(nullValue())));
+        assertThat(facet instanceof NotInServiceMenuFacetDerivedFromDomainServiceFacet, is(true));
+        final NotInServiceMenuFacetDerivedFromDomainServiceFacet facetDerivedFromDomainServiceFacet = (NotInServiceMenuFacetDerivedFromDomainServiceFacet) facet;
+        assertThat(facetDerivedFromDomainServiceFacet.getNatureOfService(), equalTo(NatureOfService.DOMAIN));
+    }
+
+    @Test
+    public void whenView() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.VIEW)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertThat(facet, is(nullValue()));
+    }
+
+    @Test
+    public void whenMenu() throws Exception {
+
+        // given
+        @DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {}));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertThat(facet, is(nullValue()));
+    }
+
+    @Test
+    public void whenNone() throws Exception {
+
+        // given
+        class Customer {
+
+            public String name() {
+                return "Joe";
+            }
+        }
+
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(null));
+        }});
+
+        expectNoMethodsRemoved();
+
+        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+        // when
+        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertThat(facet, is(nullValue()));
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactoryTest.java
new file mode 100644
index 0000000..a926219
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactoryTest.java
@@ -0,0 +1,74 @@
+/*
+ *  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.facets.actions.notinservicemenu.method;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacetAbstract;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.method.NotInServiceMenuFacetViaMethodFactory;
+
+public class NotInServiceMenuMethodFacetFactoryTest extends AbstractFacetFactoryTest {
+
+    private NotInServiceMenuFacetViaMethodFactory facetFactory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        facetFactory = new NotInServiceMenuFacetViaMethodFactory();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        facetFactory = null;
+        super.tearDown();
+    }
+
+    public void testSupportingMethodForActionPickedUp() {
+        // given
+        class CustomerRepository {
+            @SuppressWarnings("unused")
+            public void someAction() {
+            }
+
+            @SuppressWarnings("unused")
+            public boolean notInServiceMenuSomeAction() {
+                return true;
+            }
+        }
+        final Method actionMethod = findMethod(CustomerRepository.class, "someAction");
+
+        // when
+        facetFactory.process(new ProcessMethodContext(CustomerRepository.class, null, null, actionMethod, methodRemover, facetedMethod));
+
+        // then
+        final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof NotInServiceMenuFacetAbstract);
+
+        // assertNoMethodsRemoved();
+        assertEquals(1, methodRemover.getRemovedMethodMethodCalls().size());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
index 65a7219..655ad30 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
@@ -45,7 +45,7 @@ import org.apache.isis.applib.query.QueryDefault;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.value.Clob;
 
-@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS)
+@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
 public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     //region > priority (contributed property)

http://git-wip-us.apache.org/repos/asf/isis/blob/b72dd11c/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
index de9afc5..7359856 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
@@ -58,7 +58,7 @@ import static com.google.common.collect.Lists.newArrayList;
  *     vetoing the change).
  * </p>
  */
-@DomainService(nature = NatureOfService.VIEW_MENU)
+@DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
 @DomainServiceLayout(menuBar = DomainServiceLayout.MenuBar.SECONDARY, menuOrder = "30")
 public class ToDoItemSubscriptions {
 


[2/5] isis git commit: ISIS-968: extending @DomainService(nature=...).

Posted by da...@apache.org.
ISIS-968: extending @DomainService(nature=...).

Also deprecating @NotInServiceMenu.


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

Branch: refs/heads/master
Commit: 2dc30cfa4c4114e005e89f77d1873bf41edf1ade
Parents: b919f2a
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Jan 28 17:45:33 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jan 29 19:00:11 2015 +0000

----------------------------------------------------------------------
 .../isis/applib/annotation/DomainService.java   |  5 ++
 .../isis/applib/annotation/NatureOfService.java | 57 ++++++++++++++++++++
 .../applib/annotation/NotInServiceMenu.java     |  6 ++-
 ...butedFacetDerivedFromDomainServiceFacet.java | 36 +++++++++++++
 ...cetDerivedFromDomainServiceFacetFactory.java | 57 ++++++++++++++++++++
 ...eMenuFacetDerivedFromDomainServiceFacet.java | 43 +++++++++++++++
 ...cetDerivedFromDomainServiceFacetFactory.java | 57 ++++++++++++++++++++
 .../domainservice/DomainServiceFacet.java       | 21 +++++++-
 .../DomainServiceFacetAbstract.java             | 13 ++++-
 .../DomainServiceFacetAnnotation.java           |  6 ++-
 .../DomainServiceFacetAnnotationFactory.java    |  2 +-
 .../dflt/ProgrammingModelFacetsJava5.java       |  6 +++
 .../src/main/java/dom/simple/SimpleObject.java  |  1 -
 .../main/java/app/ToDoAppDashboardService.java  |  3 +-
 .../java/dom/todo/ToDoItemContributions.java    | 13 ++---
 .../java/dom/todo/ToDoItemSubscriptions.java    |  7 ++-
 16 files changed, 308 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
index 8f4321b..1c2c1ea 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainService.java
@@ -39,6 +39,11 @@ public @interface DomainService {
     Class<?> repositoryFor() default Object.class;
 
     /**
+     * The nature of this service, eg for menus, contributed actions, repository.
+     */
+    NatureOfService nature() default NatureOfService.VIEW;
+
+    /**
      * Number in Dewey Decimal format representing the order.
      *
      * <p>

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
new file mode 100644
index 0000000..f8d71b6
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NatureOfService.java
@@ -0,0 +1,57 @@
+/*
+ *  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.applib.annotation;
+
+/**
+ * The different sorts of domain services recognized by Isis, as specified in {@link DomainService#nature()}
+ */
+public enum NatureOfService {
+
+    /**
+     * The default; the service's actions appear on menus and can be contributed to domain objects as actions,
+     * properties or collections.
+     */
+    VIEW,
+    /**
+     * The service's actions appear on menus but do not contribute.
+     *
+     * <p>
+     * Equivalent to annotating all actions with {@link org.apache.isis.applib.annotation.NotContributed}).
+     * </p>
+     */
+    VIEW_MENU,
+    /**
+     * The service's actions can be contributed to domain objects as actions, properties or collections but do not
+     * appear on menus.
+     *
+     * <p>
+     * Equivalent to annotating all actions with {@link org.apache.isis.applib.annotation.NotInServiceMenu).
+     * </p>
+     */
+    VIEW_CONTRIBUTIONS,
+    /**
+     * The service's actions do not appear on menus and are not contributed.
+     *
+     * <p>
+     * Equivalent to annotating all actions with both {@link org.apache.isis.applib.annotation.NotInServiceMenu} and {@link org.apache.isis.applib.annotation.NotContributed}).
+     * </p>
+     */
+    DOMAIN
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
index 9797fd1..5f58124 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
@@ -26,8 +26,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * Indicates the (service) action should be not be displayed in the service
- * menu.
+ * Indicates the (service) action should be not be displayed in the menu.
  * 
  * <p>
  * It may still be contributed (unless it has been annotated as
@@ -36,7 +35,10 @@ import java.lang.annotation.Target;
  * 
  * <p>
  * Has no meaning if annotated on an action of a regular entity.
+ * 
+ * @deprecated - instead move such actions into a separate domain service and specify nature of {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS contributions} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN domain} using {@link DomainService#nature()}.
  */
+@Deprecated
 @Inherited
 @Target({ ElementType.METHOD })
 @Retention(RetentionPolicy.RUNTIME)

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
new file mode 100644
index 0000000..167a99a
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacet.java
@@ -0,0 +1,36 @@
+/*
+ *  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.facets.actions.notcontributed.derived;
+
+
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacetAbstract;
+
+
+public class NotContributedFacetDerivedFromDomainServiceFacet extends NotContributedFacetAbstract {
+
+    private final NatureOfService natureOfService;
+
+    public NotContributedFacetDerivedFromDomainServiceFacet(final NatureOfService natureOfService, final FacetHolder holder) {
+        super(NotContributed.As.EITHER, holder);
+        this.natureOfService = natureOfService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
new file mode 100644
index 0000000..cc346bd
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactory.java
@@ -0,0 +1,57 @@
+/*
+ *  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.facets.actions.notcontributed.derived;
+
+import java.lang.reflect.Method;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class NotContributedFacetDerivedFromDomainServiceFacetFactory extends FacetFactoryAbstract {
+
+    public NotContributedFacetDerivedFromDomainServiceFacetFactory() {
+        super(FeatureType.ACTIONS_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+        final Class<?> declaringClass = method.getDeclaringClass();
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(declaringClass);
+
+        final DomainServiceFacet domainServiceFacet = spec.getFacet(DomainServiceFacet.class);
+        if(domainServiceFacet == null || domainServiceFacet.isNoop()) {
+            return;
+        }
+
+        final NatureOfService natureOfService = domainServiceFacet.getNatureOfService();
+        if(natureOfService == NatureOfService.VIEW_CONTRIBUTIONS || natureOfService == NatureOfService.VIEW) {
+            return;
+        }
+
+        final FacetedMethod facetHolder = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new NotContributedFacetDerivedFromDomainServiceFacet(natureOfService, facetHolder));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
new file mode 100644
index 0000000..10a8413
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacet.java
@@ -0,0 +1,43 @@
+/*
+ *  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.facets.actions.notinservicemenu.derived;
+
+
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.events.VisibilityEvent;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacetAbstract;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
+
+
+public class NotInServiceMenuFacetDerivedFromDomainServiceFacet extends NotInServiceMenuFacetAbstract {
+
+    private final NatureOfService natureOfService;
+
+    public NotInServiceMenuFacetDerivedFromDomainServiceFacet(
+            final NatureOfService natureOfService, final FacetHolder holder) {
+        super(holder);
+        this.natureOfService = natureOfService;
+    }
+
+    @Override
+    public String hides(final VisibilityContext<? extends VisibilityEvent> ic) {
+        return String.format("@DomainService(nature=%s) annotation present", natureOfService);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
new file mode 100644
index 0000000..ceddccf
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.java
@@ -0,0 +1,57 @@
+/*
+ *  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.facets.actions.notinservicemenu.derived;
+
+import java.lang.reflect.Method;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory extends FacetFactoryAbstract {
+
+    public NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory() {
+        super(FeatureType.ACTIONS_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+        final Class<?> declaringClass = method.getDeclaringClass();
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(declaringClass);
+
+        final DomainServiceFacet domainServiceFacet = spec.getFacet(DomainServiceFacet.class);
+        if(domainServiceFacet == null || domainServiceFacet.isNoop()) {
+            return;
+        }
+        
+        final NatureOfService natureOfService = domainServiceFacet.getNatureOfService();
+        if(natureOfService == NatureOfService.VIEW_MENU || natureOfService == NatureOfService.VIEW) {
+            return;
+        }
+
+        final FacetedMethod facetHolder = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new NotInServiceMenuFacetDerivedFromDomainServiceFacet(natureOfService, facetHolder));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
index 1d9258e..e891308 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacet.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.domainservice;
 
 
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 
 
@@ -29,10 +30,26 @@ public interface DomainServiceFacet extends Facet {
 
     /**
      * Corresponds to {@link org.apache.isis.applib.annotation.DomainService#repositoryFor()}.
-     *
+     * <p/>
      * <p>
      * May be null.
      * </p>
      */
     public Class<?> getRepositoryFor();
-}
+
+    /**
+     * Corresponds to {@link org.apache.isis.applib.annotation.DomainService#nature()}.
+     *
+     * <p>
+     *     If set to {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_MENU} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}, then {@link org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet} is
+     *     derived for all actions.
+     * </p>
+     *
+     * <p>
+     *     If set to {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}, then {@link org.apache.isis.core.metamodel.facets.actions.notinservicemenu.NotInServiceMenuFacet} is
+     *     derived for all actions.
+     * </p>
+     */
+    public NatureOfService getNatureOfService();
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
index fb63eb2..8195140 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/DomainServiceFacetAbstract.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.domainservice;
 
 
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -33,14 +34,22 @@ public abstract class DomainServiceFacetAbstract
     }
 
     private final Class<?> repositoryFor;
+    private final NatureOfService natureOfService;
 
-    public DomainServiceFacetAbstract(final FacetHolder facetHolder, final Class<?> repositoryFor) {
+    public DomainServiceFacetAbstract(
+            final FacetHolder facetHolder,
+            final Class<?> repositoryFor,
+            final NatureOfService natureOfService) {
         super(DomainServiceFacetAbstract.type(), facetHolder, Derivation.NOT_DERIVED);
         this.repositoryFor = repositoryFor;
+        this.natureOfService = natureOfService;
     }
 
-
     public Class<?> getRepositoryFor() {
         return repositoryFor;
     }
+
+    public NatureOfService getNatureOfService() {
+        return natureOfService;
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
index 7c391ef..55aed4b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotation.java
@@ -19,6 +19,7 @@
 package org.apache.isis.core.metamodel.facets.object.domainservice.annotation;
 
 
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacetAbstract;
 
@@ -27,7 +28,8 @@ public class DomainServiceFacetAnnotation extends DomainServiceFacetAbstract {
 
     public DomainServiceFacetAnnotation(
             final FacetHolder facetHolder,
-            final Class<?> repositoryFor) {
-        super(facetHolder, repositoryFor);
+            final Class<?> repositoryFor,
+            final NatureOfService natureOfService) {
+        super(facetHolder, repositoryFor, natureOfService);
     }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
index c81cf37..675b1bd 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainservice/annotation/DomainServiceFacetAnnotationFactory.java
@@ -42,7 +42,7 @@ public class DomainServiceFacetAnnotationFactory extends FacetFactoryAbstract {
         FacetUtil.addFacet(
                 new DomainServiceFacetAnnotation(
                         processClassContext.getFacetHolder(),
-                        annotation.repositoryFor()));
+                        annotation.repositoryFor(), annotation.nature()));
         if(annotation.repositoryFor() != null) {
             FacetUtil.addFacet(
                     new IconFacetDerivedFromDomainServiceAnnotation(

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 9970867..4f9643e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -27,7 +27,9 @@ import org.apache.isis.core.metamodel.facets.actions.homepage.annotation.HomePag
 import org.apache.isis.core.metamodel.facets.actions.interaction.ActionNamedDebugExplorationFacetFactory;
 import org.apache.isis.core.metamodel.facets.actions.layout.ActionLayoutFacetFactory;
 import org.apache.isis.core.metamodel.facets.actions.notcontributed.annotation.NotContributedFacetAnnotationFactory;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.derived.NotContributedFacetDerivedFromDomainServiceFacetFactory;
 import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.annotation.NotInServiceMenuFacetAnnotationFactory;
+import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.derived.NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory;
 import org.apache.isis.core.metamodel.facets.actions.notinservicemenu.method.NotInServiceMenuFacetViaMethodFactory;
 import org.apache.isis.core.metamodel.facets.actions.paged.annotation.PagedFacetOnActionFactory;
 import org.apache.isis.core.metamodel.facets.actions.prototype.annotation.PrototypeFacetAnnotationFactory;
@@ -354,6 +356,10 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(NotInServiceMenuFacetAnnotationFactory.class);
         addFactory(NotInServiceMenuFacetViaMethodFactory.class);
 
+        addFactory(NotContributedFacetDerivedFromDomainServiceFacetFactory.class);
+        addFactory(NotInServiceMenuFacetDerivedFromDomainServiceFacetFactory.class);
+
+
         addFactory(HiddenFacetOnTypeAnnotationFactory.class);
         // must come after the TitleAnnotationFacetFactory, because can act as an override
         addFactory(HiddenFacetOnMemberFactory.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/example/application/simpleapp/dom/src/main/java/dom/simple/SimpleObject.java
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/dom/src/main/java/dom/simple/SimpleObject.java b/example/application/simpleapp/dom/src/main/java/dom/simple/SimpleObject.java
index f93aacf..b0cbb46 100644
--- a/example/application/simpleapp/dom/src/main/java/dom/simple/SimpleObject.java
+++ b/example/application/simpleapp/dom/src/main/java/dom/simple/SimpleObject.java
@@ -24,7 +24,6 @@ import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.BookmarkPolicy;
 import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainObjectLayout;
-import org.apache.isis.applib.annotation.MemberOrder;
 import org.apache.isis.applib.annotation.Title;
 import org.apache.isis.applib.util.ObjectContracts;
 

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java b/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java
index 7fc67af..c60f255 100644
--- a/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java
+++ b/example/application/todoapp/dom/src/main/java/app/ToDoAppDashboardService.java
@@ -19,9 +19,10 @@
 package app;
 
 import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.services.homepage.AbstractHomePageDashboardService;
 
-@DomainService
+@DomainService(nature = NatureOfService.DOMAIN)
 public class ToDoAppDashboardService extends AbstractHomePageDashboardService<ToDoAppDashboard> {
 
     public ToDoAppDashboardService() {

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
index 3a9b6a9..65a7219 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
@@ -32,12 +32,11 @@ import org.joda.time.LocalDate;
 import org.apache.isis.applib.AbstractFactoryAndRepository;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
-import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.NotContributed;
 import org.apache.isis.applib.annotation.NotContributed.As;
-import org.apache.isis.applib.annotation.NotInServiceMenu;
 import org.apache.isis.applib.annotation.Optional;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.SemanticsOf;
@@ -46,11 +45,10 @@ import org.apache.isis.applib.query.QueryDefault;
 import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 import org.apache.isis.applib.value.Clob;
 
-@DomainService
+@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS)
 public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     //region > priority (contributed property)
-    @NotInServiceMenu
     @NotContributed(As.ACTION) // ie contributed as association
     @Action(
             semantics = SemanticsOf.SAFE,
@@ -106,7 +104,6 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     //endregion
 
     //region >  next, previous (contributed actions)
-    @NotInServiceMenu
     @NotContributed(As.ASSOCIATION) // ie contributed as action
     @Action(semantics = SemanticsOf.SAFE)
     @ActionLayout(
@@ -132,7 +129,6 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     // //////////////////////////////////////
 
-    @NotInServiceMenu
     @NotContributed(As.ASSOCIATION) // ie contributed as action
     @ActionLayout(
             describedAs = "The previous item not yet completed"
@@ -174,7 +170,6 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     //endregion
 
     //region > similarTo (contributed collection)
-    @NotInServiceMenu
     @NotContributed(As.ACTION)
     @Action(semantics = SemanticsOf.SAFE)
     public List<ToDoItem> similarTo(final ToDoItem toDoItem) {
@@ -199,7 +194,6 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     //region > updateCategory (contributed action)
 
-    @NotInServiceMenu
     @ActionLayout(
             describedAs = "Update category and subcategory"
     )
@@ -236,8 +230,7 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     /**
      * Demonstrates functionality of streaming back Clob/Blob result within an action with a prompt, i.e. Ajax request
      */
-    @ActionSemantics(ActionSemantics.Of.SAFE)
-    @NotInServiceMenu
+    @Action(semantics = SemanticsOf.SAFE)
     public Clob exportAsJson(
             final ToDoItem toDoItem,
             @ParameterLayout(named = "File name") String fileName

http://git-wip-us.apache.org/repos/asf/isis/blob/2dc30cfa/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
index 600d9c0..de9afc5 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemSubscriptions.java
@@ -33,11 +33,11 @@ import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.DomainServiceLayout;
-import org.apache.isis.applib.annotation.RestrictTo;
 import org.apache.isis.applib.annotation.MemberOrder;
-import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.annotation.RestrictTo;
 import org.apache.isis.applib.annotation.SemanticsOf;
 import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
 import org.apache.isis.applib.services.eventbus.CollectionDomainEvent;
@@ -58,7 +58,7 @@ import static com.google.common.collect.Lists.newArrayList;
  *     vetoing the change).
  * </p>
  */
-@DomainService
+@DomainService(nature = NatureOfService.VIEW_MENU)
 @DomainServiceLayout(menuBar = DomainServiceLayout.MenuBar.SECONDARY, menuOrder = "30")
 public class ToDoItemSubscriptions {
 
@@ -129,7 +129,6 @@ public class ToDoItemSubscriptions {
      * To demo/test what occurs if a subscriber that might veto an event.
      */
     @MemberOrder(name = "Prototyping", sequence = "80")
-    @NotContributed
     @ActionLayout(
         named="Set subscriber behaviour"
     )


[5/5] isis git commit: Merge branch 'ISIS-968'

Posted by da...@apache.org.
Merge branch 'ISIS-968'


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

Branch: refs/heads/master
Commit: 63957e2e8556871c15bd011371f4de4c3d4d745c
Parents: ebf5c5c f3294b6
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jan 29 19:16:16 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jan 29 19:16:16 2015 +0000

----------------------------------------------------------------------
 .../isis/applib/annotation/ActionLayout.java    |  13 +
 .../isis/applib/annotation/Contributed.java     |  46 +++
 .../isis/applib/annotation/DomainService.java   |   5 +
 .../isis/applib/annotation/NatureOfService.java |  57 +++
 .../isis/applib/annotation/NotContributed.java  |  48 ++-
 .../applib/annotation/NotInServiceMenu.java     |   6 +-
 .../applib/fixturescripts/FixtureScript.java    |   6 +-
 .../core/metamodel/facets/FacetedMethod.java    |  18 +-
 .../layout/ActionLayoutFacetFactory.java        |  31 ++
 .../NamedFacetForActionLayoutAnnotation.java    |   2 +-
 ...ntributedFacetForActionLayoutAnnotation.java |  49 +++
 .../NotContributedFacetForLayoutProperties.java |  60 +++
 .../NotContributedFacetAbstract.java            |  13 +-
 ...butedFacetDerivedFromDomainServiceFacet.java |  40 ++
 ...cetDerivedFromDomainServiceFacetFactory.java |  57 +++
 .../NotInServiceMenuFacetAbstract.java          |  10 +-
 ...eMenuFacetDerivedFromDomainServiceFacet.java |  47 +++
 ...cetDerivedFromDomainServiceFacetFactory.java |  58 +++
 .../domainservice/DomainServiceFacet.java       |  21 +-
 .../DomainServiceFacetAbstract.java             |  13 +-
 .../DomainServiceFacetAnnotation.java           |   6 +-
 .../DomainServiceFacetAnnotationFactory.java    |   2 +-
 .../layoutmetadata/ActionLayoutFacetRepr.java   |   2 +
 .../dflt/ProgrammingModelFacetsJava5.java       |   6 +
 ...nLayoutAnnotationFacetFactoryJunit4Test.java | 380 +++++++++++++++++++
 .../ActionLayoutAnnotationFacetFactoryTest.java | 139 ++++---
 ...erivedFromDomainServiceFacetFactoryTest.java | 201 ++++++++++
 ...epositoryMenuAnnotationFacetFactoryTest.java |  67 ----
 ...tInRepositoryMenuMethodFacetFactoryTest.java |  74 ----
 ...InServiceMenuAnnotationFacetFactoryTest.java |  65 ++++
 ...erivedFromDomainServiceFacetFactoryTest.java | 201 ++++++++++
 .../NotInServiceMenuMethodFacetFactoryTest.java |  74 ++++
 .../src/main/java/dom/simple/SimpleObject.java  |   1 -
 .../main/java/app/ToDoAppDashboardService.java  |   3 +-
 .../java/app/ToDoItemAnalysisContributions.java |  12 +-
 .../java/dom/todo/ToDoItemContributions.java    |  32 +-
 .../java/dom/todo/ToDoItemSubscriptions.java    |   7 +-
 37 files changed, 1622 insertions(+), 250 deletions(-)
----------------------------------------------------------------------



[4/5] isis git commit: ISIS-968: @ActionLayout(contributed=...) support.

Posted by da...@apache.org.
ISIS-968: @ActionLayout(contributed=...) support.


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

Branch: refs/heads/master
Commit: f3294b65d843742f7fa529bc05128f098582872e
Parents: b72dd11
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jan 29 15:30:20 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jan 29 19:00:14 2015 +0000

----------------------------------------------------------------------
 .../isis/applib/annotation/ActionLayout.java    |  13 +
 .../isis/applib/annotation/Contributed.java     |  46 +++
 .../isis/applib/annotation/NotContributed.java  |  48 ++-
 .../layout/ActionLayoutFacetFactory.java        |  31 ++
 .../NamedFacetForActionLayoutAnnotation.java    |   2 +-
 ...ntributedFacetForActionLayoutAnnotation.java |  49 +++
 .../NotContributedFacetForLayoutProperties.java |  60 +++
 .../layoutmetadata/ActionLayoutFacetRepr.java   |   2 +
 ...nLayoutAnnotationFacetFactoryJunit4Test.java | 380 +++++++++++++++++++
 .../ActionLayoutAnnotationFacetFactoryTest.java | 139 ++++---
 ...erivedFromDomainServiceFacetFactoryTest.java |  52 +--
 ...erivedFromDomainServiceFacetFactoryTest.java |  52 +--
 .../java/app/ToDoItemAnalysisContributions.java |  12 +-
 .../java/dom/todo/ToDoItemContributions.java    |  19 +-
 14 files changed, 787 insertions(+), 118 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
index a692d71..52a652f 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/ActionLayout.java
@@ -116,6 +116,19 @@ public @interface ActionLayout {
         PANEL_DROPDOWN
     }
 
+    // //////////////////////////////////////
+
+    /**
+     * For actions of domain services that can be viewed and contributed (that is, whose
+     * {@link DomainService#nature() nature} is either {@link org.apache.isis.applib.annotation.NatureOfService#VIEW}
+     * or {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS_ONLY}), specifies how the
+     * contribution should be implemented, as an action, as an association, or as both.
+     *
+     * <p>
+     *     Has no meaning for actions of domain entities.
+     * </p>
+     */
+    Contributed contributed() default Contributed.AS_BOTH;
 
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/applib/src/main/java/org/apache/isis/applib/annotation/Contributed.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Contributed.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Contributed.java
new file mode 100644
index 0000000..88c46ea
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Contributed.java
@@ -0,0 +1,46 @@
+/*
+ *  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.applib.annotation;
+
+/**
+ * The means by which a domain service action will be contributed to a domain object.
+ */
+public enum Contributed {
+    /**
+     * Default: contributed as both an action and also (if takes a single argument and has safe semantics) as an association
+     * (contributed property if returns a single value, contributed collection if returns a collection).
+     */
+    AS_BOTH,
+    /**
+     * Contributed as an action but <i>not</i> as an association.
+     */
+    AS_ACTION,
+    /**
+     * (If takes a single argument and has safe semantics) then is contributed as an association
+     * (contributed property if returns a single value, contributed collection if returns a collection) but <i>not</i>
+     * as an action.
+     */
+    AS_ASSOCIATION,
+    /**
+     * The action is not contributed as either an action or as an association.
+     */
+    AS_NEITHER;
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/applib/src/main/java/org/apache/isis/applib/annotation/NotContributed.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotContributed.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotContributed.java
index 067e9e0..5e37325 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotContributed.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotContributed.java
@@ -28,27 +28,57 @@ import java.lang.annotation.Target;
 /**
  * Indicates the a (repository) action should not be contributed, either as
  * an object action, or as an association (property/collection), or as either.
- * 
- * <p>
+ * <p/>
+ * <p/>
  * It may still be appear in the repository menu (unless it has been annotated
  * as {@link NotInServiceMenu}).
- * 
- * <p>
+ * <p/>
+ * <p/>
  * If annotated with {@link Hidden}, then also implies that the
  * menu should not be contributed.
- * 
- * <p>
+ * <p/>
+ * <p/>
  * Has no meaning for actions on regular entities.
+ *
+ * @deprecated - to not contribute at all, move action to a service whose {@link org.apache.isis.applib.annotation.DomainService#nature() nature} is {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_MENU_ONLY} or {@link org.apache.isis.applib.annotation.NatureOfService#DOMAIN}; to contribute only as an action or as an association, ensure action is in a service whose nature is {@link org.apache.isis.applib.annotation.NatureOfService#VIEW} or {@link org.apache.isis.applib.annotation.NatureOfService#VIEW_CONTRIBUTIONS_ONLY}, and use {@link ActionLayout#contributed()} to specify whether the contribution should be  {@link Contributed#AS_ACTION as action} or {@link Contributed#AS_ASSOCIATION as association}.
  */
+@Deprecated
 @Inherited
-@Target({ ElementType.METHOD })
+@Target({ElementType.METHOD})
 @Retention(RetentionPolicy.RUNTIME)
 public @interface NotContributed {
+
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public enum As {
         ACTION,
         ASSOCIATION,
         EITHER;
+
+        /**
+         * @deprecated
+         */
+        @Deprecated
+        public static As from(final Contributed contributed) {
+            if(contributed == null) { return null; }
+            switch (contributed) {
+                case AS_ACTION: return As.ASSOCIATION;
+                case AS_ASSOCIATION: return As.ACTION;
+                case AS_NEITHER: return As.EITHER;
+                case AS_BOTH: return null;
+            }
+            return null;
+        }
+
     }
-    
-    As value() default As.EITHER; 
+
+    /**
+     * @deprecated
+     * @return
+     */
+    @Deprecated
+    As value() default As.EITHER;
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
index 23a653c..9068ab9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutFacetFactory.java
@@ -19,14 +19,17 @@
 package org.apache.isis.core.metamodel.facets.actions.layout;
 
 
+import java.lang.reflect.Method;
 import java.util.Properties;
 import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facets.Annotations;
 import org.apache.isis.core.metamodel.facets.ContributeeMemberFacetFactory;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet;
 import org.apache.isis.core.metamodel.facets.actions.position.ActionPositionFacet;
 import org.apache.isis.core.metamodel.facets.actions.position.ActionPositionFacetFallback;
 import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
@@ -35,6 +38,8 @@ import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.members.cssclass.CssClassFacet;
 import org.apache.isis.core.metamodel.facets.members.cssclassfa.CssClassFaFacet;
 import org.apache.isis.core.metamodel.facets.object.bookmarkpolicy.BookmarkPolicyFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
 
 public class ActionLayoutFacetFactory extends FacetFactoryAbstract implements ContributeeMemberFacetFactory {
@@ -114,6 +119,32 @@ public class ActionLayoutFacetFactory extends FacetFactoryAbstract implements Co
         }
         FacetUtil.addFacet(actionPositionFacet);
 
+
+        // contributing
+
+        if (isContributingService(processMethodContext)) {
+            NotContributedFacet notContributedFacet = NotContributedFacetForLayoutProperties.create(properties, holder);
+            if(notContributedFacet == null) {
+                notContributedFacet = NotContributedFacetForActionLayoutAnnotation.create(actionLayout, holder);
+            }
+            FacetUtil.addFacet(notContributedFacet);
+        }
+    }
+
+    protected boolean isContributingService(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+        final Class<?> declaringClass = method.getDeclaringClass();
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(declaringClass);
+
+        final DomainServiceFacet domainServiceFacet = spec.getFacet(DomainServiceFacet.class);
+        return domainServiceFacet != null && !domainServiceFacet.isNoop() &&
+                domainServiceFacet.getNatureOfService() != NatureOfService.VIEW_MENU_ONLY &&
+                domainServiceFacet.getNatureOfService() != NatureOfService.DOMAIN;
+    }
+
+
+    protected boolean skipContributing(final DomainServiceFacet domainServiceFacet) {
+        return domainServiceFacet == null || domainServiceFacet.isNoop() || domainServiceFacet.getNatureOfService() == NatureOfService.VIEW_MENU_ONLY || domainServiceFacet.getNatureOfService() == NatureOfService.DOMAIN;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionLayoutAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionLayoutAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionLayoutAnnotation.java
index 3bf2cab..6a36efb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionLayoutAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NamedFacetForActionLayoutAnnotation.java
@@ -27,7 +27,7 @@ import org.apache.isis.core.metamodel.facets.all.named.NamedFacetAbstract;
 
 public class NamedFacetForActionLayoutAnnotation extends NamedFacetAbstract {
 
-    public static NamedFacet create(ActionLayout actionLayout, FacetHolder holder) {
+    public static NamedFacet create(final ActionLayout actionLayout, final FacetHolder holder) {
         if(actionLayout == null) {
             return null;
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForActionLayoutAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForActionLayoutAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForActionLayoutAnnotation.java
new file mode 100644
index 0000000..7273c48
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForActionLayoutAnnotation.java
@@ -0,0 +1,49 @@
+/*
+ *  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.facets.actions.layout;
+
+
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.Contributed;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacetAbstract;
+
+
+public class NotContributedFacetForActionLayoutAnnotation extends NotContributedFacetAbstract {
+
+    public static NotContributedFacet create(
+            final ActionLayout actionLayout, final FacetHolder holder) {
+        if(actionLayout == null) {
+            return null;
+        }
+        final Contributed contributed = actionLayout.contributed();
+        final NotContributed.As as = NotContributed.As.from(contributed);
+        if(as == null) {
+            return null;
+        }
+        return new NotContributedFacetForActionLayoutAnnotation(as, holder);
+    }
+
+    private NotContributedFacetForActionLayoutAnnotation(final NotContributed.As as, final FacetHolder holder) {
+        super(as, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForLayoutProperties.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForLayoutProperties.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForLayoutProperties.java
new file mode 100644
index 0000000..b2029f2
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/layout/NotContributedFacetForLayoutProperties.java
@@ -0,0 +1,60 @@
+/*
+ *  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.facets.actions.layout;
+
+
+import java.util.Properties;
+import com.google.common.base.Strings;
+import org.apache.isis.applib.annotation.Contributed;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacetAbstract;
+
+
+public class NotContributedFacetForLayoutProperties extends NotContributedFacetAbstract {
+
+    public static NotContributedFacet create(final Properties properties, final FacetHolder holder) {
+        final Contributed contributed = contributing(properties);
+        if(contributed == null) {
+            return null;
+        }
+        return contributed != null? new NotContributedFacetForLayoutProperties(NotContributed.As.from(contributed), holder): null;
+    }
+
+    private NotContributedFacetForLayoutProperties(
+            final NotContributed.As as,
+            final FacetHolder holder) {
+        super(as, holder);
+    }
+
+
+    private static Contributed contributing(final Properties properties) {
+        if(properties == null) {
+            return null;
+        }
+        String contributing = Strings.emptyToNull(properties.getProperty("contributing"));
+        if(contributing == null) {
+            // alternate key
+            contributing = Strings.emptyToNull(properties.getProperty("contributed"));
+        }
+        return contributing != null? Contributed.valueOf(contributing): null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionLayoutFacetRepr.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionLayoutFacetRepr.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionLayoutFacetRepr.java
index 37ba265..e8612f8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionLayoutFacetRepr.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/layoutmetadata/ActionLayoutFacetRepr.java
@@ -19,6 +19,7 @@ package org.apache.isis.core.metamodel.layoutmetadata;
 
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.applib.annotation.BookmarkPolicy;
+import org.apache.isis.applib.annotation.Contributed;
 import org.apache.isis.applib.annotation.Where;
 
 public class ActionLayoutFacetRepr {
@@ -31,4 +32,5 @@ public class ActionLayoutFacetRepr {
     public String named;
     public boolean namedEscaped = true;
     public ActionLayout.Position position;
+    public Contributed contributed;
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryJunit4Test.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryJunit4Test.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryJunit4Test.java
new file mode 100644
index 0000000..54909d3
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryJunit4Test.java
@@ -0,0 +1,380 @@
+/*
+ *  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.facets.actions.layout;
+
+import org.hamcrest.CoreMatchers;
+import org.jmock.Expectations;
+import org.junit.Before;
+import org.junit.Test;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.Contributed;
+import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.NatureOfService;
+import org.apache.isis.applib.annotation.NotContributed;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
+import org.apache.isis.core.metamodel.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.actions.notcontributed.NotContributedFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacetAbstract;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class ActionLayoutAnnotationFacetFactoryJunit4Test extends AbstractFacetFactoryJUnit4TestCase {
+
+    ActionLayoutFacetFactory facetFactory;
+
+    @Before
+    public void setUp() throws Exception {
+        facetFactory = new ActionLayoutFacetFactory();
+        facetFactory.setSpecificationLookup(mockSpecificationLoaderSpi);
+    }
+
+    public static class Contributing extends ActionLayoutAnnotationFacetFactoryJunit4Test {
+
+        @Test
+        public void onDomainServiceForViewWithDefault() {
+
+            // given
+            @DomainService(nature = NatureOfService.VIEW)
+            class CustomerService {
+
+                @ActionLayout()
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(nullValue()));
+
+        }
+
+        @Test
+        public void onDomainServiceForViewWithBoth() {
+            // given
+            @DomainService(nature = NatureOfService.VIEW)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_BOTH)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(nullValue()));
+
+        }
+
+        @Test
+        public void testOnDomainServiceForViewWithAssociation() {
+
+            // given
+            @DomainService(nature = NatureOfService.VIEW)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_ASSOCIATION)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(not(nullValue())));
+            assertThat(facet instanceof NotContributedFacetForActionLayoutAnnotation, CoreMatchers.is(true));
+            final NotContributedFacetForActionLayoutAnnotation facetImpl = (NotContributedFacetForActionLayoutAnnotation) facet;
+            assertThat(facetImpl.value(), CoreMatchers.equalTo(NotContributed.As.ACTION));
+
+        }
+
+        @Test
+        public void onDomainServiceForViewWithAction() {
+
+            // given
+            @DomainService(nature = NatureOfService.VIEW)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_ACTION)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(not(nullValue())));
+            assertThat(facet instanceof NotContributedFacetForActionLayoutAnnotation, CoreMatchers.is(true));
+            final NotContributedFacetForActionLayoutAnnotation facetImpl = (NotContributedFacetForActionLayoutAnnotation) facet;
+            assertThat(facetImpl.value(), CoreMatchers.equalTo(NotContributed.As.ASSOCIATION));
+        }
+
+        @Test
+        public void onDomainServiceForViewWithNeither() {
+            // given
+            @DomainService(nature = NatureOfService.VIEW)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_NEITHER)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(not(nullValue())));
+            assertThat(facet instanceof NotContributedFacetForActionLayoutAnnotation, CoreMatchers.is(true));
+            final NotContributedFacetForActionLayoutAnnotation facetImpl = (NotContributedFacetForActionLayoutAnnotation) facet;
+            assertThat(facetImpl.value(), CoreMatchers.equalTo(NotContributed.As.EITHER));
+        }
+
+        @Test
+        public void onDomainServiceForViewContributionsOnly() {
+
+            // given
+            @DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_NEITHER)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(not(nullValue())));
+            assertThat(facet instanceof NotContributedFacetForActionLayoutAnnotation, CoreMatchers.is(true));
+            final NotContributedFacetForActionLayoutAnnotation facetImpl = (NotContributedFacetForActionLayoutAnnotation) facet;
+            assertThat(facetImpl.value(), CoreMatchers.equalTo(NotContributed.As.EITHER));
+
+        }
+
+        @Test
+        public void onDomainServiceForViewMenuOnly() {
+
+            // given
+            @DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_NEITHER)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(nullValue()));
+
+        }
+
+        @Test
+        public void onDomainServiceForDomainWithBoth() {
+
+            // given
+            @DomainService(nature = NatureOfService.DOMAIN)
+            class CustomerService {
+
+                @ActionLayout(contributed = Contributed.AS_NEITHER)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {
+                }));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(nullValue()));
+
+        }
+
+        @Test
+        public void onDomainObjectIsIgnored() {
+
+
+            // given
+            @DomainObject
+            class Customer {
+
+                @ActionLayout(contributed = Contributed.AS_NEITHER)
+                public String name() {
+                    return "Joe";
+                }
+            }
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(null));
+            }});
+
+            expectNoMethodsRemoved();
+
+            facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+
+            // when
+            facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+
+            // then
+            final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
+            assertThat(facet, CoreMatchers.is(nullValue()));
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java
index 321102f..d500b9b 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/layout/ActionLayoutAnnotationFacetFactoryTest.java
@@ -20,13 +20,18 @@
 package org.apache.isis.core.metamodel.facets.actions.layout;
 
 import java.lang.reflect.Method;
+import org.jmock.Expectations;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
 import org.apache.isis.applib.annotation.ActionLayout;
 import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryTest;
+import org.apache.isis.core.metamodel.facets.AbstractFacetFactoryJUnit4TestCase;
 import org.apache.isis.core.metamodel.facets.FacetFactory.ProcessMethodContext;
 import org.apache.isis.core.metamodel.facets.actions.position.ActionPositionFacet;
 import org.apache.isis.core.metamodel.facets.actions.position.ActionPositionFacetFallback;
 import org.apache.isis.core.metamodel.facets.members.cssclassfa.CssClassFaFacet;
+import org.apache.isis.core.metamodel.facets.object.domainservice.DomainServiceFacet;
 
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.instanceOf;
@@ -34,10 +39,18 @@ import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 import static org.junit.Assert.assertThat;
 
-public class ActionLayoutAnnotationFacetFactoryTest extends AbstractFacetFactoryTest {
+public class ActionLayoutAnnotationFacetFactoryTest extends AbstractFacetFactoryJUnit4TestCase {
 
+    ActionLayoutFacetFactory facetFactory;
+
+    @Before
+    public void setUp() throws Exception {
+        facetFactory = new ActionLayoutFacetFactory();
+        facetFactory.setSpecificationLookup(mockSpecificationLoaderSpi);
+    }
+
+    @Test
     public void testActionLayoutAnnotationPickedUp() {
-        final ActionLayoutFacetFactory facetFactory = new ActionLayoutFacetFactory();
 
         class Customer {
             @SuppressWarnings("unused")
@@ -48,17 +61,26 @@ public class ActionLayoutAnnotationFacetFactoryTest extends AbstractFacetFactory
         }
         final Method method = findMethod(Customer.class, "foz");
 
-        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, methodRemover, facetedMethod));
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(null));
+        }});
+
+
+        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, mockMethodRemover, facetedMethod));
 
         final Facet facet = facetedMethod.getFacet(ActionPositionFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof ActionPositionFacetForActionLayoutAnnotation);
+        Assert.assertNotNull(facet);
+        Assert.assertTrue(facet instanceof ActionPositionFacetForActionLayoutAnnotation);
         final ActionPositionFacetForActionLayoutAnnotation actionLayoutFacetAnnotation = (ActionPositionFacetForActionLayoutAnnotation) facet;
-        assertEquals(ActionLayout.Position.PANEL, actionLayoutFacetAnnotation.position());
+        Assert.assertEquals(ActionLayout.Position.PANEL, actionLayoutFacetAnnotation.position());
     }
 
+    @Test
     public void testActionLayoutFallbackPickedUp() {
-        final ActionLayoutFacetFactory facetFactory = new ActionLayoutFacetFactory();
 
         class Customer {
             @SuppressWarnings("unused")
@@ -69,55 +91,84 @@ public class ActionLayoutAnnotationFacetFactoryTest extends AbstractFacetFactory
         }
         final Method method = findMethod(Customer.class, "foo");
 
-        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, methodRemover, facetedMethod));
+        context.checking(new Expectations() {{
+            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            will(returnValue(mockObjSpec));
+
+            allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+            will(returnValue(null));
+        }});
+
+        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, mockMethodRemover, facetedMethod));
 
         final Facet facet = facetedMethod.getFacet(ActionPositionFacet.class);
-        assertNotNull(facet);
-        assertTrue(facet instanceof ActionPositionFacetFallback);
+        Assert.assertNotNull(facet);
+        Assert.assertTrue(facet instanceof ActionPositionFacetFallback);
     }
 
-    public void testCssClassFaLeftPositionIsDefault() {
-        final ActionLayoutFacetFactory facetFactory = new ActionLayoutFacetFactory();
+    public static class CssClassFa extends ActionLayoutAnnotationFacetFactoryTest {
 
-        class Customer {
-            @SuppressWarnings("unused")
-            @ActionLayout(cssClassFa = "font-awesome")
-            public String foz() {
-                return null;
+        @Test
+        public void testDefaultPosition() {
+
+            class Customer {
+                @SuppressWarnings("unused")
+                @ActionLayout(cssClassFa = "font-awesome")
+                public String foz() {
+                    return null;
+                }
             }
-        }
-        final Method method = findMethod(Customer.class, "foz");
+            final Method method = findMethod(Customer.class, "foz");
 
-        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, methodRemover, facetedMethod));
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+                will(returnValue(mockObjSpec));
 
-        Facet facet = facetedMethod.getFacet(CssClassFaFacet.class);
-        assertThat(facet, is(notNullValue()));
-        assertThat(facet, is(instanceOf(CssClassFaFacetForActionLayoutAnnotation.class)));
-        CssClassFaFacetForActionLayoutAnnotation classFaFacetForActionLayoutAnnotation = (CssClassFaFacetForActionLayoutAnnotation) facet;
-        assertThat(classFaFacetForActionLayoutAnnotation.value(), is(equalTo("fa fa-fw font-awesome")));
-        assertThat(classFaFacetForActionLayoutAnnotation.getPosition(), is(ActionLayout.CssClassFaPosition.LEFT));
-    }
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(null));
+            }});
 
-    public void testCssClassFaRightPosition() {
-        final ActionLayoutFacetFactory facetFactory = new ActionLayoutFacetFactory();
+            facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, mockMethodRemover, facetedMethod));
 
-        class Customer {
-            @SuppressWarnings("unused")
-            @ActionLayout(cssClassFa = "font-awesome", cssClassFaPosition = ActionLayout.CssClassFaPosition.RIGHT)
-            public String foz() {
-                return null;
-            }
+            Facet facet = facetedMethod.getFacet(CssClassFaFacet.class);
+            assertThat(facet, is(notNullValue()));
+            assertThat(facet, is(instanceOf(CssClassFaFacetForActionLayoutAnnotation.class)));
+            CssClassFaFacetForActionLayoutAnnotation classFaFacetForActionLayoutAnnotation = (CssClassFaFacetForActionLayoutAnnotation) facet;
+            assertThat(classFaFacetForActionLayoutAnnotation.value(), is(equalTo("fa fa-fw font-awesome")));
+            assertThat(classFaFacetForActionLayoutAnnotation.getPosition(), is(ActionLayout.CssClassFaPosition.LEFT));
         }
-        final Method method = findMethod(Customer.class, "foz");
 
-        facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, methodRemover, facetedMethod));
+        @Test
+        public void testRightPosition() {
+
+            class Customer {
+                @SuppressWarnings("unused")
+                @ActionLayout(cssClassFa = "font-awesome", cssClassFaPosition = ActionLayout.CssClassFaPosition.RIGHT)
+                public String foz() {
+                    return null;
+                }
+            }
+            final Method method = findMethod(Customer.class, "foz");
+
+            context.checking(new Expectations() {{
+                allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+                will(returnValue(mockObjSpec));
+
+                allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
+                will(returnValue(null));
+            }});
+
+            facetFactory.process(new ProcessMethodContext(Customer.class, null, null, method, mockMethodRemover, facetedMethod));
+
+            Facet facet = facetedMethod.getFacet(CssClassFaFacet.class);
+            assertThat(facet, is(notNullValue()));
+            assertThat(facet, is(instanceOf(CssClassFaFacetForActionLayoutAnnotation.class)));
+            CssClassFaFacetForActionLayoutAnnotation classFaFacetForActionLayoutAnnotation = (CssClassFaFacetForActionLayoutAnnotation) facet;
+            assertThat(classFaFacetForActionLayoutAnnotation.value(), is(equalTo("fa fa-fw font-awesome")));
+            assertThat(classFaFacetForActionLayoutAnnotation.getPosition(), is(ActionLayout.CssClassFaPosition.RIGHT));
+        }
 
-        Facet facet = facetedMethod.getFacet(CssClassFaFacet.class);
-        assertThat(facet, is(notNullValue()));
-        assertThat(facet, is(instanceOf(CssClassFaFacetForActionLayoutAnnotation.class)));
-        CssClassFaFacetForActionLayoutAnnotation classFaFacetForActionLayoutAnnotation = (CssClassFaFacetForActionLayoutAnnotation) facet;
-        assertThat(classFaFacetForActionLayoutAnnotation.value(), is(equalTo("fa fa-fw font-awesome")));
-        assertThat(classFaFacetForActionLayoutAnnotation.getPosition(), is(ActionLayout.CssClassFaPosition.RIGHT));
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
index 5a05f12..d62e916 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notcontributed/derived/NotContributedFacetDerivedFromDomainServiceFacetFactoryTest.java
@@ -34,7 +34,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
 
         // given
         @DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -42,19 +42,20 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
@@ -69,7 +70,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
 
         // given
         @DomainService(nature = NatureOfService.DOMAIN)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -77,19 +78,20 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
@@ -104,7 +106,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
 
         // given
         @DomainService(nature = NatureOfService.VIEW)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -112,19 +114,20 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
@@ -136,7 +139,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
 
         // given
         @DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -144,19 +147,20 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);
@@ -167,7 +171,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
     public void whenNone() throws Exception {
 
         // given
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -175,7 +179,7 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
@@ -184,10 +188,10 @@ public class NotContributedFacetDerivedFromDomainServiceFacetFactoryTest extends
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotContributedFacet.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
index 7d69a76..dfb1a4a 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/actions/notinservicemenu/derived/NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest.java
@@ -34,7 +34,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
 
         // given
         @DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -42,19 +42,20 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_CONTRIBUTIONS_ONLY) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
@@ -69,7 +70,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
 
         // given
         @DomainService(nature = NatureOfService.DOMAIN)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -77,19 +78,20 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.DOMAIN) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
@@ -104,7 +106,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
 
         // given
         @DomainService(nature = NatureOfService.VIEW)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -112,19 +114,20 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
@@ -136,7 +139,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
 
         // given
         @DomainService(nature = NatureOfService.VIEW_MENU_ONLY)
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -144,19 +147,20 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
-            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {}));
+            will(returnValue(new DomainServiceFacetAbstract(mockObjSpec, null, NatureOfService.VIEW_MENU_ONLY) {
+            }));
         }});
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);
@@ -167,7 +171,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
     public void whenNone() throws Exception {
 
         // given
-        class Customer {
+        class CustomerService {
 
             public String name() {
                 return "Joe";
@@ -175,7 +179,7 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
         }
 
         context.checking(new Expectations() {{
-            allowing(mockSpecificationLoaderSpi).loadSpecification(Customer.class);
+            allowing(mockSpecificationLoaderSpi).loadSpecification(CustomerService.class);
             will(returnValue(mockObjSpec));
 
             allowing(mockObjSpec).getFacet(DomainServiceFacet.class);
@@ -184,10 +188,10 @@ public class NotInServiceMenuFacetDerivedFromDomainServiceFacetFactoryTest exten
 
         expectNoMethodsRemoved();
 
-        facetedMethod = FacetedMethod.createForAction(Customer.class, "name");
+        facetedMethod = FacetedMethod.createForAction(CustomerService.class, "name");
 
         // when
-        facetFactory.process(new FacetFactory.ProcessMethodContext(Customer.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
+        facetFactory.process(new FacetFactory.ProcessMethodContext(CustomerService.class, null, null, facetedMethod.getMethod(), mockMethodRemover, facetedMethod));
 
         // then
         final Facet facet = facetedMethod.getFacet(NotInServiceMenuFacet.class);

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/example/application/todoapp/dom/src/main/java/app/ToDoItemAnalysisContributions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/app/ToDoItemAnalysisContributions.java b/example/application/todoapp/dom/src/main/java/app/ToDoItemAnalysisContributions.java
index 6527ffe..baf4b00 100644
--- a/example/application/todoapp/dom/src/main/java/app/ToDoItemAnalysisContributions.java
+++ b/example/application/todoapp/dom/src/main/java/app/ToDoItemAnalysisContributions.java
@@ -21,20 +21,18 @@ package app;
 import dom.todo.ToDoItem;
 
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.Contributed;
 import org.apache.isis.applib.annotation.DomainService;
-import org.apache.isis.applib.annotation.Hidden;
-import org.apache.isis.applib.annotation.NotContributed;
-import org.apache.isis.applib.annotation.NotContributed.As;
-import org.apache.isis.applib.annotation.NotInServiceMenu;
+import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.SemanticsOf;
 
-@DomainService
+@DomainService(nature = NatureOfService.VIEW_CONTRIBUTIONS_ONLY)
 public class ToDoItemAnalysisContributions {
 
 
     //region > analyseCategory (action)
-    @NotInServiceMenu
-    @NotContributed(As.ASSOCIATION)
+    @ActionLayout(contributed = Contributed.AS_ACTION)
     @Action(
             semantics = SemanticsOf.SAFE
     )

http://git-wip-us.apache.org/repos/asf/isis/blob/f3294b65/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
----------------------------------------------------------------------
diff --git a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
index 655ad30..3698130 100644
--- a/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
+++ b/example/application/todoapp/dom/src/main/java/dom/todo/ToDoItemContributions.java
@@ -32,11 +32,10 @@ import org.joda.time.LocalDate;
 import org.apache.isis.applib.AbstractFactoryAndRepository;
 import org.apache.isis.applib.annotation.Action;
 import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.Contributed;
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
-import org.apache.isis.applib.annotation.NotContributed;
-import org.apache.isis.applib.annotation.NotContributed.As;
 import org.apache.isis.applib.annotation.Optional;
 import org.apache.isis.applib.annotation.ParameterLayout;
 import org.apache.isis.applib.annotation.SemanticsOf;
@@ -49,13 +48,13 @@ import org.apache.isis.applib.value.Clob;
 public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     //region > priority (contributed property)
-    @NotContributed(As.ACTION) // ie contributed as association
     @Action(
             semantics = SemanticsOf.SAFE,
             hidden = Where.ALL_TABLES
     )
     @ActionLayout(
-            describedAs = "The relative priority of this item compared to others not yet complete (using 'due by' date)"
+            describedAs = "The relative priority of this item compared to others not yet complete (using 'due by' date)",
+            contributed = Contributed.AS_ASSOCIATION
     )
     @Disabled(reason="Relative priority, derived from due date")
     public Integer relativePriority(final ToDoItem toDoItem) {
@@ -104,10 +103,10 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     //endregion
 
     //region >  next, previous (contributed actions)
-    @NotContributed(As.ASSOCIATION) // ie contributed as action
     @Action(semantics = SemanticsOf.SAFE)
     @ActionLayout(
-            describedAs = "The next item not yet completed"
+            describedAs = "The next item not yet completed",
+            contributed = Contributed.AS_ACTION
     )
     public ToDoItem next(final ToDoItem item) {
         final Integer priority = relativePriority(item);
@@ -129,9 +128,9 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     // //////////////////////////////////////
 
-    @NotContributed(As.ASSOCIATION) // ie contributed as action
     @ActionLayout(
-            describedAs = "The previous item not yet completed"
+            describedAs = "The previous item not yet completed",
+            contributed = Contributed.AS_ACTION
     )
     @Action(semantics = SemanticsOf.SAFE)
     public ToDoItem previous(final ToDoItem item) {
@@ -170,7 +169,9 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     //endregion
 
     //region > similarTo (contributed collection)
-    @NotContributed(As.ACTION)
+    @ActionLayout(
+            contributed = Contributed.AS_ASSOCIATION
+    )
     @Action(semantics = SemanticsOf.SAFE)
     public List<ToDoItem> similarTo(final ToDoItem toDoItem) {
         final List<ToDoItem> similarToDoItems = allMatches(