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 2014/02/26 23:41:00 UTC

git commit: ISIS-541: hide and disable now supported for contributee actions.

Repository: isis
Updated Branches:
  refs/heads/master 47ed4b32d -> 5eb556b18


ISIS-541: hide and disable now supported for contributee actions.

In addition, in the todo example app:
- enhance next/previous contributed actions to demonstrate usage
- use QueryResultsCache as demo
- changed JDOQL query names, to follow Estatio's convention
- removed some unused "naive" repository query examples


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

Branch: refs/heads/master
Commit: 5eb556b18fed8f9d4cbcddea0f55bc03464b8bfe
Parents: 47ed4b3
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Wed Feb 26 22:40:49 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Wed Feb 26 22:40:49 2014 +0000

----------------------------------------------------------------------
 .../adapter/util/AdapterInvokeUtils.java        | 16 ++++
 .../interactions/InteractionContext.java        | 25 +++++-
 .../specimpl/ObjectActionContributee.java       | 14 ++-
 .../disabled/DisableForContextFacet.java        |  4 -
 .../DisableForContextFacetAbstract.java         |  8 --
 .../disabled/DisableForContextFacetNone.java    |  8 +-
 .../method/DisableForContextFacetViaMethod.java | 12 ++-
 .../members/hidden/HideForContextFacet.java     |  1 -
 .../hidden/HideForContextFacetAbstract.java     |  7 +-
 .../members/hidden/HideForContextFacetNone.java |  7 +-
 .../method/HideForContextFacetViaMethod.java    | 10 ++-
 .../dom/src/main/java/dom/todo/ToDoItem.java    | 15 ++--
 .../java/dom/todo/ToDoItemContributions.java    | 94 +++++++++++++-------
 .../dom/src/main/java/dom/todo/ToDoItems.java   | 54 ++++-------
 .../src/main/webapp/WEB-INF/isis.properties     |  1 +
 15 files changed, 168 insertions(+), 108 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterInvokeUtils.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterInvokeUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterInvokeUtils.java
index b0a7c15..1648d56 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterInvokeUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/adapter/util/AdapterInvokeUtils.java
@@ -21,6 +21,7 @@ package org.apache.isis.core.metamodel.adapter.util;
 
 import java.lang.reflect.Method;
 import java.util.List;
+import java.util.Map;
 
 import com.google.common.collect.Lists;
 
@@ -56,6 +57,21 @@ public final class AdapterInvokeUtils {
         return MethodExtensions.invoke(method, AdapterUtils.unwrap(adapter), AdapterUtils.unwrap(argumentAdapters));
     }
     
