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 2018/02/09 23:59:16 UTC
[isis] 02/02: ISIS-1585: adds support for checkboxes in parented
collections, to act as the defaults for any associated actions.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git
commit 26e84ce74c9260ac5f9ec0fac9c8d919743e9e4f
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Fri Feb 9 23:21:42 2018 +0000
ISIS-1585: adds support for checkboxes in parented collections, to act as the defaults for any associated actions.
---
.../guides/rgant/_rgant-Action_associateWith.adoc | 25 +++-
...ActionParameterDefaultsFacetViaToggleBoxes.java | 63 ++++++++++
...arameterDefaultsFacetViaToggleBoxesFactory.java | 127 +++++++++++++++++++++
.../core/metamodel/spec/feature/ObjectAction.java | 49 ++++++++
.../spec/feature/ObjectActionParameter.java | 30 +++++
.../metamodel/specloader/SpecificationLoader.java | 34 ++++--
.../dflt/ProgrammingModelFacetsJava5.java | 7 ++
.../background/CommandExecutorServiceDefault.java | 3 +-
.../system/session/IsisSessionFactoryBuilder.java | 2 +-
.../viewer/wicket/model/models/ActionPrompt.java | 6 +
.../wicket/model/models/EntityCollectionModel.java | 3 +-
.../model/models/ToggledMementosProvider.java | 13 +++
.../entityactions/EntityActionLinkFactory.java | 8 +-
.../actionmenu/entityactions/LinkAndLabelUtil.java | 12 +-
.../actionmenu/serviceactions/CssMenuItem.java | 2 +-
.../serviceactions/ServiceActionLinkFactory.java | 7 +-
.../actionprompt/ActionPromptModalWindow.java | 2 +
.../collection/AssociatedWithActionsHelper.java | 87 ++++++++++++++
.../ui/components/collection/CollectionPanel.java | 99 +++++++++++++++-
.../collection/bulk/BulkActionsHelper.java | 56 +++++----
.../collection/bulk/BulkActionsLinkFactory.java | 4 +-
.../collection/bulk/BulkActionsProvider.java | 6 +-
.../CollectionContentsAsAjaxTablePanel.java | 2 +-
.../StandaloneCollectionPanel.java | 42 ++++---
.../components/widgets/bootstrap/ModalDialog.java | 10 ++
.../widgets/linkandlabel/ActionLinkFactory.java | 5 +-
.../linkandlabel/ActionLinkFactoryAbstract.java | 78 ++++++++++++-
.../viewer/wicket/ui/pages/bootstrap-overrides.css | 5 +
28 files changed, 705 insertions(+), 82 deletions(-)
diff --git a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_associateWith.adoc b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_associateWith.adoc
index 913d478..38d0c94 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_associateWith.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgant/_rgant-Action_associateWith.adoc
@@ -22,7 +22,7 @@ public class Order {
public Order addItem(Product p, int quantity) { ... }
@Action(associateWith="items:2")
- public Order removeItem(Product p, int quantity) { ... }
+ public Order removeItem(OrderItem item) { ... }
...
}
----
@@ -36,3 +36,26 @@ In the user interface associated actions are rendered close to the member to whi
The same effect can be accomplished using `@MemberOrder` or with the `.layout.xml` file.
====
+
+== Collection Parameters
+
+If the action that has collection parameters is associated with a collection, then the Wicket viewer will render the collection with checkboxes, and these checkboxes can be used to select the items of the action parameter.
+
+For example, suppose we have a "removeItems(...)" action:
+
+[source,java]
+----
+public class Order {
+
+ @Collection
+ SortedSet<OrderItem> getItems() { ... }
+
+ ...
+
+ @Action(associateWith="items:2")
+ public Order removeItems(SortedSet<OrderItem> items) { ... }
+ public SortedSet<OrderItem> choices0RemoveItems() { return getItems(); }
+}
+----
+
+The Wicket viewer will then render the "items" collection with checkboxes, and any selected items will be used as the pre-selected set of items if the action is invoked.
\ No newline at end of file
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/togglebox/ActionParameterDefaultsFacetViaToggleBoxes.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/togglebox/ActionParameterDefaultsFacetViaToggleBoxes.java
new file mode 100644
index 0000000..f9ad50e
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/togglebox/ActionParameterDefaultsFacetViaToggleBoxes.java
@@ -0,0 +1,63 @@
+/*
+ * 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.param.defaults.togglebox;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.apache.isis.applib.ApplicationException;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.param.defaults.ActionParameterDefaultsFacetAbstract;
+
+public class ActionParameterDefaultsFacetViaToggleBoxes extends ActionParameterDefaultsFacetAbstract {
+
+ private static ThreadLocal<List<Object>> selectedPojos = new ThreadLocal<List<Object>>() {
+ @Override protected List<Object> initialValue() {
+ return Collections.emptyList();
+ }
+ };
+
+ public interface SerializableRunnable<T> extends Callable<T>, Serializable {}
+
+ public static <T> T withSelected(final List<Object> objects, final SerializableRunnable<T> callable) {
+ try {
+ selectedPojos.set(objects);
+ return callable.call();
+ } catch (Exception e) {
+ throw new ApplicationException(e);
+ } finally {
+ selectedPojos.set(Collections.emptyList());
+ }
+ }
+
+ public ActionParameterDefaultsFacetViaToggleBoxes(final FacetHolder holder) {
+ super(holder);
+ }
+
+ @Override
+ public Object getDefault(final ObjectAdapter target, List<ObjectAdapter> argumentsIfAvailable) {
+ return selectedPojos.get();
+ }
+
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/togglebox/ActionParameterDefaultsFacetViaToggleBoxesFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/togglebox/ActionParameterDefaultsFacetViaToggleBoxesFactory.java
new file mode 100644
index 0000000..3af6f2b
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/defaults/togglebox/ActionParameterDefaultsFacetViaToggleBoxesFactory.java
@@ -0,0 +1,127 @@
+/*
+ * 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.param.defaults.togglebox;
+
+import java.util.List;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategoryProvider;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+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.services.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+
+/**
+ * Sets up all the {@link Facet}s for an action in a single shot.
+ */
+public class ActionParameterDefaultsFacetViaToggleBoxesFactory extends FacetFactoryAbstract {
+
+ private DeploymentCategoryProvider deploymentCategoryProvider;
+
+ /**
+ * Note that the {@link Facet}s registered are the generic ones from
+ * noa-architecture (where they exist)
+ */
+ public ActionParameterDefaultsFacetViaToggleBoxesFactory() {
+ super(ImmutableList.of(FeatureType.OBJECT_POST_PROCESSING));
+ }
+
+ @Override
+ public void process(final ProcessClassContext processClassContext) {
+ final ObjectSpecification objectSpecification = getSpecificationLoader()
+ .loadSpecification(processClassContext.getCls());
+ postProcess(objectSpecification);
+
+ }
+
+ /**
+ * NOT API.
+ * Called as special case in SpecificationLoader.
+ */
+ public void postProcess(final ObjectSpecification objectSpecification) {
+
+ // all the actions of this type
+ final List<ActionType> actionTypes = inferActionTypes();
+ List<ObjectAction> objectActions = objectSpecification.getObjectActions(actionTypes, Contributed.INCLUDED, Filters.<ObjectAction>any());
+
+ // and all the collections of this type
+ final List<OneToManyAssociation> oneToManyAssociations =
+ objectSpecification.getCollections(Contributed.INCLUDED);
+
+ // for each collection, ...
+ for (final OneToManyAssociation otma : oneToManyAssociations) {
+
+ // ... see if any of its actions has a collection parameter of the same type
+ //
+ // eg Order#getItems() and Order#removeItems(List<OrderItem>)
+ //
+ final String collectionId = otma.getId();
+ final ObjectSpecification specification = otma.getSpecification();
+ final ImmutableList<ObjectAction> actions = FluentIterable.from(objectActions)
+ .filter(
+ ObjectAction.Predicates.associatedWithAndWithCollectionParameterFor(collectionId, specification))
+ .toList();
+
+ //
+ // ... for the matching actions, install the default facet populated using toggle boxes
+ //
+ final ObjectActionParameter.Predicates.CollectionParameter whetherCollectionParamOfType =
+ new ObjectActionParameter.Predicates.CollectionParameter(specification);
+ for (final ObjectAction action : actions) {
+ final List<ObjectActionParameter> parameters = action.getParameters();
+ final ImmutableList<ObjectActionParameter> collectionParams = FluentIterable.from(parameters)
+ .filter(whetherCollectionParamOfType).toList();
+ for (final ObjectActionParameter collectionParam : collectionParams) {
+ FacetUtil.addFacet(new ActionParameterDefaultsFacetViaToggleBoxes(collectionParam));
+ }
+ }
+ }
+ }
+
+ private List<ActionType> inferActionTypes() {
+ final List<ActionType> actionTypes = Lists.newArrayList();
+ actionTypes.add(ActionType.USER);
+ final DeploymentCategory deploymentCategory = deploymentCategoryProvider.getDeploymentCategory();
+ if ( !deploymentCategory.isProduction()) {
+ actionTypes.add(ActionType.PROTOTYPE);
+ }
+ return actionTypes;
+ }
+
+
+ @Override
+ public void setServicesInjector(final ServicesInjector servicesInjector) {
+ super.setServicesInjector(servicesInjector);
+ deploymentCategoryProvider = servicesInjector.getDeploymentCategoryProvider();
+ }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
index 6ec249d..e2b8bd1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectAction.java
@@ -21,8 +21,12 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
+import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import org.apache.isis.applib.Identifier;
@@ -413,6 +417,51 @@ public interface ObjectAction extends ObjectMember {
public static Predicate<ObjectAction> memberOrderOf(ObjectAssociation association) {
return org.apache.isis.applib.filter.Filters.asPredicate(Filters.memberOrderOf(association));
}
+
+ public static Predicate<ObjectAction> associatedWithAndWithCollectionParameterFor(
+ final String collectionName,
+ final ObjectSpecification collectionTypeOfSpec) {
+
+ return com.google.common.base.Predicates.and(
+ new AssociatedWith(collectionName),
+ new HasParameterMatching(
+ new ObjectActionParameter.Predicates.CollectionParameter(collectionTypeOfSpec)
+ )
+ );
+ }
+
+ public static class AssociatedWith implements Predicate<ObjectAction> {
+ private final String memberNameAssociatedWith;
+ public AssociatedWith(final String memberNameAssociatedWith) {
+ this.memberNameAssociatedWith = memberNameAssociatedWith;
+ }
+
+ @Override
+ public boolean apply(final ObjectAction objectAction) {
+ final MemberOrderFacet memberOrderFacet = objectAction.getFacet(MemberOrderFacet.class);
+ if(memberOrderFacet == null) {
+ return false;
+ }
+ final String name = memberNameAssociatedWith;
+ final String memberOrderName = memberOrderFacet.untranslatedName();
+ return name != null && memberOrderName != null &&
+ Objects.equal(name.toLowerCase(), memberOrderName.toLowerCase());
+ }
+ }
+
+ public static class HasParameterMatching implements Predicate<ObjectAction> {
+ private final Predicate<ObjectActionParameter> parameterPredicate;
+ public HasParameterMatching(final Predicate<ObjectActionParameter> parameterPredicate) {
+ this.parameterPredicate = parameterPredicate;
+ }
+
+ @Override
+ public boolean apply(@Nullable final ObjectAction objectAction) {
+ return FluentIterable
+ .from(objectAction.getParameters())
+ .anyMatch(parameterPredicate);
+ }
+ }
}
//endregion
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java
index 0ddbec1..fce2438 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionParameter.java
@@ -19,13 +19,17 @@
package org.apache.isis.core.metamodel.spec.feature;
+import javax.annotation.Nullable;
+
import com.google.common.base.Function;
+import com.google.common.base.Predicate;
import org.apache.isis.applib.filter.Filter;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.consent.InteractionInitiatedBy;
import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
import org.apache.isis.core.metamodel.interactions.ActionArgValidityContext;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
/**
* Analogous to {@link ObjectAssociation}.
@@ -155,4 +159,30 @@ public interface ObjectActionParameter extends ObjectFeature, CurrentHolder {
private Functions(){}
}
+
+ public static class Predicates {
+ private Predicates(){}
+
+ public static class CollectionParameter implements Predicate<ObjectActionParameter> {
+
+ private final ObjectSpecification elementSpecification;
+
+ public CollectionParameter(final ObjectSpecification elementSpecification) {
+ this.elementSpecification = elementSpecification;
+ }
+
+ @Override
+ public boolean apply(@Nullable final ObjectActionParameter objectActionParameter) {
+ if (!(objectActionParameter instanceof OneToManyActionParameter)) {
+ return false;
+ }
+
+ final OneToManyActionParameter otmap =
+ (OneToManyActionParameter) objectActionParameter;
+ final ObjectSpecification specification = otmap.getSpecification();
+ final ObjectSpecification typeOfSpecification = this.elementSpecification;
+ return specification == typeOfSpecification;
+ }
+ }
+ }
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index 07b06bb..8142104 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -42,6 +42,7 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
import org.apache.isis.core.metamodel.facets.FacetFactory;
import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet;
import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
+import org.apache.isis.core.metamodel.facets.param.defaults.togglebox.ActionParameterDefaultsFacetViaToggleBoxesFactory;
import org.apache.isis.core.metamodel.layoutmetadata.LayoutMetadataReader;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
import org.apache.isis.core.metamodel.services.ServicesInjector;
@@ -358,9 +359,6 @@ public class SpecificationLoader implements ApplicationScopedComponent {
return spec;
}
final ObjectSpecification specification = createSpecification(type, natureOfService);
- if (specification == null) {
- throw new IsisException("Failed to create specification for class " + typeName);
- }
// put into the cache prior to introspecting, to prevent
// infinite loops
@@ -439,17 +437,18 @@ public class SpecificationLoader implements ApplicationScopedComponent {
final ObjectSpecificationAbstract.IntrospectionState introspectionState = specSpi.getIntrospectionState();
// REVIEW: can't remember why this is done in multiple passes, could it be simplified?
- if (introspectionState == ObjectSpecificationAbstract.IntrospectionState.NOT_INTROSPECTED) {
+ switch (introspectionState) {
+ case NOT_INTROSPECTED:
specSpi.setIntrospectionState(ObjectSpecificationAbstract.IntrospectionState.BEING_INTROSPECTED);
introspect(specSpi);
-
- } else if (introspectionState == ObjectSpecificationAbstract.IntrospectionState.BEING_INTROSPECTED) {
-
+ break;
+ case BEING_INTROSPECTED:
introspect(specSpi);
-
- } else if (introspectionState == ObjectSpecificationAbstract.IntrospectionState.INTROSPECTED) {
+ break;
+ case INTROSPECTED:
// nothing to do
+ break;
}
return spec;
}
@@ -461,6 +460,23 @@ public class SpecificationLoader implements ApplicationScopedComponent {
}
+ public void postProcess() {
+
+ //
+ // HMM. Not possible to add this as a facet factory, because of
+ // inifinite loop (can't lookup actions of spec until fully processed).
+ // so, instead, calling as a one-off special-case in SpecificationLoader
+ //
+ final ActionParameterDefaultsFacetViaToggleBoxesFactory factory =
+ new ActionParameterDefaultsFacetViaToggleBoxesFactory();
+ factory.setServicesInjector(getServicesInjector());
+
+ final Collection<ObjectSpecification> specs = allSpecifications();
+ for (final ObjectSpecification spec : specs) {
+ factory.postProcess(spec);
+ }
+ }
+
//endregion
//region > allSpecifications
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 4435bca..302a8f8 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
@@ -280,6 +280,13 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
addFactory(new ActionDefaultsFacetViaMethodFactory());
addFactory(new ActionParameterDefaultsFacetViaMethodFactory());
+ //
+ // HMM. Not possible to add this as a facet factory, because of
+ // inifinite loop (can't lookup actions of spec until fully processed).
+ // so, instead, calling as a one-off special-case in SpecificationLoader
+ //
+ //addFactory(new ActionParameterDefaultsFacetViaToggleBoxesFactory());
+
// members in general
addFactory(new NamedFacetStaticMethodFactory());
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java
index 63737b5..cb29cf0 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/services/background/CommandExecutorServiceDefault.java
@@ -148,11 +148,10 @@ public class CommandExecutorServiceDefault implements CommandExecutorService {
// thrown then we would have a command with only completedAt, which is inconsistent.
// Therefore instead we copy down from the backgroundInteraction (similar to how we populate the
// completedAt at the end)
- final Interaction.Execution priorExecution = interaction.getPriorExecution();
final Interaction.Execution currentExecution = interaction.getCurrentExecution();
final Timestamp startedAt = currentExecution != null
- ? priorExecution.getStartedAt()
+ ? currentExecution.getStartedAt()
: clockService.nowAsJavaSqlTimestamp();
commandWithDto.setStartedAt(startedAt);
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java
index c834152..5c9e0b4 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionFactoryBuilder.java
@@ -212,6 +212,7 @@ public class IsisSessionFactoryBuilder {
new Runnable() {
@Override
public void run() {
+ specificationLoader.postProcess();
try {
specificationLoader.validateAndAssert();
@@ -223,7 +224,6 @@ public class IsisSessionFactoryBuilder {
}
IsisContext.setMetaModelInvalidException(ex);
}
-
}
}
);
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPrompt.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPrompt.java
index 0e2747a..f2e03a7 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPrompt.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ActionPrompt.java
@@ -68,4 +68,10 @@ public interface ActionPrompt extends Serializable {
* @param target The current Ajax request handler
*/
void closePrompt(AjaxRequestTarget target);
+
+ public interface CloseHandler extends Serializable {
+ public void close(final AjaxRequestTarget target);
+ }
+
+ void setOnClose(CloseHandler closeHandler);
}
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
index 923980a..a49e365 100644
--- a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/EntityCollectionModel.java
@@ -487,7 +487,7 @@ public class EntityCollectionModel extends ModelAbstract<List<ObjectAdapter>> im
}
public List<ObjectAdapterMemento> getToggleMementosList() {
- return Collections.unmodifiableList(this.toggledMementosList);
+ return Collections.unmodifiableList(Lists.newArrayList(this.toggledMementosList));
}
public void clearToggleMementosList() {
@@ -495,6 +495,7 @@ public class EntityCollectionModel extends ModelAbstract<List<ObjectAdapter>> im
}
public void addLinkAndLabels(List<LinkAndLabel> linkAndLabels) {
+ this.linkAndLabels.clear();
this.linkAndLabels.addAll(linkAndLabels);
}
diff --git a/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ToggledMementosProvider.java b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ToggledMementosProvider.java
new file mode 100644
index 0000000..eb1ef2e
--- /dev/null
+++ b/core/viewer-wicket-model/src/main/java/org/apache/isis/viewer/wicket/model/models/ToggledMementosProvider.java
@@ -0,0 +1,13 @@
+package org.apache.isis.viewer.wicket.model.models;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+
+public interface ToggledMementosProvider extends Serializable {
+ List<ObjectAdapterMemento> getToggles();
+ void clearToggles(final AjaxRequestTarget target);
+}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
index bb4c32c..e680565 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/EntityActionLinkFactory.java
@@ -27,6 +27,7 @@ import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
import org.apache.isis.viewer.wicket.model.models.EntityModel;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.model.models.ToggledMementosProvider;
import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract;
public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
@@ -42,7 +43,8 @@ public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
@Override
public LinkAndLabel newLink(
final ObjectAction objectAction,
- final String linkId) {
+ final String linkId,
+ final ToggledMementosProvider toggledMementosProviderIfAny) {
final ObjectAdapter objectAdapter = this.targetEntityModel.load(ConcurrencyChecking.NO_CHECK);
@@ -65,7 +67,7 @@ public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
// }
- final AbstractLink link = newLink(linkId, objectAction);
+ final AbstractLink link = newLink(linkId, objectAction, toggledMementosProviderIfAny);
// similarly for whether disabled, done at point of rendering
@@ -84,4 +86,6 @@ public final class EntityActionLinkFactory extends ActionLinkFactoryAbstract {
}
+
+
}
\ No newline at end of file
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
index 6d8c9af..441449c 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/entityactions/LinkAndLabelUtil.java
@@ -33,6 +33,7 @@ import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
import org.apache.isis.viewer.wicket.model.models.EntityModel;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.model.models.ToggledMementosProvider;
import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactory;
public final class LinkAndLabelUtil {
@@ -76,6 +77,15 @@ public final class LinkAndLabelUtil {
final List<ObjectAction> objectActions,
final ScalarModel scalarModelForAssociationIfAny) {
+ return asActionLinksForAdditionalLinksPanel(parentEntityModel, objectActions, scalarModelForAssociationIfAny, null);
+ }
+
+ public static List<LinkAndLabel> asActionLinksForAdditionalLinksPanel(
+ final EntityModel parentEntityModel,
+ final List<ObjectAction> objectActions,
+ final ScalarModel scalarModelForAssociationIfAny,
+ final ToggledMementosProvider toggledMementosProviderIfAny) {
+
final ActionLinkFactory linkFactory = new EntityActionLinkFactory(parentEntityModel, scalarModelForAssociationIfAny);
return FluentIterable.from(objectActions)
@@ -83,7 +93,7 @@ public final class LinkAndLabelUtil {
@Override
public LinkAndLabel apply(ObjectAction objectAction) {
- return linkFactory.newLink(objectAction, AdditionalLinksPanel.ID_ADDITIONAL_LINK);
+ return linkFactory.newLink(objectAction, AdditionalLinksPanel.ID_ADDITIONAL_LINK,toggledMementosProviderIfAny);
}
})
.filter(Predicates.<LinkAndLabel>notNull())
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
index 877b4ea..41e2f9a 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/CssMenuItem.java
@@ -375,7 +375,7 @@ class CssMenuItem implements Serializable {
final String descriptionIfAny = describedAsFacet != null ? describedAsFacet.value() : null;
// build the link
- final LinkAndLabel linkAndLabel = actionLinkFactory.newLink(objectAction, PageAbstract.ID_MENU_LINK);
+ final LinkAndLabel linkAndLabel = actionLinkFactory.newLink(objectAction, PageAbstract.ID_MENU_LINK, null);
if (linkAndLabel == null) {
// can only get a null if invisible, so this should not happen given the visibility guard above
return null;
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
index e96bc54..f36f540 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionmenu/serviceactions/ServiceActionLinkFactory.java
@@ -26,6 +26,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChec
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.ToggledMementosProvider;
import org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel.ActionLinkFactoryAbstract;
class ServiceActionLinkFactory extends ActionLinkFactoryAbstract {
@@ -38,11 +39,13 @@ class ServiceActionLinkFactory extends ActionLinkFactoryAbstract {
@Override
public LinkAndLabel newLink(
- final ObjectAction objectAction, final String linkId) {
+ final ObjectAction objectAction,
+ final String linkId,
+ final ToggledMementosProvider toggledMementosProviderIfAny) {
ObjectAdapter objectAdapter = this.targetEntityModel.load(ConcurrencyChecking.NO_CHECK);
- final AbstractLink link = newLink(linkId, objectAction);
+ final AbstractLink link = newLink(linkId, objectAction, toggledMementosProviderIfAny);
return newLinkAndLabel(objectAdapter, objectAction, link, null);
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptModalWindow.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptModalWindow.java
index 782a3e9..b3880c9 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptModalWindow.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/actionprompt/ActionPromptModalWindow.java
@@ -16,6 +16,7 @@
*/
package org.apache.isis.viewer.wicket.ui.components.actionprompt;
+import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.core.request.handler.IPartialPageRequestHandler;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.OnDomReadyHeaderItem;
@@ -66,4 +67,5 @@ public class ActionPromptModalWindow extends ModalDialog<Void> {
response.render(OnDomReadyHeaderItem.forScript(
String.format("Wicket.Event.publish(Isis.Topic.FOCUS_FIRST_PARAMETER, '%s')", getMarkupId())));
}
+
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
new file mode 100644
index 0000000..65bf609
--- /dev/null
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/AssociatedWithActionsHelper.java
@@ -0,0 +1,87 @@
+/*
+ * 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.viewer.wicket.ui.components.collection;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+import org.apache.isis.applib.filter.Filters;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.deployment.DeploymentCategory;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
+import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
+import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsHelper;
+
+/**
+ * See also {@link BulkActionsHelper}.
+ */
+public class AssociatedWithActionsHelper implements Serializable {
+ private final EntityCollectionModel collectionModel;
+
+ public AssociatedWithActionsHelper(final EntityCollectionModel collectionModel) {
+ this.collectionModel = collectionModel;
+ }
+
+ public List<ObjectAction> getAssociatedActions(final IsisSessionFactory isisSessionFactory) {
+
+ if(collectionModel.isStandalone()) {
+ return Collections.emptyList();
+ }
+ final ObjectSpecification objectSpec = getObjectSpecification(isisSessionFactory);
+
+ final List<ActionType> actionTypes = inferActionTypes(isisSessionFactory);
+ List<ObjectAction> objectActions = objectSpec.getObjectActions(actionTypes, Contributed.INCLUDED, Filters.<ObjectAction>any());
+
+ return FluentIterable.from(objectActions)
+ .filter(ObjectAction.Predicates.associatedWithAndWithCollectionParameterFor(
+ collectionModel.getName(),
+ collectionModel.getTypeOfSpecification()))
+ .toList();
+ }
+
+ private ObjectSpecification getObjectSpecification(final IsisSessionFactory isisSessionFactory) {
+ final ObjectAdapterMemento parentOam = collectionModel.getParentObjectAdapterMemento();
+ final ObjectAdapter parentAdapter = parentOam.getObjectAdapter(
+ AdapterManager.ConcurrencyChecking.NO_CHECK,
+ isisSessionFactory.getCurrentSession().getPersistenceSession(),
+ isisSessionFactory.getSpecificationLoader());
+ return parentAdapter.getSpecification();
+ }
+
+ private static List<ActionType> inferActionTypes(final IsisSessionFactory isisSessionFactory) {
+ final List<ActionType> actionTypes = Lists.newArrayList();
+ actionTypes.add(ActionType.USER);
+ final DeploymentCategory deploymentCategory = isisSessionFactory.getDeploymentCategory();
+ if ( !deploymentCategory.isProduction()) {
+ actionTypes.add(ActionType.PROTOTYPE);
+ }
+ return actionTypes;
+ }
+
+}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
index b479039..cdbf1e5 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/CollectionPanel.java
@@ -19,11 +19,13 @@
package org.apache.isis.viewer.wicket.ui.components.collection;
+import java.io.Serializable;
import java.util.List;
import com.google.common.collect.Lists;
import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.feedback.ComponentFeedbackMessageFilter;
import org.apache.wicket.markup.html.basic.Label;
@@ -31,13 +33,18 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.viewer.wicket.model.common.OnSelectionHandler;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
import org.apache.isis.viewer.wicket.model.models.EntityModel;
+import org.apache.isis.viewer.wicket.model.models.ToggledMementosProvider;
import org.apache.isis.viewer.wicket.ui.ComponentType;
import org.apache.isis.viewer.wicket.ui.components.actionmenu.entityactions.LinkAndLabelUtil;
+import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsProvider;
import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorPanel;
import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorProvider;
+import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
import org.apache.isis.viewer.wicket.ui.components.scalars.ScalarPanelAbstract2;
import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
@@ -47,7 +54,8 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.common.NotificationPanel
* Panel for rendering entity collection; analogous to (any concrete subclass
* of) {@link ScalarPanelAbstract2}.
*/
-public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implements CollectionSelectorProvider {
+public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implements CollectionSelectorProvider,
+ BulkActionsProvider {
private static final long serialVersionUID = 1L;
@@ -57,6 +65,8 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
private Label label;
+ private final AssociatedWithActionsHelper associatedWithActionsHelper;
+
public CollectionPanel(
final String id,
final EntityCollectionModel collectionModel) {
@@ -67,14 +77,22 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
final OneToManyAssociation otma = collectionModel.getCollectionMemento().getCollection(collectionModel.getSpecificationLoader());
final EntityModel entityModel = collectionModel.getEntityModel();
final ObjectAdapter adapter = entityModel.load(AdapterManager.ConcurrencyChecking.NO_CHECK);
-
+
final List<ObjectAction> associatedActions =
ObjectAction.Util.findForAssociation(adapter, otma, getDeploymentCategory());
+ associatedWithActionsHelper = new AssociatedWithActionsHelper(collectionModel);
+
+ final ToggledMementosProvider toggledMementosProvider =
+ new MyToggledMementosProvider(collectionModel, this, this);
+
entityActionLinks.addAll(
- LinkAndLabelUtil.asActionLinksForAdditionalLinksPanel(entityModel, associatedActions, null));
+ LinkAndLabelUtil
+ .asActionLinksForAdditionalLinksPanel(
+ entityModel, associatedActions, null, toggledMementosProvider));
collectionModel.addLinkAndLabels(entityActionLinks);
+
}
@Override
@@ -87,6 +105,8 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
collectionContents = getComponentFactoryRegistry().addOrReplaceComponent(this, ComponentType.COLLECTION_CONTENTS, getModel());
addOrReplace(new NotificationPanel(ID_FEEDBACK, collectionContents, new ComponentFeedbackMessageFilter(collectionContents)));
+
+ setOutputMarkupId(true);
}
public Label createLabel(final String id, final String collectionName) {
@@ -106,6 +126,79 @@ public class CollectionPanel extends PanelAbstract<EntityCollectionModel> implem
public void setSelectorDropdownPanel(CollectionSelectorPanel selectorDropdownPanel) {
this.selectorDropdownPanel = selectorDropdownPanel;
}
+
+ //endregion
+
+ //region > BulkActionsProvider
+ ObjectAdapterToggleboxColumn toggleboxColumn;
+
+ @Override
+ public ObjectAdapterToggleboxColumn getToggleboxColumn() {
+
+ if(toggleboxColumn == null) {
+ final List<ObjectAction> associatedActions =
+ associatedWithActionsHelper.getAssociatedActions(getIsisSessionFactory());
+
+ final EntityCollectionModel entityCollectionModel = getModel();
+ if(associatedActions.isEmpty() || entityCollectionModel.isStandalone()) {
+ return null;
+ }
+
+ toggleboxColumn = new ObjectAdapterToggleboxColumn();
+ final OnSelectionHandler handler = new OnSelectionHandler() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void onSelected(
+ final Component context,
+ final ObjectAdapter selectedAdapter,
+ final AjaxRequestTarget ajaxRequestTarget) {
+ getModel().toggleSelectionOn(selectedAdapter);
+ }
+
+ };
+ toggleboxColumn.setOnSelectionHandler(handler);
+ }
+
+ return toggleboxColumn;
+ }
+
+
+ @Override
+ public void configureBulkActions(final ObjectAdapterToggleboxColumn toggleboxColumn) {
+ }
+
+ private static class MyToggledMementosProvider implements ToggledMementosProvider, Serializable {
+ private final EntityCollectionModel collectionModel;
+ private final BulkActionsProvider bulkActionsProvider;
+ private final CollectionPanel collectionPanel;
+
+ MyToggledMementosProvider(
+ final EntityCollectionModel collectionModel,
+ final BulkActionsProvider bulkActionsProvider,
+ final CollectionPanel collectionPanel) {
+ this.collectionModel = collectionModel;
+ this.bulkActionsProvider = bulkActionsProvider;
+ this.collectionPanel = collectionPanel;
+ }
+
+ @Override
+ public List<ObjectAdapterMemento> getToggles() {
+ return collectionModel.getToggleMementosList();
+ }
+
+ @Override
+ public void clearToggles(final AjaxRequestTarget target) {
+ collectionModel.clearToggleMementosList();
+
+ final ObjectAdapterToggleboxColumn toggleboxColumn = bulkActionsProvider.getToggleboxColumn();
+ toggleboxColumn.clearToggles();
+
+ target.add(collectionPanel);
+ }
+ }
+
//endregion
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java
index 723f85b..39fd75a 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java
@@ -22,8 +22,7 @@ import java.io.Serializable;
import java.util.Collections;
import java.util.List;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
+import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import org.apache.isis.applib.filter.Filters;
@@ -34,52 +33,49 @@ import org.apache.isis.core.metamodel.spec.feature.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
+import org.apache.isis.viewer.wicket.ui.components.collection.AssociatedWithActionsHelper;
+/**
+ * See also {@link AssociatedWithActionsHelper}.
+ */
public class BulkActionsHelper implements Serializable {
- private final EntityCollectionModel model;
+ private final EntityCollectionModel collectionModel;
private static final long serialVersionUID = 1L;
- public BulkActionsHelper(final EntityCollectionModel model) {
- this.model = model;
- }
-
- private EntityCollectionModel getModel() {
- return model;
+ public BulkActionsHelper(final EntityCollectionModel collectionModel) {
+ this.collectionModel = collectionModel;
}
public List<ObjectAction> getBulkActions(final IsisSessionFactory isisSessionFactory) {
- final EntityCollectionModel model = getModel();
- if(model.isParented()) {
+ if(collectionModel.isParented()) {
return Collections.emptyList();
}
- final ObjectSpecification typeSpec = model.getTypeOfSpecification();
-
- List<ObjectAction> objectActions = typeSpec.getObjectActions(ActionType.USER, Contributed.INCLUDED, Filters.<ObjectAction>any());
+ final ObjectSpecification objectSpec = getObjectSpecification(isisSessionFactory);
- final DeploymentCategory deploymentCategory = isisSessionFactory.getDeploymentCategory();
- if ( !deploymentCategory.isProduction()) {
- List<ObjectAction> prototypeActions = typeSpec.getObjectActions(ActionType.PROTOTYPE, Contributed.INCLUDED, Filters.<ObjectAction>any());
- objectActions.addAll(prototypeActions);
- }
+ final List<ActionType> actionTypes = inferActionTypes(isisSessionFactory);
+ List<ObjectAction> objectActions = objectSpec.getObjectActions(actionTypes, Contributed.INCLUDED, Filters.<ObjectAction>any());
- List<ObjectAction> flattenedActions = objectActions;
-
- return Lists.newArrayList(Iterables.filter(flattenedActions, BULK));
+ return FluentIterable.from(objectActions)
+ .filter(ObjectAction.Predicates.bulk())
+ .toList();
}
+ private ObjectSpecification getObjectSpecification(final IsisSessionFactory isisSessionFactory) {
+ return collectionModel.getTypeOfSpecification();
+ }
- @SuppressWarnings("deprecation")
- private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
-
- /**
- * Protected so can be overridden in testing if required.
- */
- protected boolean isDebugMode() {
- return true;
+ private List<ActionType> inferActionTypes(final IsisSessionFactory isisSessionFactory) {
+ final List<ActionType> actionTypes = Lists.newArrayList();
+ actionTypes.add(ActionType.USER);
+ final DeploymentCategory deploymentCategory = isisSessionFactory.getDeploymentCategory();
+ if ( !deploymentCategory.isProduction()) {
+ actionTypes.add(ActionType.PROTOTYPE);
+ }
+ return actionTypes;
}
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
index 4a6a82d..a407aeb 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
@@ -52,6 +52,7 @@ 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.models.ToggledMementosProvider;
import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponse;
import org.apache.isis.viewer.wicket.ui.actionresponse.ActionResultResponseType;
import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
@@ -79,7 +80,8 @@ public final class BulkActionsLinkFactory implements ActionLinkFactory {
@Override
public LinkAndLabel newLink(
final ObjectAction objectAction,
- final String linkId) {
+ final String linkId,
+ final ToggledMementosProvider toggledMementosProviderIfAny) {
final ActionMemento actionMemento = new ActionMemento(objectAction);
final AbstractLink link = new Link<Object>(linkId) {
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java
index 39f2b96..335b8dc 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java
@@ -18,11 +18,13 @@
*/
package org.apache.isis.viewer.wicket.ui.components.collection.bulk;
+import java.io.Serializable;
+
import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
-public interface BulkActionsProvider {
+public interface BulkActionsProvider extends Serializable {
void configureBulkActions(ObjectAdapterToggleboxColumn toggleboxColumn);
- ObjectAdapterToggleboxColumn createToggleboxColumn();
+ ObjectAdapterToggleboxColumn getToggleboxColumn();
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
index 700998f..8093034 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
@@ -90,7 +90,7 @@ public class CollectionContentsAsAjaxTablePanel
ObjectAdapterToggleboxColumn toggleboxColumn = null;
if(bulkActionsProvider != null) {
- toggleboxColumn = bulkActionsProvider.createToggleboxColumn();
+ toggleboxColumn = bulkActionsProvider.getToggleboxColumn();
if(toggleboxColumn != null) {
columns.add(toggleboxColumn);
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
index 242b58a..eba0bb0 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
@@ -138,31 +138,35 @@ public class StandaloneCollectionPanel extends PanelAbstract<EntityCollectionMod
//region > BulkActionsProvider
+ ObjectAdapterToggleboxColumn toggleboxColumn;
+
@Override
- public ObjectAdapterToggleboxColumn createToggleboxColumn() {
+ public ObjectAdapterToggleboxColumn getToggleboxColumn() {
- final List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions(getIsisSessionFactory());
+ if (toggleboxColumn == null) {
+ final List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions(getIsisSessionFactory());
- final EntityCollectionModel entityCollectionModel = getModel();
- if(bulkActions.isEmpty() || entityCollectionModel.isParented()) {
- return null;
- }
+ final EntityCollectionModel entityCollectionModel = getModel();
+ if(bulkActions.isEmpty() || entityCollectionModel.isParented()) {
+ return null;
+ }
- final ObjectAdapterToggleboxColumn toggleboxColumn = new ObjectAdapterToggleboxColumn();
- final OnSelectionHandler handler = new OnSelectionHandler() {
+ toggleboxColumn = new ObjectAdapterToggleboxColumn();
+ final OnSelectionHandler handler = new OnSelectionHandler() {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- @Override
- public void onSelected(
- final Component context,
- final ObjectAdapter selectedAdapter,
- final AjaxRequestTarget ajaxRequestTarget) {
- getModel().toggleSelectionOn(selectedAdapter);
- }
+ @Override
+ public void onSelected(
+ final Component context,
+ final ObjectAdapter selectedAdapter,
+ final AjaxRequestTarget ajaxRequestTarget) {
+ getModel().toggleSelectionOn(selectedAdapter);
+ }
- };
- toggleboxColumn.setOnSelectionHandler(handler);
+ };
+ toggleboxColumn.setOnSelectionHandler(handler);
+ }
return toggleboxColumn;
}
@@ -181,7 +185,7 @@ public class StandaloneCollectionPanel extends PanelAbstract<EntityCollectionMod
List<LinkAndLabel> linkAndLabels = Lists.transform(bulkActions, new Function<ObjectAction, LinkAndLabel>(){
@Override
public LinkAndLabel apply(ObjectAction objectAction) {
- return linkFactory.newLink(objectAction, ID_ADDITIONAL_LINK);
+ return linkFactory.newLink(objectAction, ID_ADDITIONAL_LINK, null);
}
});
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java
index f3a5e07..a0ffd4d 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/bootstrap/ModalDialog.java
@@ -34,6 +34,8 @@ import de.agilecoders.wicket.extensions.markup.html.bootstrap.behavior.Draggable
*/
public class ModalDialog<T> extends Modal<T> implements ActionPrompt {
+ private CloseHandler closeHandlerIfAny;
+
public ModalDialog(String markupId) {
this(markupId, null);
}
@@ -82,6 +84,14 @@ public class ModalDialog<T> extends Modal<T> implements ActionPrompt {
close(target);
}
setVisible(false);
+ if(closeHandlerIfAny != null) {
+ closeHandlerIfAny.close(target);
+ }
+ }
+
+ @Override
+ public void setOnClose(final CloseHandler closeHandlerIfAny) {
+ this.closeHandlerIfAny = closeHandlerIfAny;
}
@Override
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java
index 4dced29..092838a 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactory.java
@@ -20,8 +20,10 @@
package org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel;
import java.io.Serializable;
+
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+import org.apache.isis.viewer.wicket.model.models.ToggledMementosProvider;
public interface ActionLinkFactory extends Serializable {
@@ -31,5 +33,6 @@ public interface ActionLinkFactory extends Serializable {
*/
LinkAndLabel newLink(
final ObjectAction objectAction,
- final String linkId);
+ final String linkId,
+ final ToggledMementosProvider toggledMementosProviderIfAny);
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
index a1ffa24..e705eba 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/linkandlabel/ActionLinkFactoryAbstract.java
@@ -17,8 +17,16 @@
package org.apache.isis.viewer.wicket.ui.components.widgets.linkandlabel;
+import java.util.List;
import java.util.concurrent.Callable;
+import javax.annotation.Nullable;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+
import org.apache.wicket.Application;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.Page;
@@ -29,13 +37,16 @@ import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.isis.applib.annotation.PromptStyle;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
+import org.apache.isis.core.metamodel.facets.param.defaults.togglebox.ActionParameterDefaultsFacetViaToggleBoxes;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.core.runtime.system.session.IsisSessionFactory;
import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettingsAccessor;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+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.ActionPrompt;
import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
@@ -43,6 +54,7 @@ import org.apache.isis.viewer.wicket.model.models.EntityModel;
import org.apache.isis.viewer.wicket.model.models.FormExecutor;
import org.apache.isis.viewer.wicket.model.models.InlinePromptContext;
import org.apache.isis.viewer.wicket.model.models.ScalarModel;
+import org.apache.isis.viewer.wicket.model.models.ToggledMementosProvider;
import org.apache.isis.viewer.wicket.ui.ComponentType;
import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistry;
import org.apache.isis.viewer.wicket.ui.app.registry.ComponentFactoryRegistryAccessor;
@@ -72,7 +84,8 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
protected ActionLink newLink(
final String linkId,
- final ObjectAction action) {
+ final ObjectAction action,
+ final ToggledMementosProvider toggledMementosProviderIfAny) {
final ActionModel actionModel = ActionModel.create(this.targetEntityModel, action);
@@ -80,9 +93,58 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
new ActionLink(linkId, actionModel, action) {
private static final long serialVersionUID = 1L;
- protected void doOnClick(AjaxRequestTarget target) {
+ protected void doOnClick(final AjaxRequestTarget target) {
+
+ if(toggledMementosProviderIfAny != null) {
+
+ final PersistenceSession persistenceSession = getIsisSessionFactory()
+ .getCurrentSession().getPersistenceSession();
+ final SpecificationLoader specificationLoader =
+ getIsisSessionFactory().getSpecificationLoader();
+
+ final List<ObjectAdapterMemento> selectedMementos =
+ toggledMementosProviderIfAny.getToggles();
+
+ final ImmutableList<Object> selectedPojos = FluentIterable.from(selectedMementos)
+ .transform(new Function<ObjectAdapterMemento, Object>() {
+ @Nullable @Override
+ public Object apply(@Nullable final ObjectAdapterMemento input) {
+ if(input == null) {
+ return null;
+ }
+ final ObjectAdapter objectAdapter = input.getObjectAdapter(
+ AdapterManager.ConcurrencyChecking.NO_CHECK,
+ persistenceSession, specificationLoader);
+ return objectAdapter != null ? objectAdapter.getObject() : null;
+ }
+ })
+ .filter(Predicates.notNull())
+ .toList();
+
+ final ActionPrompt actionPrompt = ActionParameterDefaultsFacetViaToggleBoxes.withSelected(
+ selectedPojos,
+ new ActionParameterDefaultsFacetViaToggleBoxes.SerializableRunnable<ActionPrompt>() {
+ public ActionPrompt call() {
+ return performOnClick(target);
+ }
+ }
+ );
+ if(actionPrompt != null) {
+ actionPrompt.setOnClose(new ActionPrompt.CloseHandler() {
+ @Override
+ public void close(final AjaxRequestTarget target) {
+ toggledMementosProviderIfAny.clearToggles(target);
+ }
+ });
+ }
+
+ } else {
+ performOnClick(target);
+ }
+ }
- ActionLinkFactoryAbstract.this.onClick(this, target);
+ private ActionPrompt performOnClick(final AjaxRequestTarget target) {
+ return ActionLinkFactoryAbstract.this.onClick(this, target);
}
};
@@ -91,8 +153,10 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
return link;
}
-
- private void onClick(
+ /**
+ * @return the prompt, if not inline prompt
+ */
+ private ActionPrompt onClick(
final ActionLink actionLink,
final AjaxRequestTarget target) {
@@ -135,6 +199,8 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
actionParametersPanel.setActionPrompt(prompt);
prompt.showPrompt(target);
+ return prompt;
+
} else {
@@ -202,6 +268,8 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
target.add(scalarTypeContainer);
}
+
+ return null;
}
diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
index f8e4f4a..18981b6 100644
--- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
+++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/pages/bootstrap-overrides.css
@@ -753,6 +753,11 @@ div.referencePanel.scalarNameAndValueComponentType {
tr.headers th form input {
margin-left: -8px;
}
+/*
+tbody td.togglebox-column form {
+ margin-left: 6px;
+}
+*/
#aboutLink {
padding-right: 30px;
--
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.