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/01/18 17:03:42 UTC
git commit: ISIS-304: fixing bulk actions,
introduced new @Bulk annotation.
Updated Branches:
refs/heads/master b1aa11f86 -> 38f71bf9f
ISIS-304: fixing bulk actions, introduced new @Bulk annotation.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/38f71bf9
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/38f71bf9
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/38f71bf9
Branch: refs/heads/master
Commit: 38f71bf9fd76cd7a3f9da917d7a8c15e3c64a9ea
Parents: b1aa11f
Author: Dan Haywood <da...@apache.org>
Authored: Fri Jan 18 15:54:52 2013 +0000
Committer: Dan Haywood <da...@apache.org>
Committed: Fri Jan 18 16:02:52 2013 +0000
----------------------------------------------------------------------
.../ajaxtable/BulkActionsLinkFactory.java | 85 +++++++
.../ajaxtable/BulkCollectionsLinkFactory.java | 66 ------
.../CollectionContentsAsAjaxTablePanel.css | 13 +-
.../CollectionContentsAsAjaxTablePanel.java | 74 ++++---
.../components/entity/EntityActionLinkFactory.java | 1 -
.../components/widgets/cssmenu/CssMenuBuilder.java | 75 ++++---
.../ui/components/widgets/cssmenu/CssMenuItem.java | 33 ++-
.../ui/components/widgets/cssmenu/CssMenuPanel.css | 13 +-
core/applib/src/docbkx/guide/isis-applib.xml | 174 ++++++++++-----
.../org/apache/isis/applib/annotation/Bulk.java | 50 ++++
.../isis/applib/annotation/NotInServiceMenu.java | 4 +-
.../spec/feature/ObjectActionContainer.java | 1 -
.../spec/feature/ObjectActionFilters.java | 16 +-
.../specloader/ObjectReflectorDefault.java | 2 +-
.../isis/core/progmodel/app/IsisMetaModel.java | 7 +-
.../progmodel/facets/actions/bulk/BulkFacet.java | 34 +++
.../facets/actions/bulk/BulkFacetAbstract.java | 36 +++
.../annotation/BulkAnnotationFacetFactory.java | 49 ++++
.../bulk/annotation/BulkFacetAnnotation.java | 31 +++
.../method/NotInServiceMenuMethodFacetFactory.java | 15 +-
.../dflt/ProgrammingModelFacetsJava5.java | 2 +
.../dom/src/main/java/dom/todo/ToDoItems.java | 2 +-
.../dom/src/main/java/dom/todo/ToDoItem.java | 16 +-
.../dom/src/main/java/dom/todo/ToDoItems.java | 3 +-
24 files changed, 578 insertions(+), 224 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/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
new file mode 100644
index 0000000..34ca6ca
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
@@ -0,0 +1,85 @@
+/*
+ * 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.collectioncontents.ajaxtable;
+
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
+import org.apache.wicket.markup.html.link.AbstractLink;
+
+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;
+import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
+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.EntityCollectionModel;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
+
+final class BulkActionsLinkFactory implements CssMenuLinkFactory {
+ private static final long serialVersionUID = 1L;
+ private final EntityCollectionModel model;
+ private final DataTable<ObjectAdapter,String> dataTable;
+
+ BulkActionsLinkFactory(EntityCollectionModel model, DataTable<ObjectAdapter,String> dataTable) {
+ this.model = model;
+ this.dataTable = dataTable;
+ }
+
+ @Override
+ public LinkAndLabel newLink(final ObjectAdapterMemento serviceAdapterMemento, final ObjectAction objectAction, final String linkId) {
+ final ActionMemento actionMemento = new ActionMemento(objectAction);
+ AbstractLink link = new AjaxLink<Void>(linkId) {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void onClick(AjaxRequestTarget target) {
+ final ObjectAction objectAction = actionMemento.getAction();
+
+ for(ObjectAdapterMemento entityAdapterMemento: model.getToggleMementosList()) {
+ final ObjectAdapter entityAdapter = entityAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK);
+
+ int numParameters = objectAction.getParameterCount();
+ if(objectAction.isContributed()) {
+ // a contributed action
+ if(numParameters != 1) {
+ return;
+ }
+ if(serviceAdapterMemento == null) {
+ // not expected
+ return;
+ }
+ final ObjectAdapter serviceAdapter = serviceAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+ objectAction.execute(serviceAdapter, new ObjectAdapter[]{entityAdapter});
+ } else {
+ // an entity action
+ if(numParameters != 0) {
+ return;
+ }
+ objectAction.execute(entityAdapter, new ObjectAdapter[]{});
+ }
+ }
+ model.clearToggleMementosList();
+ target.add(dataTable);
+ }
+ };
+ return new LinkAndLabel(link, objectAction.getName());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkCollectionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkCollectionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkCollectionsLinkFactory.java
deleted file mode 100644
index 93ac411..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkCollectionsLinkFactory.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
-
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.DataTable;
-import org.apache.wicket.markup.html.link.AbstractLink;
-
-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;
-import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
-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.EntityCollectionModel;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuLinkFactory;
-
-final class BulkCollectionsLinkFactory implements CssMenuLinkFactory {
- private static final long serialVersionUID = 1L;
- private final EntityCollectionModel model;
- private final DataTable<ObjectAdapter,String> dataTable;
-
- BulkCollectionsLinkFactory(EntityCollectionModel model, DataTable<ObjectAdapter,String> dataTable) {
- this.model = model;
- this.dataTable = dataTable;
- }
-
- @Override
- public LinkAndLabel newLink(final ObjectAdapterMemento contributorAdapterMemento, final ObjectAction objectAction, final String linkId) {
- final ActionMemento actionMemento = new ActionMemento(objectAction);
- AbstractLink link = new AjaxLink<Void>(linkId) {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public void onClick(AjaxRequestTarget target) {
- final ObjectAction objectAction = actionMemento.getAction();
- for(ObjectAdapterMemento contributeeAdapterMemento: model.getToggleMementosList()) {
- final ObjectAdapter contributorAdapter = contributorAdapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
- final ObjectAdapter contributeeAdapter = contributeeAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK);
- objectAction.execute(contributorAdapter, new ObjectAdapter[]{contributeeAdapter});
- }
- model.clearToggleMementosList();
- target.add(dataTable);
- }
- };
- return new LinkAndLabel(link, objectAction.getName());
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
index 40270c5..ece5d60 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.css
@@ -147,4 +147,15 @@
.collectionContentsAsAjaxTablePanel table tfoot tr td {
padding:20px 4px 0px;
background-color:#FFFFFF !important;
-}
\ No newline at end of file
+}
+
+.collectionContentsAsAjaxTablePanel .actions {
+ float: right;
+ padding:0em 0em;
+}
+
+.collectionContentsAsAjaxTablePanel .entityActions .cssMenuPanel .menuh a:hover
+ {
+ color: #000;
+ background-color:#E3E3D9;
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
index 498a500..b13c2c9 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/CollectionContentsAsAjaxTablePanel.java
@@ -19,8 +19,12 @@
package org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable;
+import java.util.ArrayList;
+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.Lists;
import org.apache.wicket.Component;
@@ -39,6 +43,7 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer.Contributed;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionFilters;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
import org.apache.isis.core.metamodel.spec.feature.ObjectAssociationFilters;
import org.apache.isis.viewer.wicket.model.common.SelectionHandler;
@@ -59,6 +64,8 @@ import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
*/
public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityCollectionModel> {
+ private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectActionFilters.bulk());
+
private static final long serialVersionUID = 1L;
private static final String ID_TABLE = "table";
@@ -75,57 +82,52 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
private void buildGui() {
final EntityCollectionModel model = getModel();
- buildEntityActionsGui();
-
final List<IColumn<ObjectAdapter,String>> columns = Lists.newArrayList();
- addToggleboxColumnIfRequired(columns);
+ List<ObjectAction> bulkActions = determineBulkActions();
+
+ addToggleboxColumnIfRequired(columns, bulkActions);
addTitleColumn(columns);
addPropertyColumnsIfRequired(columns);
addSelectedButtonIfRequired(columns);
final SortableDataProvider<ObjectAdapter,String> dataProvider = new CollectionContentsSortableDataProvider(model);
dataTable = new MyAjaxFallbackDefaultDataTable<ObjectAdapter,String>(ID_TABLE, columns, dataProvider, model.getPageSize());
-
+
+ buildEntityActionsGui(bulkActions);
+
add(dataTable);
}
- private void addToggleboxColumnIfRequired(final List<IColumn<ObjectAdapter,String>> columns) {
+ private void addToggleboxColumnIfRequired(final List<IColumn<ObjectAdapter,String>> columns, List<ObjectAction> bulkActions) {
final EntityCollectionModel model = getModel();
-
- if(model.isStandalone()) {
- columns.add(new ObjectAdapterToggleboxColumn(new SelectionHandler() {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public void onSelected(final Component context, final ObjectAdapter selectedAdapter) {
- model.toggleSelectionOn(selectedAdapter);
- }
- }));
+ if(bulkActions.isEmpty() || model.isParented()) {
+ return;
}
+
+ columns.add(new ObjectAdapterToggleboxColumn(new SelectionHandler() {
+
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void onSelected(final Component context, final ObjectAdapter selectedAdapter) {
+ model.toggleSelectionOn(selectedAdapter);
+ }
+ }));
}
- private void buildEntityActionsGui() {
+ private void buildEntityActionsGui(List<ObjectAction> bulkActions) {
final EntityCollectionModel model = getModel();
- if(model.isParented()) {
+ if(bulkActions.isEmpty() || model.isParented()) {
permanentlyHide(ID_ENTITY_ACTIONS);
return;
}
- final ObjectSpecification typeSpec = model.getTypeOfSpecification();
-
- @SuppressWarnings("unchecked")
- final List<ObjectAction> userActions = typeSpec.getObjectActions(ActionType.USER, Contributed.INCLUDED,
- Filters.and(
- ObjectActionFilters.withNoBusinessRules(), ObjectActionFilters.contributedAnd1ParamAndVoid()
- ));
-
- if(!userActions.isEmpty()) {
- final CssMenuLinkFactory linkFactory = new BulkCollectionsLinkFactory(model, dataTable);
+ if(!bulkActions.isEmpty()) {
+ final CssMenuLinkFactory linkFactory = new BulkActionsLinkFactory(model, dataTable);
- final CssMenuBuilder cssMenuBuilder = new CssMenuBuilder(null, getServiceAdapters(), userActions, linkFactory);
+ final CssMenuBuilder cssMenuBuilder = new CssMenuBuilder(null, getServiceAdapters(), bulkActions, linkFactory);
// TODO: i18n
final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions");
@@ -135,6 +137,20 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
}
}
+ private List<ObjectAction> determineBulkActions() {
+ final EntityCollectionModel model = getModel();
+
+ if(model.isParented()) {
+ return Collections.emptyList();
+ }
+
+ final ObjectSpecification typeSpec = model.getTypeOfSpecification();
+
+ List<ObjectAction> objectActions = typeSpec.getObjectActions(ActionType.USER, Contributed.INCLUDED, Filters.<ObjectAction>any());
+ List<ObjectAction> flattenedActions = ObjectActions.flattenedActions(objectActions);
+ return Lists.newArrayList(Iterables.filter(flattenedActions, BULK));
+ }
+
private static void addTitleColumn(final List<IColumn<ObjectAdapter,String>> columns) {
columns.add(new ObjectAdapterTitleColumn());
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
index 3c51a3e..6f5c4b1 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/EntityActionLinkFactory.java
@@ -61,7 +61,6 @@ public final class EntityActionLinkFactory implements CssMenuLinkFactory {
final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
final AbstractLink link = createLink(adapterMemento, action, linkId, adapter);
- final ObjectAdapter contextAdapter = entityModel.getObject();
final String label = ObjectActions.nameFor(action);
return new LinkAndLabel(link, label);
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
index 5773e0a..534cf74 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuBuilder.java
@@ -19,28 +19,25 @@
package org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import com.google.common.collect.Collections2;
-
-import org.apache.wicket.Application;
-
import org.apache.isis.applib.filter.Filters;
import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.spec.ActionType;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionFilters;
-import org.apache.isis.core.metamodel.spec.feature.ObjectActions;
+import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet;
import org.apache.isis.core.progmodel.facets.actions.notcontributed.NotContributedFacet;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem.Builder;
import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel.Style;
+import com.google.common.collect.Collections2;
+
/**
* Used to build a {@link CssMenuItem} hierarchy from a
* {@link ObjectAdapterMemento object adapter}'s actions and any contributed
@@ -48,19 +45,31 @@ import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel.
*/
public class CssMenuBuilder {
+ /**
+ * The target to invoke upon; may be null in case of bulk actions; not used if a contributed action.
+ */
private final ObjectAdapterMemento adapterMemento;
+ /**
+ * Used to determine wire up against contributed actions.
+ */
private final List<ObjectAdapter> serviceAdapters;
+
private final List<ObjectAction> actions;
private final CssMenuLinkFactory cssMenuLinkFactory;
-
+
public CssMenuBuilder(final ObjectAdapterMemento adapterMemento, final List<ObjectAdapter> serviceAdapters, final List<ObjectAction> actions, final CssMenuLinkFactory cssMenuLinkFactory) {
- this.adapterMemento = adapterMemento;
+ this.adapterMemento = adapterMemento; // may be null
this.serviceAdapters = serviceAdapters;
this.actions = actions;
this.cssMenuLinkFactory = cssMenuLinkFactory;
}
+ public CssMenuBuilder(final List<ObjectAction> actions, final CssMenuLinkFactory cssMenuLinkFactory) {
+ this(null, null, actions, cssMenuLinkFactory);
+ }
+
+
public CssMenuPanel buildPanel(final String wicketId, final String rootName) {
final CssMenuItem findUsing = CssMenuItem.newMenuItem(rootName).build();
addMenuItems(findUsing, actions);
@@ -100,10 +109,6 @@ public class CssMenuBuilder {
}
}
- private void addMenuItems(final CssMenuItem parent, final ObjectAction[] actions) {
- addMenuItems(parent, Arrays.asList(actions));
- }
-
private void addMenuItem(final CssMenuItem parent, final ObjectAction action) {
if (action.getType() == ActionType.SET) {
addMenuItemForActionSet(parent, action);
@@ -121,21 +126,29 @@ public class CssMenuBuilder {
}
}
- private void addMenuItemForAction(final CssMenuItem parent, final ObjectAction contributedAction) {
-
- // skip if annotated to not be contributed
- if (contributedAction.getFacet(NotContributedFacet.class) != null) {
+ private void addMenuItemForAction(final CssMenuItem parent, final ObjectAction action) {
+
+ if (action.getFacet(NotContributedFacet.class) != null) {
+ // skip if is an action that has been annotated to not be contributed
return;
}
- final ObjectAdapterMemento serviceAdapterMemento = determineAdapterFor(contributedAction);
- if(serviceAdapterMemento == null) {
- return;
+ Builder subMenuItemBuilder = null;
+
+ final ObjectAdapterMemento targetAdapterMemento = determineAdapterFor(action);
+ if(targetAdapterMemento != null) {
+ // against an entity or a service (if a contributed action)
+ subMenuItemBuilder = parent.newSubMenuItem(targetAdapterMemento, action, cssMenuLinkFactory);
+ } else {
+ if (action.containsDoOpFacet(BulkFacet.class)) {
+ // ignore fact have no target action;
+ // we expect that the link factory is able to handle this
+ // (ie will iterate through all objects from a list and invoke in bulk)
+ subMenuItemBuilder = parent.newSubMenuItem(action, cssMenuLinkFactory);
+ }
}
-
- final Builder subMenuItemBuilder = parent.newSubMenuItem(serviceAdapterMemento, contributedAction, cssMenuLinkFactory);
+
if (subMenuItemBuilder != null) {
- // could be null if invisible
subMenuItemBuilder.build();
}
}
@@ -148,14 +161,20 @@ public class CssMenuBuilder {
* adapters also.
*/
private ObjectAdapterMemento determineAdapterFor(final ObjectAction action) {
- // search through service adapters first
- final ObjectSpecification onType = action.getOnType();
- for (final ObjectAdapter serviceAdapter : getServiceAdapters()) {
- if (serviceAdapter.getSpecification() == onType) {
- return ObjectAdapterMemento.createOrNull(serviceAdapter);
+
+ if(getServiceAdapters() != null) {
+ // null check required because could be null.
+
+ // search through service adapters first
+ final ObjectSpecification onType = action.getOnType();
+ for (final ObjectAdapter serviceAdapter : getServiceAdapters()) {
+ if (serviceAdapter.getSpecification() == onType) {
+ return ObjectAdapterMemento.createOrNull(serviceAdapter);
+ }
}
}
- // otherwise, specified adapter
+
+ // otherwise, specified adapter (could be null)
return adapterMemento;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
index 64f65b6..541c5f9 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuItem.java
@@ -45,6 +45,7 @@ import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
import org.apache.isis.core.metamodel.consent.Consent;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet;
import org.apache.isis.viewer.wicket.model.links.LinkAndLabel;
import org.apache.isis.viewer.wicket.model.mementos.ObjectAdapterMemento;
import org.apache.isis.viewer.wicket.ui.pages.PageAbstract;
@@ -194,30 +195,44 @@ public class CssMenuItem implements Serializable {
private final Where where = Where.ANYWHERE;
/**
+ * Creates a {@link Builder} for a submenu item invoking an action on the provided
+ * {@link ObjectAdapterMemento target adapter}.
+ *
* @return the builder, else <tt>null</tt> if the action is not visible for
* the current user.
*/
- public Builder newSubMenuItem(final ObjectAdapterMemento adapterMemento, final ObjectAction objectAction, final CssMenuLinkFactory cssMenuLinkFactory) {
+ public Builder newSubMenuItem(final ObjectAdapterMemento targetAdapterMemento, final ObjectAction objectAction, final CssMenuLinkFactory cssMenuLinkFactory) {
- final AuthenticationSession session = getAuthenticationSession();
+ final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(targetAdapterMemento, objectAction, PageAbstract.ID_MENU_LINK);
+ final AbstractLink link = linkAndLabel.getLink();
+ final String actionLabel = linkAndLabel.getLabel();
- final CssMenuItem parentMenuItem = this;
+ // check visibility and whether enabled
+ final AuthenticationSession session = getAuthenticationSession();
- final ObjectAdapter adapter = adapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK);
+ final ObjectAdapter adapter = targetAdapterMemento.getObjectAdapter(ConcurrencyChecking.CHECK);
final Consent visibility = objectAction.isVisible(session, adapter, where);
if (visibility.isVetoed()) {
return null;
}
- final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(adapterMemento, objectAction, PageAbstract.ID_MENU_LINK);
+ final Consent usability = objectAction.isUsable(session, adapter, where);
+ final String reasonDisabledIfAny = usability.getReason();
+
+ return newSubMenuItem(actionLabel).link(link).enabled(reasonDisabledIfAny);
+ }
+
+ /**
+ * Creates a {@link Builder} for a submenu item where the provided {@link CssMenuLinkFactory} is able to provide the target adapter.
+ */
+ public Builder newSubMenuItem(final ObjectAction objectAction, final CssMenuLinkFactory cssMenuLinkFactory) {
+
+ final LinkAndLabel linkAndLabel = cssMenuLinkFactory.newLink(null, objectAction, PageAbstract.ID_MENU_LINK);
final AbstractLink link = linkAndLabel.getLink();
final String actionLabel = linkAndLabel.getLabel();
- final Consent usability = objectAction.isUsable(session, adapter, where);
- final String reasonDisabledIfAny = usability.getReason();
-
- return parentMenuItem.newSubMenuItem(actionLabel).link(link).enabled(reasonDisabledIfAny);
+ return this.newSubMenuItem(actionLabel).link(link);
}
// //////////////////////////////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuPanel.css
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuPanel.css b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuPanel.css
index b021b4a..94c3a67 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuPanel.css
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/CssMenuPanel.css
@@ -139,6 +139,10 @@
color: gray;
}
+.cssMenuPanel li.cssSubMenuItem {
+ margin-left:0px;
+}
+
/******** overrides for grouped actions and entity actions ***************/
.groupedActions .cssMenuPanel li.cssMenuItemPanel>p.top-parent {
display: none;
@@ -220,13 +224,18 @@
padding: 0px;
}
-.entityActions .cssMenuPanel .menuh li,
-.entityActions .cssMenuPanel .menuh li p {
+.entityActions .cssMenuPanel .menuh li {
float:left;
display:block;
margin-left:10px;
}
+.entityActions .cssMenuPanel .menuh li p {
+ float:left;
+ display:block;
+ margin-left:0px;
+}
+
.entityActions .cssMenuPanel .menuh a,
.entityActions .cssMenuPanel .menuh p {
display: inline-block;
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/applib/src/docbkx/guide/isis-applib.xml
----------------------------------------------------------------------
diff --git a/core/applib/src/docbkx/guide/isis-applib.xml b/core/applib/src/docbkx/guide/isis-applib.xml
index e4ddeb1..8d52f72 100644
--- a/core/applib/src/docbkx/guide/isis-applib.xml
+++ b/core/applib/src/docbkx/guide/isis-applib.xml
@@ -240,6 +240,63 @@ public void setPropertyName(PropertyType param)</programlisting></para>
</sect1>
<sect1>
+ <title condition="java">How to specify a title for a domain
+ entity</title>
+
+ <para>A title is used to identify an object to the user in the user
+ interface. For example, a <classname>Customer</classname>'s title
+ might be the organization's customer reference, or perhaps (more
+ informally) their first and last names.</para>
+
+ <para>By default, the framework will use the object's <literal
+ moreinfo="none">toString()</literal> method as the title. Most titles
+ tend to be made up of the same set of elements: for example a
+ Customer's name might be the concatenation of their customer first
+ name and their ;ast name. For these the <classname>@Title</classname>
+ annotation can be used:</para>
+
+ <para><programlisting>public class Customer {
+ @Title
+ public String getFirstName() { ... }
+ @Title
+ public String getLastName() { ... }
+ ...
+}</programlisting></para>
+
+ <para>For more control, the order of the title components can be
+ specified using a sequence number (specified in Dewey decimal
+ format):</para>
+
+ <programlisting>public class Customer {
+ @Title("1.0")
+ public String getFirstName() { ... }
+ @Title("1.1")
+ public String getLastName() { ... }
+ ...
+}</programlisting>
+
+ <para>For more control the title can be declared imperately using the
+ <literal moreinfo="none">title()</literal> method (returning a
+ <literal moreinfo="none">String</literal>). This leaves the programmer
+ needs to make use of the <literal moreinfo="none">toString()</literal>
+ method for other purposes, such as for debugging. For example, to
+ return the title for a customer which is their last name and then
+ first initial of their first name, we could use:</para>
+
+ <para><programlisting>public class Customer {
+ public String title() {
+ return getLastName() + ", " + getFirstName().substring(0,1);
+ }
+ ...
+}</programlisting></para>
+
+ <para>The applib contains a class,
+ <classname>org.apache.isis.applib.util.TitleBuffer</classname>, which
+ you can use to help create title strings if you so wish. See <xref
+ linkend="apx.UtilityClasses" /> for more details.</para>
+ </sect1>
+
+ <sect1>
<title>How to add a collection to a domain entity</title>
<para>A collection is a multi-valued attribute/field of a entity, in
@@ -305,7 +362,8 @@ public class Department {
</sect1>
<sect1>
- <title>How to add an action to a domain entity or service</title>
+ <title>How to add an action (or bulk action) to a domain entity or
+ service</title>
<para>An 'action' is a method that we expect the user to be able to
invoke on a domain entity via the user interface, though it may also
@@ -358,63 +416,36 @@ public class Department {
are ignored: such functionality should reside in a service, such as a
repository or factory (see <xref
linkend="chp.DomainServices" />).</para>
- </sect1>
- <sect1>
- <title condition="java">How to specify a title for a domain
- entity</title>
+ <para>If the action is a bulk action - meaning that it should only be
+ applied to a collection of instances of the entity - then annotate
+ using <classname>@Bulk</classname>:</para>
- <para>A title is used to identify an object to the user in the user
- interface. For example, a <classname>Customer</classname>'s title
- might be the organization's customer reference, or perhaps (more
- informally) their first and last names.</para>
-
- <para>By default, the framework will use the object's <literal
- moreinfo="none">toString()</literal> method as the title. Most titles
- tend to be made up of the same set of elements: for example a
- Customer's name might be the concatenation of their customer first
- name and their ;ast name. For these the <classname>@Title</classname>
- annotation can be used:</para>
+ <programlisting>@Bulk
+public void actionName() { ... }</programlisting>
- <para><programlisting>public class Customer {
- @Title
- public String getFirstName() { ... }
- @Title
- public String getLastName() { ... }
- ...
-}</programlisting></para>
+ <para>Note that bulk actions have a couple of important
+ restrictions.</para>
- <para>For more control, the order of the title components can be
- specified using a sequence number (specified in Dewey decimal
- format):</para>
+ <itemizedlist>
+ <listitem>
+ <para>entity actions cannot take any arguments, while contributed
+ actions can take only a single parameter (the contributee)</para>
- <programlisting>public class Customer {
- @Title("1.0")
- public String getFirstName() { ... }
- @Title("1.1")
- public String getLastName() { ... }
- ...
-}</programlisting>
+ <para>This restriction might be lifted in the future;</para>
+ </listitem>
- <para>For more control the title can be declared imperately using the
- <literal moreinfo="none">title()</literal> method (returning a
- <literal moreinfo="none">String</literal>). This leaves the programmer
- needs to make use of the <literal moreinfo="none">toString()</literal>
- method for other purposes, such as for debugging. For example, to
- return the title for a customer which is their last name and then
- first initial of their first name, we could use:</para>
+ <listitem>
+ <para>any business rules for hiding, disabling or validating the
+ action are ignored.</para>
+ </listitem>
+ </itemizedlist>
- <para><programlisting>public class Customer {
- public String title() {
- return getLastName() + ", " + getFirstName().substring(0,1);
- }
- ...
-}</programlisting></para>
+ <para>See <xref linkend="chp.BusinessRules" /> for more details on
+ writing business rules.</para>
- <para>The applib contains a class,
- <classname>org.apache.isis.applib.util.TitleBuffer</classname>, which
- you can use to help create title strings if you so wish. See <xref
- linkend="apx.UtilityClasses" /> for more details.</para>
+ <para>At the time of writing, only the Wicket viewer recognizes bulk
+ actions; other viewers treat the action as a regular action.</para>
</sect1>
<sect1 id="sec.HowToSpecifyTheIconForAnObjectsClass">
@@ -508,11 +539,9 @@ public class Department {
...
}</programlisting>
- <para></para>
-
- <para>***</para>
-
- <para></para>
+ <para>The syntax for the <classname>@MemberOrder</classname> is dewey
+ decimal notation, so "3.5" and "3.6" come between "3" and "4"; "3.5.1"
+ comes between "3.5" and "3.6".</para>
</sect1>
<sect1>
@@ -844,13 +873,13 @@ persist(newCust);</programlisting>
</sect1>
</chapter>
- <chapter id="chp.Properties">
+ <chapter id="chp.BusinessRules">
<title>How to add business rules</title>
<abstract>
<para>How-to add business rules to domain entities and services,
controlling whether a domain entity or service's class members are
- visible, if they are enabled, and to validate arguments. </para>
+ visible, if they are enabled, and to validate arguments.</para>
</abstract>
<para>Business rules can be added to domain objects in a number of ways.
@@ -1989,7 +2018,7 @@ public class Customer {
<para>The Isis viewers will automatically render the state of properties
and collections, but the values of such need not be persisted; they can
- be derived from other information available to the object. </para>
+ be derived from other information available to the object.</para>
<para>For collections</para>
@@ -3144,6 +3173,14 @@ isis.services = employee.EmployeeRepositoryDefault, claim.ClaimRepositoryDefault
If an action should neither be contributed nor appear in service
menu items, then simply annotate it as
<classname>@Hidden</classname>.</para>
+
+ <para>Alternatively, this can be performed using a supporting
+ method:</para>
+
+ <programlisting>public class LibraryImpl implements Library {
+ public Loan borrow(Loanable l, Borrower b) { ... }
+ public boolean notInServiceMenuBorrow() { ... }
+}</programlisting>
</sect2>
<sect2>
@@ -5282,6 +5319,27 @@ public class County {
</note>
</sect1>
+ <sect1>
+ <title>@Bulk</title>
+
+ <para>For actions that should only be applied to a collection of
+ objects of the same type, annotate using
+ @<classname>Bulk</classname>.</para>
+
+ <para>For example:</para>
+
+ <programlisting format="linespecific">public class ToDoItem {
+ ...
+ @Bulk
+ public void markAsCompleted() {
+ setCompleted(true);
+ }
+}</programlisting>
+
+ <para>Bulk actions cannot take arguments, nor can they be hidden,
+ disabled or have validation rules.</para>
+ </sect1>
+
<sect1 id="sec.DebugAnnotation">
<title>@Debug</title>
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/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
new file mode 100644
index 0000000..c9af9cd
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/Bulk.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.applib.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates the (entity) action should be used only against many objects
+ * in a collection.
+ *
+ * <p>
+ * Bulk actions have a number of constraints:
+ * <ul>
+ * <li>It must take no arguments
+ * <li>It must return <tt>void</tt>
+ * <li>It cannot be hidden (any annotations or supporting methods to that effect will be
+ * ignored).
+ * <li>It cannot be disabled (any annotations or supporting methods to that effect will be
+ * ignored).
+ * </ul>
+ *
+ * <p>
+ * Has no meaning if annotated on an action of a domain service.
+ */
+@Inherited
+@Target({ ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Bulk {
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
index 2bcece5..9797fd1 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/NotInServiceMenu.java
@@ -26,7 +26,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Indicates the a (service) action should be not be displayed in the service
+ * Indicates the (service) action should be not be displayed in the service
* menu.
*
* <p>
@@ -35,7 +35,7 @@ import java.lang.annotation.Target;
* should not appear in the service menu.
*
* <p>
- * Has no meanings for actions on regular entities.
+ * Has no meaning if annotated on an action of a regular entity.
*/
@Inherited
@Target({ ElementType.METHOD })
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
index 1cc82a9..b089c97 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionContainer.java
@@ -25,7 +25,6 @@ import org.apache.isis.applib.Identifier;
import org.apache.isis.applib.filter.Filter;
import org.apache.isis.core.metamodel.spec.ActionType;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.spec.feature.ObjectActionContainer.Contributed;
public interface ObjectActionContainer {
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
index 9501e18..32ef9e9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/feature/ObjectActionFilters.java
@@ -32,6 +32,7 @@ import org.apache.isis.core.metamodel.interactions.HidingInteractionAdvisor;
import org.apache.isis.core.metamodel.interactions.ValidatingInteractionAdvisor;
import org.apache.isis.core.metamodel.spec.ActionType;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet;
public class ObjectActionFilters {
@@ -54,14 +55,12 @@ public class ObjectActionFilters {
};
}
- public static Filter<ObjectAction> withNoBusinessRules() {
+ public static Filter<ObjectAction> withNoValidationRules() {
return new Filter<ObjectAction>(){
@Override
public boolean accept(final ObjectAction objectAction) {
- final List<Facet> hidingFacets = objectAction.getFacets(FacetFilters.isA(HidingInteractionAdvisor.class));
- final List<Facet> disablingFacets = objectAction.getFacets(FacetFilters.isA(DisablingInteractionAdvisor.class));
final List<Facet> validatingFacets = objectAction.getFacets(FacetFilters.isA(ValidatingInteractionAdvisor.class));
- return hidingFacets.isEmpty() && disablingFacets.isEmpty() && validatingFacets.isEmpty();
+ return validatingFacets.isEmpty();
}};
}
@@ -85,4 +84,13 @@ public class ObjectActionFilters {
}
};
}
+
+ public static Filter<ObjectAction> bulk() {
+ return new Filter<ObjectAction>(){
+
+ @Override
+ public boolean accept(ObjectAction oa) {
+ return oa.containsDoOpFacet(BulkFacet.class);
+ }};
+ }
}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
index b2ce2ef..6e6583d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/ObjectReflectorDefault.java
@@ -231,6 +231,7 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
*/
@Override
public void init() {
+
ValidationFailures validationFailures = initAndValidate();
validationFailures.assertNone();
@@ -267,7 +268,6 @@ public final class ObjectReflectorDefault implements SpecificationLoaderSpi, App
facetProcessor.init();
metaModelValidator.init();
- // prime cache and validate
primeCache();
ValidationFailures validationFailures = new ValidationFailures();
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
index 2ccaa4c..47ba2f3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/app/IsisMetaModel.java
@@ -180,13 +180,14 @@ public class IsisMetaModel implements ApplicationScopedComponent {
runtimeContext.injectInto(reflector);
reflector.injectInto(runtimeContext);
- validationFailures = reflector.initAndValidate();
- runtimeContext.init();
-
for (final Object service : services) {
final ObjectSpecification serviceSpec = reflector.loadSpecification(service.getClass());
serviceSpec.markAsService();
}
+
+ validationFailures = reflector.initAndValidate();
+ runtimeContext.init();
+
state = State.INITIALIZED;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacet.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacet.java
new file mode 100644
index 0000000..fd3d284
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacet.java
@@ -0,0 +1,34 @@
+/*
+ * 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.progmodel.facets.actions.bulk;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+
+/**
+ * Indicates that the action (entity or service) can also be used as a bulk
+ * action against collections of objects.
+ *
+ * <p>
+ * In the standard Apache Isis Programming Model, corresponds to annotating the
+ * action method using <tt>@Bulk</tt>.
+ */
+public interface BulkFacet extends Facet {
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacetAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacetAbstract.java
new file mode 100644
index 0000000..3cd7452
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/BulkFacetAbstract.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.bulk;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
+
+public abstract class BulkFacetAbstract extends MarkerFacetAbstract implements BulkFacet {
+
+ public static Class<? extends Facet> type() {
+ return BulkFacet.class;
+ }
+
+ public BulkFacetAbstract(final FacetHolder holder) {
+ super(type(), holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkAnnotationFacetFactory.java
new file mode 100644
index 0000000..906dfba
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkAnnotationFacetFactory.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.isis.core.progmodel.facets.actions.bulk.annotation;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.applib.annotation.Bulk;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacet;
+
+public class BulkAnnotationFacetFactory extends FacetFactoryAbstract {
+
+ public BulkAnnotationFacetFactory() {
+ super(FeatureType.ACTIONS_ONLY);
+ }
+
+ @Override
+ public void process(final ProcessMethodContext processMethodContext) {
+ Method method = processMethodContext.getMethod();
+ final Bulk annotation = Annotations.getAnnotation(method, Bulk.class);
+ FacetUtil.addFacet(create(annotation, processMethodContext.getFacetHolder()));
+ }
+
+ private BulkFacet create(final Bulk annotation, final FacetHolder holder) {
+ return annotation == null ? null : new BulkFacetAnnotation(holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkFacetAnnotation.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkFacetAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkFacetAnnotation.java
new file mode 100644
index 0000000..3e4b3ee
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/bulk/annotation/BulkFacetAnnotation.java
@@ -0,0 +1,31 @@
+/*
+ * 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.progmodel.facets.actions.bulk.annotation;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.progmodel.facets.actions.bulk.BulkFacetAbstract;
+
+public class BulkFacetAnnotation extends BulkFacetAbstract {
+
+ public BulkFacetAnnotation(final FacetHolder holder) {
+ super(holder);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactory.java
index 4fcd17d..fdc8cb1 100755
--- a/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/actions/notinservicemenu/method/NotInServiceMenuMethodFacetFactory.java
@@ -41,23 +41,16 @@ public class NotInServiceMenuMethodFacetFactory extends MethodPrefixBasedFacetFa
final String capitalizedName = NameUtils.javaBaseNameStripAccessorPrefixIfRequired(getMethod.getName());
final Class<?> cls = processMethodContext.getCls();
- final Method hideMethod = MethodFinderUtils.findMethod(cls, MethodScope.OBJECT, /*
- * MethodPrefixConstants
- * .
- * HIDE_PREFIX
- */
+ final Method notInServiceMenuMethod = MethodFinderUtils.findMethod(cls, MethodScope.OBJECT,
"notInServiceMenu" + capitalizedName, boolean.class, new Class[] {});
- if (hideMethod == null) {
+ if (notInServiceMenuMethod == null) {
return;
}
- processMethodContext.removeMethod(hideMethod);
+ processMethodContext.removeMethod(notInServiceMenuMethod);
final FacetHolder facetedMethod = processMethodContext.getFacetHolder();
- // FacetUtil.addFacet(new
- // NotInServiceMenuFacetAnnotation(facetedMethod));
- FacetUtil.addFacet(new NotInServiceMenuFacetMethod(hideMethod, facetedMethod));
-
+ FacetUtil.addFacet(new NotInServiceMenuFacetMethod(notInServiceMenuMethod, facetedMethod));
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index dd5fded..5bb4242 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
@@ -20,6 +20,7 @@
package org.apache.isis.progmodels.dflt;
import org.apache.isis.core.metamodel.progmodel.ProgrammingModelAbstract;
+import org.apache.isis.core.progmodel.facets.actions.bulk.annotation.BulkAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.debug.annotation.DebugAnnotationFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.defaults.method.ActionDefaultsFacetFactory;
import org.apache.isis.core.progmodel.facets.actions.exploration.annotation.ExplorationAnnotationFacetFactory;
@@ -309,6 +310,7 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
addFactory(NotContributedAnnotationFacetFactory.class);
addFactory(NotInServiceMenuAnnotationFacetFactory.class);
addFactory(NotInServiceMenuMethodFacetFactory.class);
+ addFactory(BulkAnnotationFacetFactory.class);
addFactory(HiddenAnnotationForTypeFacetFactory.class);
// must come after the TitleAnnotationFacetFactory, because can act as an override
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/example/application/quickstart_dnd_junit_bdd/dom/src/main/java/dom/todo/ToDoItems.java
----------------------------------------------------------------------
diff --git a/example/application/quickstart_dnd_junit_bdd/dom/src/main/java/dom/todo/ToDoItems.java b/example/application/quickstart_dnd_junit_bdd/dom/src/main/java/dom/todo/ToDoItems.java
index d13e71e..cd120eb 100644
--- a/example/application/quickstart_dnd_junit_bdd/dom/src/main/java/dom/todo/ToDoItems.java
+++ b/example/application/quickstart_dnd_junit_bdd/dom/src/main/java/dom/todo/ToDoItems.java
@@ -112,7 +112,7 @@ public class ToDoItems extends AbstractFactoryAndRepository {
});
}
// }}
-
+
// {{ autoComplete (hidden)
@Hidden
public List<ToDoItem> autoComplete(final String description) {
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/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 4bb1a19..641aff2 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
@@ -28,7 +28,9 @@ import javax.jdo.annotations.VersionStrategy;
import javax.jdo.spi.PersistenceCapable;
import org.apache.isis.applib.DomainObjectContainer;
+import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.AutoComplete;
+import org.apache.isis.applib.annotation.Bulk;
import org.apache.isis.applib.annotation.Disabled;
import org.apache.isis.applib.annotation.Hidden;
import org.apache.isis.applib.annotation.MemberGroups;
@@ -41,6 +43,7 @@ import org.apache.isis.applib.annotation.Optional;
import org.apache.isis.applib.annotation.Programmatic;
import org.apache.isis.applib.annotation.RegEx;
import org.apache.isis.applib.annotation.Resolve;
+import org.apache.isis.applib.annotation.ActionSemantics.Of;
import org.apache.isis.applib.annotation.Resolve.Type;
import org.apache.isis.applib.annotation.Where;
import org.apache.isis.applib.clock.Clock;
@@ -48,7 +51,6 @@ import org.apache.isis.applib.filter.Filter;
import org.apache.isis.applib.filter.Filters;
import org.apache.isis.applib.util.TitleBuffer;
import org.apache.isis.applib.value.Blob;
-import org.apache.isis.applib.value.Clob;
import org.apache.isis.core.objectstore.jdo.applib.annotations.Auditable;
import org.joda.time.LocalDate;
@@ -130,6 +132,9 @@ public class ToDoItem implements Comparable<ToDoItem> {
public void setDueBy(final LocalDate dueBy) {
this.dueBy = dueBy;
}
+ public void clearDueBy() {
+ setDueBy(null);
+ }
// proposed new value is validated before setting
public String validateDueBy(final LocalDate dueBy) {
if (dueBy == null) {
@@ -236,6 +241,7 @@ public class ToDoItem implements Comparable<ToDoItem> {
// }}
// {{ completed (action)
+ @Bulk
@MemberOrder(sequence = "1")
public ToDoItem completed() {
setComplete(true);
@@ -246,7 +252,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
public String disableCompleted() {
return complete ? "Already completed" : null;
}
-
// }}
// {{ notYetCompleted (action)
@@ -262,6 +267,9 @@ public class ToDoItem implements Comparable<ToDoItem> {
return !complete ? "Not yet completed" : null;
}
// }}
+
+
+
// {{ dependencies (Collection)
private List<ToDoItem> dependencies = new ArrayList<ToDoItem>();
@@ -357,7 +365,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
/**
* by complete flag, then due by date, then description
*/
- @Programmatic
// exclude from the framework's metamodel
@Override
public int compareTo(final ToDoItem other) {
@@ -378,7 +385,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
}
return getDueBy().compareTo(getDueBy());
}
-
// }}
// {{ helpers
@@ -429,8 +435,6 @@ public class ToDoItem implements Comparable<ToDoItem> {
};
}
-
-
// }}
// {{ injected: DomainObjectContainer
http://git-wip-us.apache.org/repos/asf/isis/blob/38f71bf9/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 bbb1034..1c94c32 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
@@ -24,6 +24,7 @@ import java.util.List;
import org.apache.isis.applib.AbstractFactoryAndRepository;
import org.apache.isis.applib.annotation.ActionSemantics;
import org.apache.isis.applib.annotation.ActionSemantics.Of;
+import org.apache.isis.applib.annotation.Bulk;
import org.apache.isis.applib.annotation.Hidden;
import org.apache.isis.applib.annotation.MemberOrder;
import org.apache.isis.applib.annotation.Named;
@@ -132,7 +133,6 @@ public class ToDoItems extends AbstractFactoryAndRepository {
// }}
-
// {{ autoComplete (hidden)
@Hidden
public List<ToDoItem> autoComplete(final String description) {
@@ -155,4 +155,5 @@ public class ToDoItems extends AbstractFactoryAndRepository {
}
// }}
+
}