+    public static Object invoke(final Method method, final ObjectAdapter adapter, final Map<Integer, ObjectAdapter> argumentAdapters) {
+        return invoke(method, adapter, asArray(argumentAdapters, method.getParameterTypes().length));
+    }
+
+    private static ObjectAdapter[] asArray(Map<Integer, ObjectAdapter> argumentAdapters, int length) {
+        ObjectAdapter[] args = new ObjectAdapter[length];
+        for (final Map.Entry<Integer, ObjectAdapter> entry : argumentAdapters.entrySet()) {
+            final Integer paramNum = entry.getKey();
+            if(paramNum < length) {
+                args[paramNum] = entry.getValue();
+            }
+        }
+        return args;
+    }
+
     /**
      * Invokes the method, adjusting arguments as required to make them fit the method's parameters.
      * 

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/InteractionContext.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/InteractionContext.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/InteractionContext.java
index e3c04db..3e4ff01 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/InteractionContext.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/interactions/InteractionContext.java
@@ -19,6 +19,10 @@
 
 package org.apache.isis.core.metamodel.interactions;
 
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+
 import org.apache.isis.applib.Identifier;
 import org.apache.isis.applib.events.InteractionEvent;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
@@ -61,8 +65,10 @@ public abstract class InteractionContext<T extends InteractionEvent> {
     private final InteractionInvocationMethod invocation;
     private final AuthenticationSession session;
     private final ObjectAdapter target;
-    // TODO: need to pass this in, obtain from DeploymentCategoryProvider (as implemented by the runtime's DeploymentType)
     private final DeploymentCategory deploymentCategory;
+    
+    private int contributeeParam = -1; // no contributee
+    private ObjectAdapter contributee = null;
 
     public InteractionContext(final InteractionContextType interactionType, DeploymentCategory deploymentCategory, final AuthenticationSession session, final InteractionInvocationMethod invocationMethod, final Identifier identifier, final ObjectAdapter target) {
         this.interactionType = interactionType;
@@ -136,6 +142,23 @@ public abstract class InteractionContext<T extends InteractionEvent> {
         return target;
     }
 
+    // //////////////////////////////////////
+
+    public void putContributee(int contributeeParam, ObjectAdapter contributee) {
+        this.contributeeParam = contributeeParam;
+        this.contributee = contributee;
+    }
+    
+    public Map<Integer, ObjectAdapter> getContributeeAsMap() {
+        return contributee != null
+                ? ImmutableMap.<Integer, ObjectAdapter>of(contributeeParam, contributee)
+                : ImmutableMap.<Integer, ObjectAdapter>of();
+    }
+
+    // //////////////////////////////////////
+
+    
+    
     /**
      * Factory method to create corresponding {@link InteractionEvent}.
      * 

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
index 49cd76c..87a6992 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectActionContributee.java
@@ -31,12 +31,18 @@ import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.commons.lang.ObjectExtensions;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.consent.Consent;
+import org.apache.isis.core.metamodel.consent.InteractionInvocationMethod;
+import org.apache.isis.core.metamodel.consent.InteractionResult;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
 import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetHolderImpl;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.MultiTypedFacet;
 import org.apache.isis.core.metamodel.facets.actions.invoke.ActionInvocationFacet;
+import org.apache.isis.core.metamodel.interactions.InteractionUtils;
+import org.apache.isis.core.metamodel.interactions.UsabilityContext;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
 import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
@@ -142,12 +148,16 @@ public class ObjectActionContributee extends ObjectActionImpl implements Contrib
     
     @Override
     public Consent isVisible(final AuthenticationSession session, final ObjectAdapter contributee, Where where) {
-        return serviceAction.isVisible(session, serviceAdapter, where);
+        final VisibilityContext<?> ic = serviceAction.createVisibleInteractionContext(session, InteractionInvocationMethod.BY_USER, serviceAdapter, where);
+        ic.putContributee(this.contributeeParam, contributee);
+        return InteractionUtils.isVisibleResult(this, ic).createConsent();
     }
 
     @Override
     public Consent isUsable(final AuthenticationSession session, final ObjectAdapter contributee, Where where) {
-        return serviceAction.isUsable(session, serviceAdapter, where);
+        final UsabilityContext<?> ic = serviceAction.createUsableInteractionContext(session, InteractionInvocationMethod.BY_USER, serviceAdapter, where);
+        ic.putContributee(this.contributeeParam, contributee);
+        return InteractionUtils.isUsableResult(this, ic).createConsent();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacet.java
index d8e2a14..46cff41 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacet.java
@@ -33,9 +33,5 @@ import org.apache.isis.core.metamodel.interactions.DisablingInteractionAdvisor;
  */
 public interface DisableForContextFacet extends Facet, DisablingInteractionAdvisor {
 
-    /**
-     * The reason this object is disabled, or <tt>null</tt> otherwise.
-     */
-    public String disabledReason(ObjectAdapter object);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetAbstract.java
index 7544595..78fe58b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetAbstract.java
@@ -19,12 +19,9 @@
 
 package org.apache.isis.core.progmodel.facets.members.disabled;
 
-import org.apache.isis.applib.events.UsabilityEvent;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 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.interactions.UsabilityContext;
 
 public abstract class DisableForContextFacetAbstract extends FacetAbstract implements DisableForContextFacet {
 
@@ -36,10 +33,5 @@ public abstract class DisableForContextFacetAbstract extends FacetAbstract imple
         super(type(), holder, Derivation.NOT_DERIVED);
     }
 
-    @Override
-    public String disables(final UsabilityContext<? extends UsabilityEvent> ic) {
-        final ObjectAdapter target = ic.getTarget();
-        return disabledReason(target);
-    }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetNone.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetNone.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetNone.java
index 46e5f42..37abf73 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetNone.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/DisableForContextFacetNone.java
@@ -19,8 +19,10 @@
 
 package org.apache.isis.core.progmodel.facets.members.disabled;
 
+import org.apache.isis.applib.events.UsabilityEvent;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.interactions.UsabilityContext;
 
 public class DisableForContextFacetNone extends DisableForContextFacetAbstract {
 
@@ -29,13 +31,17 @@ public class DisableForContextFacetNone extends DisableForContextFacetAbstract {
     }
 
     /**
+     * The reason this object is disabled, or <tt>null</tt> otherwise.
+     * 
+     * <p>
      * Always returns <tt>null</tt>.
      */
     @Override
-    public String disabledReason(final ObjectAdapter target) {
+    public String disables(final UsabilityContext<? extends UsabilityEvent> ic) {
         return null;
     }
 
+
     @Override
     public boolean isNoop() {
         return true;

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
index b963808..0282b7c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/disabled/method/DisableForContextFacetViaMethod.java
@@ -23,10 +23,12 @@ import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.isis.applib.events.UsabilityEvent;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.interactions.UsabilityContext;
 import org.apache.isis.core.progmodel.facets.members.disabled.DisableForContextFacetAbstract;
 
 public class DisableForContextFacetViaMethod extends DisableForContextFacetAbstract implements ImperativeFacet {
@@ -57,12 +59,16 @@ public class DisableForContextFacetViaMethod extends DisableForContextFacetAbstr
         return false;
     }
 
+    /**
+     * The reason this object is disabled, or <tt>null</tt> otherwise.
+     */
     @Override
-    public String disabledReason(final ObjectAdapter owningAdapter) {
-        if (owningAdapter == null) {
+    public String disables(final UsabilityContext<? extends UsabilityEvent> ic) {
+        final ObjectAdapter target = ic.getTarget();
+        if (target == null) {
             return null;
         }
-        return (String) AdapterInvokeUtils.invoke(method, owningAdapter);
+        return (String) AdapterInvokeUtils.invoke(method, target, ic.getContributeeAsMap());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacet.java
index d1d39ea..3364f1d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacet.java
@@ -33,6 +33,5 @@ import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
  */
 public interface HideForContextFacet extends Facet, HidingInteractionAdvisor {
 
-    public String hiddenReason(ObjectAdapter object);
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetAbstract.java
index d815af5..e1df4ed 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetAbstract.java
@@ -19,11 +19,9 @@
 
 package org.apache.isis.core.progmodel.facets.members.hidden;
 
-import org.apache.isis.applib.events.VisibilityEvent;
 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.interactions.VisibilityContext;
 
 public abstract class HideForContextFacetAbstract extends FacetAbstract implements HideForContextFacet {
 
@@ -35,8 +33,5 @@ public abstract class HideForContextFacetAbstract extends FacetAbstract implemen
         super(type(), holder, Derivation.NOT_DERIVED);
     }
 
-    @Override
-    public String hides(final VisibilityContext<? extends VisibilityEvent> ic) {
-        return hiddenReason(ic.getTarget());
-    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetNone.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetNone.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetNone.java
index fc825b1..7577012 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetNone.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/HideForContextFacetNone.java
@@ -19,8 +19,9 @@
 
 package org.apache.isis.core.progmodel.facets.members.hidden;
 
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.applib.events.VisibilityEvent;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 
 public class HideForContextFacetNone extends HideForContextFacetAbstract {
 
@@ -32,10 +33,10 @@ public class HideForContextFacetNone extends HideForContextFacetAbstract {
      * Always returns <tt>null</tt>.
      */
     @Override
-    public String hiddenReason(final ObjectAdapter object) {
+    public String hides(final VisibilityContext<? extends VisibilityEvent> ic) {
         return null;
     }
-
+    
     @Override
     public boolean isNoop() {
         return true;

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
index 6677514..40e3bc4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/members/hidden/method/HideForContextFacetViaMethod.java
@@ -23,10 +23,12 @@ import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.List;
 
+import org.apache.isis.applib.events.VisibilityEvent;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.interactions.VisibilityContext;
 import org.apache.isis.core.progmodel.facets.members.hidden.HideForContextFacetAbstract;
 
 public class HideForContextFacetViaMethod extends HideForContextFacetAbstract implements ImperativeFacet {
@@ -58,11 +60,12 @@ public class HideForContextFacetViaMethod extends HideForContextFacetAbstract im
     }
 
     @Override
-    public String hiddenReason(final ObjectAdapter owningAdapter) {
-        if (owningAdapter == null) {
+    public String hides(final VisibilityContext<? extends VisibilityEvent> ic) {
+        final ObjectAdapter target = ic.getTarget();
+        if (target == null) {
             return null;
         }
-        final Boolean isHidden = (Boolean) AdapterInvokeUtils.invoke(method, owningAdapter);
+        final Boolean isHidden = (Boolean) AdapterInvokeUtils.invoke(method, target, ic.getContributeeAsMap());
         return isHidden.booleanValue() ? "Hidden" : null;
     }
 
@@ -71,4 +74,5 @@ public class HideForContextFacetViaMethod extends HideForContextFacetAbstract im
         return "method=" + method;
     }
 
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
index d4b0a1a..b752086 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItem.java
@@ -39,10 +39,9 @@ import com.google.common.collect.Ordering;
 
 import org.joda.time.LocalDate;
 
-import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.NonRecoverableException;
 import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.ActionSemantics.Of;
 import org.apache.isis.applib.annotation.Audited;
@@ -51,6 +50,7 @@ import org.apache.isis.applib.annotation.Bookmarkable;
 import org.apache.isis.applib.annotation.Bulk;
 import org.apache.isis.applib.annotation.Bulk.AppliesTo;
 import org.apache.isis.applib.annotation.Bulk.InteractionContext.InvokedAs;
+import org.apache.isis.applib.annotation.Command;
 import org.apache.isis.applib.annotation.Command.ExecuteIn;
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.annotation.Hidden;
@@ -63,7 +63,6 @@ import org.apache.isis.applib.annotation.Prototype;
 import org.apache.isis.applib.annotation.PublishedAction;
 import org.apache.isis.applib.annotation.PublishedObject;
 import org.apache.isis.applib.annotation.RegEx;
-import org.apache.isis.applib.annotation.Command;
 import org.apache.isis.applib.annotation.SortedBy;
 import org.apache.isis.applib.annotation.TypicalLength;
 import org.apache.isis.applib.clock.Clock;
@@ -90,30 +89,30 @@ import services.ClockService;
 })
 @javax.jdo.annotations.Queries( {
     @javax.jdo.annotations.Query(
-            name = "todo_all", language = "JDOQL",
+            name = "findByOwnedBy", language = "JDOQL",
             value = "SELECT "
                     + "FROM dom.todo.ToDoItem "
                     + "WHERE ownedBy == :ownedBy"),
     @javax.jdo.annotations.Query(
-            name = "todo_notYetComplete", language = "JDOQL",
+            name = "findByOwnedByAndCompleteIsFalse", language = "JDOQL",
             value = "SELECT "
                     + "FROM dom.todo.ToDoItem "
                     + "WHERE ownedBy == :ownedBy "
                     + "   && complete == false"),
     @javax.jdo.annotations.Query(
-            name = "todo_complete", language = "JDOQL",
+            name = "findByOwnedByAndCompleteIsTrue", language = "JDOQL",
             value = "SELECT "
                     + "FROM dom.todo.ToDoItem "
                     + "WHERE ownedBy == :ownedBy "
                     + "&& complete == true"),
     @javax.jdo.annotations.Query(
-            name = "todo_similarTo", language = "JDOQL",
+            name = "findByOwnedByAndCategory", language = "JDOQL",
             value = "SELECT "
                     + "FROM dom.todo.ToDoItem "
                     + "WHERE ownedBy == :ownedBy "
                     + "&& category == :category"),
     @javax.jdo.annotations.Query(
-            name = "todo_autoComplete", language = "JDOQL",
+            name = "findByOwnedByAndDescriptionContains", language = "JDOQL",
             value = "SELECT "
                     + "FROM dom.todo.ToDoItem "
                     + "WHERE ownedBy == :ownedBy && "

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
index 5720521..ec52206 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItemContributions.java
@@ -19,6 +19,7 @@
 package dom.todo;
 
 import java.util.List;
+import java.util.concurrent.Callable;
 
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
@@ -44,6 +45,7 @@ import org.apache.isis.applib.annotation.NotInServiceMenu;
 import org.apache.isis.applib.annotation.Optional;
 import org.apache.isis.applib.annotation.Where;
 import org.apache.isis.applib.query.QueryDefault;
+import org.apache.isis.applib.services.queryresultscache.QueryResultsCache;
 
 public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
@@ -55,23 +57,27 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     @DescribedAs("The relative priority of this item compared to others not yet complete (using 'due by' date)")
     @NotInServiceMenu
     @ActionSemantics(Of.SAFE)
-    @NotContributed(As.ACTION)
+    @NotContributed(As.ACTION) // ie contributed as association
     @Hidden(where=Where.ALL_TABLES)
     @Disabled(reason="Relative priority, derived from due date")
     public Integer relativePriority(final ToDoItem toDoItem) {
-        if(toDoItem.isComplete()) {
-            return null;
-        }
-
-        // sort items, then locate this one
-        int i=1;
-        for (ToDoItem each : sortedNotYetComplete()) {
-            if(each == toDoItem) {
-                return i;
-            }
-            i++;
-        }
-        return null;
+        return queryResultsCache.execute(new Callable<Integer>(){
+            @Override
+            public Integer call() throws Exception {
+                if(toDoItem.isComplete()) {
+                    return null;
+                }
+
+                // sort items, then locate this one
+                int i=1;
+                for (ToDoItem each : sortedNotYetComplete()) {
+                    if(each == toDoItem) {
+                        return i;
+                    }
+                    i++;
+                }
+                return null;
+            }}, ToDoItemContributions.class, "relativePriority", toDoItem);
     }
 
 
@@ -105,7 +111,7 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     @DescribedAs("The next item not yet completed")
     @NotInServiceMenu
     @ActionSemantics(Of.SAFE)
-    @NotContributed(As.ASSOCIATION)
+    @NotContributed(As.ASSOCIATION) // ie contributed as action
     public ToDoItem next(final ToDoItem item) {
         final Integer priority = relativePriority(item);
         if(priority == null) {
@@ -114,11 +120,22 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
         int priorityOfNext = priority != null ? priority + 1 : 0;
         return itemWithPriorityElse(priorityOfNext, item);
     }
+    public String disableNext(final ToDoItem toDoItem) {
+        if (toDoItem.isComplete()) {
+            return "Completed";
+        } 
+        if(next(toDoItem) == null) {
+            return "No next item";
+        }
+        return null;
+    }
+
+    // //////////////////////////////////////
     
     @DescribedAs("The previous item not yet completed")
     @NotInServiceMenu
     @ActionSemantics(Of.SAFE)
-    @NotContributed(As.ASSOCIATION)
+    @NotContributed(As.ASSOCIATION) // ie contributed as action
     public ToDoItem previous(final ToDoItem item) {
         final Integer priority = relativePriority(item);
         if(priority == null) {
@@ -127,14 +144,32 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
         int priorityOfPrevious = priority != null? priority - 1 : 0;
         return itemWithPriorityElse(priorityOfPrevious, item);
     }
+    public String disablePrevious(final ToDoItem toDoItem) {
+        if (toDoItem.isComplete()) {
+            return "Completed";
+        }
+        if(previous(toDoItem) == null) {
+            return "No previous item";
+        }
+        return null;
+    }
 
+    // //////////////////////////////////////
 
-    private ToDoItem itemWithPriorityElse(int idx, final ToDoItem itemElse) {
+    /**
+     * @param priority : 1-based priority
+     */
+    private ToDoItem itemWithPriorityElse(int priority, final ToDoItem itemElse) {
+        if(priority < 1) {
+            return null;
+        }
         final List<ToDoItem> items = sortedNotYetComplete();
-        return idx>=0 && items.size()>=idx? items.get(idx-1): itemElse;
+        if(priority > items.size()) {
+            return null;
+        }
+        return priority>=0 && items.size()>=priority? items.get(priority-1): itemElse;
     }
 
-    
     // //////////////////////////////////////
     // SimilarTo (contributed collection)
     // //////////////////////////////////////
@@ -143,18 +178,12 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
     @ActionSemantics(Of.SAFE)
     @NotContributed(As.ACTION)
     public List<ToDoItem> similarTo(final ToDoItem toDoItem) {
-        if(false) {
-            // the naive implementation ...
-            return allMatches(ToDoItem.class, ToDoItem.Predicates.thoseSimilarTo(toDoItem));
-        } else {
-            // the JDO implementation ...
-            final List<ToDoItem> similarToDoItems = allMatches(
-                    new QueryDefault<ToDoItem>(ToDoItem.class, 
-                            "todo_similarTo", 
-                            "ownedBy", currentUserName(), 
-                            "category", toDoItem.getCategory()));
-            return Lists.newArrayList(Iterables.filter(similarToDoItems, excluding(toDoItem)));
-        }
+        final List<ToDoItem> similarToDoItems = allMatches(
+                new QueryDefault<ToDoItem>(ToDoItem.class, 
+                        "findByOwnedByAndCategory", 
+                        "ownedBy", currentUserName(), 
+                        "category", toDoItem.getCategory()));
+        return Lists.newArrayList(Iterables.filter(similarToDoItems, excluding(toDoItem)));
     }
 
 
@@ -219,5 +248,8 @@ public class ToDoItemContributions extends AbstractFactoryAndRepository {
 
     @javax.inject.Inject
     private ToDoItems toDoItems;
+    
+    @javax.inject.Inject
+    private QueryResultsCache queryResultsCache;
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
index 7776a94..fa64a7e 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/main/java/dom/todo/ToDoItems.java
@@ -19,19 +19,15 @@
 package dom.todo;
 
 import java.math.BigDecimal;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Collections;
 import java.util.List;
 
-import com.google.common.base.Objects;
-import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 
 import dom.todo.ToDoItem.Category;
 import dom.todo.ToDoItem.Subcategory;
 
 import org.joda.time.LocalDate;
+
 import org.apache.isis.applib.DomainObjectContainer;
 import org.apache.isis.applib.annotation.ActionSemantics;
 import org.apache.isis.applib.annotation.ActionSemantics.Of;
@@ -82,7 +78,7 @@ public class ToDoItems {
     public List<ToDoItem> notYetCompleteNoUi() {
         return container.allMatches(
                 new QueryDefault<ToDoItem>(ToDoItem.class, 
-                        "todo_notYetComplete", 
+                        "findByOwnedByAndCompleteIsFalse", 
                         "ownedBy", currentUserName()));
     }
 
@@ -105,7 +101,7 @@ public class ToDoItems {
     public List<ToDoItem> completeNoUi() {
         return container.allMatches(
             new QueryDefault<ToDoItem>(ToDoItem.class, 
-                    "todo_complete", 
+                    "findByOwnedByAndCompleteIsTrue", 
                     "ownedBy", currentUserName()));
     }
 
@@ -122,7 +118,7 @@ public class ToDoItems {
     		@Named("Category") final Category category,
     		@Named("Subcategory") final Subcategory subcategory,
     		@Named("Completed?") final boolean completed) {
-    	// a naive implementation
+    	// an example "naive" implementation (filtered in Java code, not DBMS)
         return container.allMatches(ToDoItem.class, 
                 Predicates.and(
                     ToDoItem.Predicates.thoseOwnedBy(currentUserName()), 
@@ -161,8 +157,7 @@ public class ToDoItems {
             final @Named("Subcategory") Subcategory subcategory,
             final @Optional @Named("Due by") LocalDate dueBy,
             final @Optional @Named("Cost") BigDecimal cost) {
-        final String ownedBy = currentUserName();
-        return newToDo(description, category, subcategory, ownedBy, dueBy, cost);
+        return newToDo(description, category, subcategory, currentUserName(), dueBy, cost);
     }
     public Category default1NewToDo() {
         return Category.Professional;
@@ -188,38 +183,33 @@ public class ToDoItems {
     // AllToDos (action)
     // //////////////////////////////////////
 
+    // findByOwnedBy
+    
     @ActionSemantics(Of.SAFE)
     @MemberOrder(sequence = "50")
     public List<ToDoItem> allToDos() {
-        final String currentUser = currentUserName();
-        final List<ToDoItem> items = container.allMatches(ToDoItem.class, ToDoItem.Predicates.thoseOwnedBy(currentUser));
-        Collections.sort(items);
+        final List<ToDoItem> items = container.allMatches(
+                new QueryDefault<ToDoItem>(ToDoItem.class, 
+                        "findByOwnedBy", 
+                        "ownedBy", currentUserName()));
         if(items.isEmpty()) {
             container.warnUser("No to-do items found.");
         }
         return items;
     }
 
+
     // //////////////////////////////////////
     // AutoComplete
     // //////////////////////////////////////
 
     @Programmatic // not part of metamodel
     public List<ToDoItem> autoComplete(final String description) {
-        if(false) {
-            // the naive implementation ...
-            return container.allMatches(ToDoItem.class, 
-                    Predicates.and(
-                        ToDoItem.Predicates.thoseOwnedBy(currentUserName()), 
-                        ToDoItem.Predicates.thoseWithSimilarDescription(description)));
-        } else {
-            // the JDO implementation ...
-            return container.allMatches(
-                    new QueryDefault<ToDoItem>(ToDoItem.class, 
-                            "todo_autoComplete", 
-                            "ownedBy", currentUserName(), 
-                            "description", description));
-        }
+        return container.allMatches(
+                new QueryDefault<ToDoItem>(ToDoItem.class, 
+                        "findByOwnedByAndDescriptionContains", 
+                        "ownedBy", currentUserName(), 
+                        "description", description));
     }
 
 
@@ -242,22 +232,12 @@ public class ToDoItems {
         toDoItem.setDueBy(dueBy);
         toDoItem.setCost(cost);
 
-        // 
-        // GMAP3: uncomment to use https://github.com/danhaywood/isis-wicket-gmap3        
-        // toDoItem.setLocation(
-        //    new Location(51.5172+random(-0.05, +0.05), 0.1182 + random(-0.05, +0.05)));
-        //
-        
         container.persist(toDoItem);
         container.flush();
 
         return toDoItem;
     }
     
-    private static double random(double from, double to) {
-        return Math.random() * (to-from) + from;
-    }
-
     private String currentUserName() {
         return container.getUser().getName();
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/5eb556b1/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
index c57a1b4..b3a77b6 100644
--- a/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
+++ b/example/application/quickstart_wicket_restful_jdo/webapp/src/main/webapp/WEB-INF/isis.properties
@@ -185,6 +185,7 @@ isis.services = \
                 org.apache.isis.applib.services.command.CommandContext,\
                 org.apache.isis.applib.annotation.Bulk$InteractionContext,\
                 org.apache.isis.applib.services.scratchpad.Scratchpad,\
+                org.apache.isis.applib.services.queryresultscache.QueryResultsCache,\
                 \
                 # JDO implementation of the CommandService, \
                 org.apache.isis.objectstore.jdo.applib.service.command.CommandServiceJdo,\