You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2013/10/09 00:10:14 UTC
[2/2] git commit: ISIS-559: Bulk.InteractionContext.current.get()
ISIS-559: Bulk.InteractionContext.current.get()
- provide information about the context in which a @Bulk action is invoked.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/96f4156a
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/96f4156a
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/96f4156a
Branch: refs/heads/master
Commit: 96f4156ab7444ef4b220434b589fca7c3d5be8b5
Parents: e6297bd
Author: Dan Haywood <da...@apache.org>
Authored: Tue Oct 8 23:09:58 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Tue Oct 8 23:09:58 2013 +0100
----------------------------------------------------------------------
.../ajaxtable/BulkActionsLinkFactory.java | 37 +++++++---
.../org/apache/isis/applib/annotation/Bulk.java | 75 ++++++++++++++++++++
.../invoke/ActionInvocationFacetViaMethod.java | 20 +++++-
.../dom/src/main/java/dom/todo/ToDoItem.java | 15 +++-
.../test/java/dom/todo/ToDoTest_completed.java | 9 ++-
.../integration/glue/todoitem/ToDoItemGlue.java | 18 +++--
6 files changed, 159 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/96f4156a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
index 8b13760..e750c5c 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
@@ -19,15 +19,21 @@
package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
import org.apache.wicket.markup.html.link.AbstractLink;
import org.apache.wicket.markup.html.link.Link;
+import org.apache.isis.applib.annotation.Bulk;
+import org.apache.isis.applib.annotation.Bulk.InteractionContext;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
@@ -36,6 +42,8 @@ import org.apache.isis.viewer.wicket.model.mementos.ActionMemento;
import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
import org.apache.isis.viewer.wicket.model.models.ActionModel;
import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
+import org.apache.isis.viewer.wicket.model.util.MementoFunctions;
+import org.apache.isis.viewer.wicket.model.util.ObjectAdapterFunctions;
import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
@@ -62,16 +70,29 @@ final class BulkActionsLinkFactory implements CssMenuLinkFactory {
@Override
public void onClick() {
final ObjectAction objectAction = actionMemento.getAction();
-
- for(ObjectAdapterMemento entityAdapterMemento: model.getToggleMementosList()) {
- // REVIEW: have disabled concurrency checking here...
- final ObjectAdapter entityAdapter = entityAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
- int numParameters = objectAction.getParameterCount();
- if(numParameters != 0) {
- return;
+ try {
+ final List<ObjectAdapterMemento> toggleMementosList = model.getToggleMementosList();
+
+ // REVIEW: have disabled concurrency checking here...
+ final Iterable<ObjectAdapter> toggledAdapters = Iterables.transform(toggleMementosList, ObjectAdapterFunctions.fromMemento());
+
+ final List<Object> domainObjects = Lists.newArrayList(Iterables.transform(toggledAdapters, ObjectAdapter.Functions.getObject()));
+ final Bulk.InteractionContext interactionContext = new Bulk.InteractionContext(domainObjects);
+ Bulk.InteractionContext.current.set(interactionContext);
+
+ int i=0;
+ for(final ObjectAdapter adapter : toggledAdapters) {
+
+ int numParameters = objectAction.getParameterCount();
+ if(numParameters != 0) {
+ return;
+ }
+ interactionContext.setIndex(i++);
+ objectAction.execute(adapter, new ObjectAdapter[]{});
}
- objectAction.execute(entityAdapter, new ObjectAdapter[]{});
+ } finally {
+ Bulk.InteractionContext.current.set(null);
}
model.clearToggleMementosList();
http://git-wip-us.apache.org/repos/asf/isis/blob/96f4156a/core/applib/src/main/java/org/apache/isis/applib/annotation/Bulk.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/Bulk.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/Bulk.java
index c2e1ffb..8a35466 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/Bulk.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Bulk.java
@@ -24,6 +24,8 @@ import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import java.util.Arrays;
+import java.util.List;
/**
* Indicates the (entity) action should be used only against many objects
@@ -46,4 +48,77 @@ import java.lang.annotation.Target;
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Bulk {
+
+ public static class InteractionContext {
+
+ /**
+ * Intended only to be set only by the framework.
+ *
+ * <p>
+ * Will be populated while a bulk action is being invoked.
+ *
+ * <p>
+ * <b>Note</b>: the original design was for this field to be defined within {@link Bulk}. However,
+ * this <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6982543">javac bug</a> unfortunately
+ * means that this field must live outside the annotation.
+ */
+ public static final ThreadLocal<InteractionContext> current = new ThreadLocal<InteractionContext>();
+
+ private final List<Object> domainObjects;
+ private final int size;
+
+ private int index;
+
+ public InteractionContext(Object... domainObjects) {
+ this(Arrays.asList(domainObjects));
+ }
+
+ public InteractionContext(List<Object> domainObjects) {
+ this.domainObjects = domainObjects;
+ this.size = domainObjects.size();
+ }
+
+ public List<Object> getDomainObjects() {
+ return domainObjects;
+ }
+
+ /**
+ * Will be a value in range [0, {@link #getSize() size}).
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * <b>NOT API</b>: intended to be called only by the framework.
+ */
+ public void setIndex(int index) {
+ this.index = index;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public boolean isFirst() {
+ return this.index == 0;
+ }
+
+ public boolean isLast() {
+ return this.index == (size-1);
+ }
+
+ /**
+ * @param runnable
+ */
+ public static void with(Runnable runnable, Object... domainObjects) {
+ try {
+ Bulk.InteractionContext.current.set(new Bulk.InteractionContext(domainObjects));
+ runnable.run();
+ } finally {
+ Bulk.InteractionContext.current.set(null);
+ }
+ }
+
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/96f4156a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
index ceb8c6c..7a9ab55 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/invoke/ActionInvocationFacetViaMethod.java
@@ -27,6 +27,8 @@ import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.isis.applib.annotation.Bulk;
+import org.apache.isis.applib.annotation.Bulk.InteractionContext;
import org.apache.isis.core.commons.lang.ThrowableExtensions;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
@@ -39,6 +41,7 @@ import org.apache.isis.core.metamodel.facets.typeof.ElementSpecificationProvider
import org.apache.isis.core.metamodel.facets.typeof.TypeOfFacet;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.ReflectiveActionException;
+import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet;
public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstract implements ImperativeFacet {
@@ -92,7 +95,22 @@ public class ActionInvocationFacetViaMethod extends ActionInvocationFacetAbstrac
}
final Object object = unwrap(inObject);
- final Object result = method.invoke(object, executionParameters);
+
+ final Object result;
+
+ final BulkFacet bulkFacet = getFacetHolder().getFacet(BulkFacet.class);
+ if(bulkFacet != null && Bulk.InteractionContext.current.get() == null) {
+ // make sure that the Bulk interaction context is set if not already
+ try {
+ Bulk.InteractionContext.current.set(new InteractionContext(object));
+ result = method.invoke(object, executionParameters);
+ } finally {
+ Bulk.InteractionContext.current.set(null);
+ }
+ } else {
+ result = method.invoke(object, executionParameters);
+ }
+
if (LOG.isDebugEnabled()) {
LOG.debug(" action result " + result);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/96f4156a/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 a73b604..d253850 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
@@ -43,10 +43,10 @@ import org.apache.isis.applib.annotation.Audited;
import org.apache.isis.applib.annotation.AutoComplete;
import org.apache.isis.applib.annotation.Bookmarkable;
import org.apache.isis.applib.annotation.Bulk;
+import org.apache.isis.applib.annotation.Bulk.InteractionContext;
import org.apache.isis.applib.annotation.CssClass;
import org.apache.isis.applib.annotation.Disabled;
import org.apache.isis.applib.annotation.Hidden;
-import org.apache.isis.applib.annotation.MaxLength;
import org.apache.isis.applib.annotation.MinLength;
import org.apache.isis.applib.annotation.MultiLine;
import org.apache.isis.applib.annotation.Named;
@@ -311,6 +311,18 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
@CssClass("x-highlight")
public ToDoItem completed() {
setComplete(true);
+
+ // demonstrating the use of ...
+ final InteractionContext ctxt = InteractionContext.current.get();
+ @SuppressWarnings("unused")
+ List<Object> allObjects = ctxt.getDomainObjects();
+
+ LOG.debug("completed: "
+ + ctxt.getIndex() +
+ " [" + ctxt.getSize() + "]"
+ + (ctxt.isFirst() ? " (first)" : "")
+ + (ctxt.isLast() ? " (last)" : ""));
+
return this;
}
// disable action dependent on state of object
@@ -323,6 +335,7 @@ public class ToDoItem implements Comparable<ToDoItem> /*, Locatable*/ { // GMAP3
@Bulk
public ToDoItem notYetCompleted() {
setComplete(false);
+
return this;
}
// disable action dependent on state of object
http://git-wip-us.apache.org/repos/asf/isis/blob/96f4156a/example/application/quickstart_wicket_restful_jdo/dom/src/test/java/dom/todo/ToDoTest_completed.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/dom/src/test/java/dom/todo/ToDoTest_completed.java b/example/application/quickstart_wicket_restful_jdo/dom/src/test/java/dom/todo/ToDoTest_completed.java
index 07f53cb..b0884ea 100644
--- a/example/application/quickstart_wicket_restful_jdo/dom/src/test/java/dom/todo/ToDoTest_completed.java
+++ b/example/application/quickstart_wicket_restful_jdo/dom/src/test/java/dom/todo/ToDoTest_completed.java
@@ -22,6 +22,8 @@ import static org.junit.Assert.assertThat;
import org.junit.Before;
import org.junit.Test;
+import org.apache.isis.applib.annotation.Bulk;
+
public class ToDoTest_completed {
private ToDoItem toDoItem;
@@ -38,7 +40,12 @@ public class ToDoTest_completed {
assertThat(toDoItem.disableCompleted(), is(nullValue()));
// when
- toDoItem.completed();
+ Bulk.InteractionContext.with(new Runnable() {
+ @Override
+ public void run() {
+ toDoItem.completed();
+ }
+ }, toDoItem);
// then
assertThat(toDoItem.isComplete(), is(true));
http://git-wip-us.apache.org/repos/asf/isis/blob/96f4156a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
index 000674c..a8b18ee 100644
--- a/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
+++ b/example/application/quickstart_wicket_restful_jdo/integtests/src/test/java/integration/glue/todoitem/ToDoItemGlue.java
@@ -35,6 +35,7 @@ import dom.todo.ToDoItems;
import org.jmock.Expectations;
import org.junit.Assert;
+import org.apache.isis.applib.annotation.Bulk;
import org.apache.isis.core.specsupport.scenarios.InMemoryDB;
import org.apache.isis.core.specsupport.specs.CukeGlueAbstract;
@@ -71,8 +72,19 @@ public class ToDoItemGlue extends CukeGlueAbstract {
@When("^mark the item as complete$")
public void mark_it_as_complete() throws Throwable {
- ToDoItem toDoItem = getVar(null, "toDoItem", ToDoItem.class);
- wrap(toDoItem).completed();
+ final ToDoItem toDoItem = getVar(null, "toDoItem", ToDoItem.class);
+ if(supportsMocks()) {
+ Bulk.InteractionContext.with(new Runnable(){
+ @Override
+ public void run() {
+ toDoItem.completed();
+ }
+ }, toDoItem);
+ } else {
+ // can just call directly;
+ // framework will take care of setting the Bulk.InteractionContext.
+ wrap(toDoItem).completed();
+ }
}
@Then("^the item is no longer listed as incomplete$")
@@ -81,8 +93,6 @@ public class ToDoItemGlue extends CukeGlueAbstract {
whetherNotYetCompletedContains(toDoItem, false);
}
-
-
@Given("^.*completed .*item$")
public void a_completed_ToDo_item() throws Throwable {
if(supportsMocks()) {