You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2014/11/11 09:25:00 UTC

[37/44] isis git commit: ISIS-537: tidy up, fixing selector helper for when there is only one view.

ISIS-537: tidy up, fixing selector helper for when there is only one view.


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

Branch: refs/heads/master
Commit: cb2bea9ab22d60248e43e53aae9b21614e98286c
Parents: 9bad917
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Nov 10 20:26:22 2014 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Nov 10 20:26:22 2014 +0000

----------------------------------------------------------------------
 .../common/OnConcurrencyExceptionHandler.java   |  38 +++
 .../wicket/model/common/OnSelectionHandler.java |  37 +++
 .../wicket/model/common/SelectionHandler.java   |  44 ----
 .../collection/bulk/BulkActionsHelper.java      | 102 +++++++++
 .../collection/bulk/BulkActionsLinkFactory.java | 229 +++++++++++++++++++
 .../collection/bulk/BulkActionsProvider.java    |  28 +++
 .../selector/CollectionSelectorHelper.java      |  64 +++---
 .../selector/CollectionSelectorPanel.java       |   2 +-
 .../ajaxtable/BulkActionsHelper.java            | 102 ---------
 .../ajaxtable/BulkActionsLinkFactory.java       | 229 -------------------
 .../ajaxtable/BulkActionsProvider.java          |  28 ---
 .../CollectionContentsAsAjaxTablePanel.java     |  49 +---
 .../columns/ObjectAdapterToggleboxColumn.java   |  45 +++-
 .../CollectionContentsMultipleViewsPanel.java   |  38 +--
 .../collections/EntityCollectionsPanel.java     |   2 +-
 .../StandaloneCollectionPanel.java              | 167 +++++---------
 .../cssmenu/ActionLinkFactoryAbstract.java      |   3 +-
 17 files changed, 595 insertions(+), 612 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnConcurrencyExceptionHandler.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnConcurrencyExceptionHandler.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnConcurrencyExceptionHandler.java
new file mode 100644
index 0000000..6b11659
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnConcurrencyExceptionHandler.java
@@ -0,0 +1,38 @@
+/*
+ *  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.model.common;
+
+import java.io.Serializable;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+
+/**
+ * Decouples the mechanism for selecting entities returned in collections.
+ */
+public interface OnConcurrencyExceptionHandler extends Serializable {
+
+    void onConcurrencyException(
+            Component context, ObjectAdapter selectedAdapter,
+            ConcurrencyException ex,
+            AjaxRequestTarget ajaxRequestTarget);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnSelectionHandler.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnSelectionHandler.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnSelectionHandler.java
new file mode 100644
index 0000000..17e1d4d
--- /dev/null
+++ b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/OnSelectionHandler.java
@@ -0,0 +1,37 @@
+/*
+ *  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.model.common;
+
+import java.io.Serializable;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+
+/**
+ * Decouples the mechanism for selecting entities returned in collections.
+ */
+public interface OnSelectionHandler extends Serializable {
+
+    void onSelected(
+            Component context, ObjectAdapter selectedAdapter,
+            AjaxRequestTarget ajaxRequestTarget);
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java b/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
deleted file mode 100644
index dfecf23..0000000
--- a/component/viewer/wicket/model/src/main/java/org/apache/isis/viewer/wicket/model/common/SelectionHandler.java
+++ /dev/null
@@ -1,44 +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.model.common;
-
-import java.io.Serializable;
-
-import org.apache.wicket.Component;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
-
-/**
- * Decouples the mechanism for selecting entities returned in collections.
- */
-public interface SelectionHandler extends Serializable {
-
-    void onSelected(
-            Component context, ObjectAdapter selectedAdapter,
-            AjaxRequestTarget ajaxRequestTarget);
-
-    void onConcurrencyException(
-            Component context, ObjectAdapter selectedAdapter, 
-            ConcurrencyException ex,
-            AjaxRequestTarget ajaxRequestTarget);
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java
new file mode 100644
index 0000000..b54a4d7
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsHelper.java
@@ -0,0 +1,102 @@
+/*
+ *  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.bulk;
+
+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.Lists;
+import org.apache.isis.applib.filter.Filters;
+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.context.IsisContext;
+import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
+
+public class BulkActionsHelper implements Serializable {
+
+    private final EntityCollectionModel model;
+
+    private static final long serialVersionUID = 1L;
+
+    public BulkActionsHelper(final EntityCollectionModel model) {
+        this.model = model;
+    }
+
+    private EntityCollectionModel getModel() {
+        return model;
+    }
+
+    public List<ObjectAction> getBulkActions() {
+        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());
+
+        if ( isExploring() || isPrototyping()) {
+            List<ObjectAction> explorationActions = typeSpec.getObjectActions(ActionType.EXPLORATION, Contributed.INCLUDED, Filters.<ObjectAction>any());
+            List<ObjectAction> prototypeActions = typeSpec.getObjectActions(ActionType.PROTOTYPE, Contributed.INCLUDED, Filters.<ObjectAction>any());
+            objectActions.addAll(explorationActions);
+            objectActions.addAll(prototypeActions);
+        }
+        if (isDebugMode()) {
+            List<ObjectAction> debugActions = typeSpec.getObjectActions(ActionType.DEBUG, Contributed.INCLUDED, Filters.<ObjectAction>any());
+            objectActions.addAll(debugActions);
+        }
+
+        List<ObjectAction> flattenedActions = objectActions;
+
+        return Lists.newArrayList(Iterables.filter(flattenedActions, BULK));
+    }
+
+
+    @SuppressWarnings("deprecation")
+    private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
+
+
+    //region > from context
+
+    public boolean isExploring() {
+        return IsisContext.getDeploymentType().isExploring();
+    }
+    public boolean isPrototyping() {
+        return IsisContext.getDeploymentType().isPrototyping();
+    }
+
+    /**
+     * Protected so can be overridden in testing if required.
+     */
+    protected boolean isDebugMode() {
+        // TODO: need to figure out how to switch into debug mode;
+        // probably call a Debug toggle page, and stuff into
+        // Session.getMetaData()
+        return true;
+    }
+
+    //endregion
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
new file mode 100644
index 0000000..46f8642
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsLinkFactory.java
@@ -0,0 +1,229 @@
+/*
+ *  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.bulk;
+
+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.Session;
+import org.apache.wicket.markup.html.link.AbstractLink;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.isis.applib.RecoverableException;
+import org.apache.isis.applib.annotation.Bulk;
+import org.apache.isis.applib.annotation.Bulk.InteractionContext.InvokedAs;
+import org.apache.isis.applib.services.command.Command;
+import org.apache.isis.applib.services.command.Command.Executor;
+import org.apache.isis.applib.services.command.CommandContext;
+import org.apache.isis.core.commons.authentication.AuthenticationSession;
+import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
+import org.apache.isis.core.commons.authentication.MessageBroker;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.runtime.system.context.IsisContext;
+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.ActionModel;
+import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
+import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
+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;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
+import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
+
+public final class BulkActionsLinkFactory implements ActionLinkFactory {
+    
+    private static final long serialVersionUID = 1L;
+    private final EntityCollectionModel model;
+    
+    private final ObjectAdapterToggleboxColumn toggleboxColumn;
+
+    public BulkActionsLinkFactory(
+            final EntityCollectionModel model,
+            final ObjectAdapterToggleboxColumn toggleboxColumn) {
+        this.model = model;
+        this.toggleboxColumn = toggleboxColumn;
+    }
+
+
+    @Override
+    public LinkAndLabel newLink(
+            final ObjectAdapterMemento serviceAdapterMemento,
+            final ObjectAction objectAction,
+            final String linkId,
+            final ActionPromptProvider actionPromptProvider) {
+        
+        final ActionMemento actionMemento = new ActionMemento(objectAction);
+        final AbstractLink link = new Link<Object>(linkId) {
+            
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            public void onClick() {
+                final ObjectAction objectAction = actionMemento.getAction();
+                final ConcurrencyChecking concurrencyChecking = 
+                        ConcurrencyChecking.concurrencyCheckingFor(objectAction.getSemantics());
+
+                try {
+                    final List<ObjectAdapterMemento> toggleMementosList = model.getToggleMementosList();
+
+                    final Iterable<ObjectAdapter> toggledAdapters = 
+                            Iterables.transform(toggleMementosList, ObjectAdapterMemento.Functions.fromMemento(concurrencyChecking));
+                    
+                    final List<Object> domainObjects = Lists.newArrayList(Iterables.transform(toggledAdapters, ObjectAdapter.Functions.getObject()));
+                    
+                    
+                    final Bulk.InteractionContext bulkInteractionContext = Bulk.InteractionContext.current.get();
+                    if (bulkInteractionContext != null) {
+                        bulkInteractionContext.setInvokedAs(InvokedAs.BULK);
+                        bulkInteractionContext.setDomainObjects(domainObjects);
+                    }
+                    
+                    final CommandContext commandContext = getServicesInjector().lookupService(CommandContext.class);
+                    final Command command;
+                    if (commandContext != null) {
+                        command = commandContext.getCommand();
+                        command.setExecutor(Executor.USER);
+                    }
+
+
+                    ObjectAdapter lastReturnedAdapter = null;
+                    int i=0;
+                    for(final ObjectAdapter adapter : toggledAdapters) {
+    
+                        int numParameters = objectAction.getParameterCount();
+                        if(numParameters != 0) {
+                            return;
+                        }
+                        if (bulkInteractionContext != null) {
+                            bulkInteractionContext.setIndex(i++);
+                        }
+
+                        lastReturnedAdapter = objectAction.executeWithRuleChecking(adapter, new ObjectAdapter[]{}, getAuthenticationSession(), ActionModel.WHERE_FOR_ACTION_INVOCATION);
+                    }
+
+
+                    
+                    model.clearToggleMementosList();
+                    toggleboxColumn.clearToggles();
+                    final ActionModel actionModelHint = model.getActionModelHint();
+                    if(actionModelHint != null && actionModelHint.getActionMemento().getAction().getSemantics().isIdempotentInNature()) {
+                        ObjectAdapter resultAdapter = actionModelHint.getObject();
+                        model.setObjectList(resultAdapter);
+                    } else {
+                        model.setObject(persistentAdaptersWithin(model.getObject()));
+                    }
+                    
+                    if(lastReturnedAdapter != null) {
+                        final ActionResultResponse resultResponse = 
+                                ActionResultResponseType.determineAndInterpretResult(actionModelHint, null, lastReturnedAdapter);
+                        resultResponse.getHandlingStrategy().handleResults(this, resultResponse);
+                    }
+
+                } catch(final ConcurrencyException ex) {
+                    
+                    recover();
+                    // display a warning to the user so that they know that the action wasn't performed
+                    getMessageBroker().addWarning(ex.getMessage());
+                    return;
+
+                } catch(final RuntimeException ex) {
+                    
+                    final RecoverableException appEx = ActionModel.getApplicationExceptionIfAny(ex);
+                    if (appEx != null) {
+
+                        recover();
+                        
+                        getMessageBroker().setApplicationError(appEx.getMessage());
+                        
+                        // there's no need to abort the transaction, it will have already been done
+                        // (in IsisTransactionManager#executeWithinTransaction(...)). 
+                        return;
+                    } 
+                    throw ex;
+                }
+            }
+            
+            private void recover() {
+                // resync with the objectstore
+                final List<ObjectAdapterMemento> toggleMementosList = Lists.newArrayList(model.getToggleMementosList());
+                for (ObjectAdapterMemento oam : toggleMementosList) {
+                    // just requesting the adapter will sync the OAM's version with the objectstore
+                    oam.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+                }
+                
+                // discard any adapters that might have been deleted
+                model.setObject(persistentAdaptersWithin(model.getObject()));
+                
+                // attempt to preserve the toggled adapters
+                final List<ObjectAdapter> adapters = model.getObject();
+                model.clearToggleMementosList();
+                for (ObjectAdapterMemento oam : toggleMementosList) {
+                    final ObjectAdapter objectAdapter = oam.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
+                    if(adapters.contains(objectAdapter)) {
+                        // in case it has been deleted...
+                        model.toggleSelectionOn(objectAdapter);
+                    }
+                }
+            }
+
+            private List<ObjectAdapter> persistentAdaptersWithin(List<ObjectAdapter> adapters) {
+                return Lists.newArrayList(Iterables.filter(adapters, new Predicate<ObjectAdapter>() {
+                    @Override
+                    public boolean apply(ObjectAdapter input) {
+                        return !input.isTransient() && !input.isDestroyed();
+                    }
+                }));
+            }
+
+        };
+        link.add(new JGrowlBehaviour());
+        final boolean explorationOrPrototype = CssMenuItem.isExplorationOrPrototype(objectAction);
+        final String actionIdentifier = CssMenuItem.actionIdentifierFor(objectAction);
+        final String cssClass = CssMenuItem.cssClassFor(objectAction);
+        final String cssClassFa = CssMenuItem.cssClassFaFor(objectAction);
+
+        return new LinkAndLabel(link, objectAction.getName(), null, false, explorationOrPrototype, actionIdentifier, cssClass, cssClassFa);
+    }
+    
+    
+    ///////////////////////////////////////////////////////
+    // Dependencies (from context)
+    ///////////////////////////////////////////////////////
+
+    public AuthenticationSession getAuthenticationSession() {
+        final AuthenticationSessionProvider asa = (AuthenticationSessionProvider) Session.get();
+        return asa.getAuthenticationSession();
+    }
+
+    protected MessageBroker getMessageBroker() {
+        return getAuthenticationSession().getMessageBroker();
+    }
+
+    protected ServicesInjector getServicesInjector() {
+        return IsisContext.getPersistenceSession().getServicesInjector();
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java
new file mode 100644
index 0000000..39f2b96
--- /dev/null
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/bulk/BulkActionsProvider.java
@@ -0,0 +1,28 @@
+/*
+ *  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.bulk;
+
+import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
+
+public interface BulkActionsProvider {
+
+    void configureBulkActions(ObjectAdapterToggleboxColumn toggleboxColumn);
+
+    ObjectAdapterToggleboxColumn createToggleboxColumn();
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java
index eed5607..8261496 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorHelper.java
@@ -20,7 +20,6 @@
 package org.apache.isis.viewer.wicket.ui.components.collection.selector;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.List;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
@@ -45,9 +44,6 @@ public class CollectionSelectorHelper implements Serializable {
 
     static final String UIHINT_EVENT_VIEW_KEY = "view";
 
-    private static final ComponentFactory ignoreFactory = new CollectionContentsMultipleViewsPanelFactory();
-    private static final ComponentType componentType = ComponentType.COLLECTION_CONTENTS; // this.ignoreFactory.getComponentType();;
-
     private final EntityCollectionModel model;
     private final List<ComponentFactory> componentFactories;
 
@@ -55,23 +51,24 @@ public class CollectionSelectorHelper implements Serializable {
             final EntityCollectionModel model,
             final ComponentFactoryRegistry componentFactoryRegistry) {
         this.model = model;
-        this.componentFactories = findOtherComponentFactories(componentFactoryRegistry);
+        this.componentFactories = locateComponentFactories(componentFactoryRegistry);
     }
 
-    public List<ComponentFactory> findOtherComponentFactories(ComponentFactoryRegistry componentFactoryRegistry) {
-        if(componentFactories != null) {
-            return componentFactories;
-        }
-        final List<ComponentFactory> componentFactories = componentFactoryRegistry.findComponentFactories(componentType, model);
-        ArrayList<ComponentFactory> otherFactories = Lists.newArrayList(Collections2.filter(componentFactories, new Predicate<ComponentFactory>() {
+    private List<ComponentFactory> locateComponentFactories(ComponentFactoryRegistry componentFactoryRegistry) {
+        final List<ComponentFactory> componentFactories = componentFactoryRegistry.findComponentFactories(ComponentType.COLLECTION_CONTENTS, model);
+        List<ComponentFactory> otherFactories = Lists.newArrayList(Collections2.filter(componentFactories, new Predicate<ComponentFactory>() {
             @Override
             public boolean apply(final ComponentFactory input) {
-                return input != ignoreFactory && input.getClass() != CollectionContentsMultipleViewsPanelFactory.class;
+                return input.getClass() != CollectionContentsMultipleViewsPanelFactory.class;
             }
         }));
         return ordered(otherFactories);
     }
 
+    public List<ComponentFactory> getComponentFactories() {
+        return componentFactories;
+    }
+
     public int honourViewHintElseDefault(final Component component) {
         // honour hints ...
         final UiHintContainer hintContainer = getUiHintContainer(component);
@@ -100,6 +97,26 @@ public class CollectionSelectorHelper implements Serializable {
 
     //region > helpers
 
+    /**
+     * return the index of {@link org.apache.isis.viewer.wicket.ui.components.collectioncontents.unresolved.CollectionContentsAsUnresolvedPanelFactory unresolved panel} if present and not eager loading;
+     * else the index of {@link org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanelFactory ajax table} if present,
+     * otherwise first factory.
+     */
+    private int determineInitialFactory() {
+        if(!hasRenderEagerlyFacet(model)) {
+            for(int i=0; i<componentFactories.size(); i++) {
+                if(componentFactories.get(i) instanceof CollectionContentsAsUnresolvedPanelFactory) {
+                    return i;
+                }
+            }
+        }
+        int ajaxTableIdx = findAjaxTable(componentFactories);
+        if(ajaxTableIdx>=0) {
+            return ajaxTableIdx;
+        }
+        return 0;
+    }
+
     private static List<ComponentFactory> ordered(List<ComponentFactory> componentFactories) {
         return orderAjaxTableToEnd(componentFactories);
     }
@@ -126,29 +143,6 @@ public class CollectionSelectorHelper implements Serializable {
     }
 
 
-
-
-
-    /**
-     * return the index of {@link org.apache.isis.viewer.wicket.ui.components.collectioncontents.unresolved.CollectionContentsAsUnresolvedPanelFactory unresolved panel} if present and not eager loading;
-     * else the index of {@link org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.CollectionContentsAsAjaxTablePanelFactory ajax table} if present,
-     * otherwise first factory.
-     */
-    protected int determineInitialFactory() {
-        if(!hasRenderEagerlyFacet(model)) {
-            for(int i=0; i<componentFactories.size(); i++) {
-                if(componentFactories.get(i) instanceof CollectionContentsAsUnresolvedPanelFactory) {
-                    return i;
-                }
-            }
-        }
-        int ajaxTableIdx = CollectionSelectorHelper.findAjaxTable(componentFactories);
-        if(ajaxTableIdx>=0) {
-            return ajaxTableIdx;
-        }
-        return 0;
-    }
-
     private static UiHintContainer getUiHintContainer(final Component component) {
         return UiHintContainer.Util.hintContainerOf(component);
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java
index 8cdc710..2033f3d 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collection/selector/CollectionSelectorPanel.java
@@ -88,7 +88,7 @@ public class CollectionSelectorPanel
 
 
     private void addDropdown() {
-        final List<ComponentFactory> componentFactories = selectorHelper.findOtherComponentFactories(getComponentFactoryRegistry());
+        final List<ComponentFactory> componentFactories = selectorHelper.getComponentFactories();
         final int selected = selectorHelper.honourViewHintElseDefault(this);
 
         // selector

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsHelper.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsHelper.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsHelper.java
deleted file mode 100644
index 0c2822f..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsHelper.java
+++ /dev/null
@@ -1,102 +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 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.Lists;
-import org.apache.isis.applib.filter.Filters;
-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.context.IsisContext;
-import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
-
-public class BulkActionsHelper implements Serializable {
-
-    private final EntityCollectionModel model;
-
-    private static final long serialVersionUID = 1L;
-
-    public BulkActionsHelper(final EntityCollectionModel model) {
-        this.model = model;
-    }
-
-    private EntityCollectionModel getModel() {
-        return model;
-    }
-
-    public List<ObjectAction> getBulkActions() {
-        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());
-
-        if ( isExploring() || isPrototyping()) {
-            List<ObjectAction> explorationActions = typeSpec.getObjectActions(ActionType.EXPLORATION, Contributed.INCLUDED, Filters.<ObjectAction>any());
-            List<ObjectAction> prototypeActions = typeSpec.getObjectActions(ActionType.PROTOTYPE, Contributed.INCLUDED, Filters.<ObjectAction>any());
-            objectActions.addAll(explorationActions);
-            objectActions.addAll(prototypeActions);
-        }
-        if (isDebugMode()) {
-            List<ObjectAction> debugActions = typeSpec.getObjectActions(ActionType.DEBUG, Contributed.INCLUDED, Filters.<ObjectAction>any());
-            objectActions.addAll(debugActions);
-        }
-
-        List<ObjectAction> flattenedActions = objectActions;
-
-        return Lists.newArrayList(Iterables.filter(flattenedActions, BULK));
-    }
-
-
-    @SuppressWarnings("deprecation")
-    private static final Predicate<ObjectAction> BULK = Filters.asPredicate(ObjectAction.Filters.bulk());
-
-
-    //region > from context
-
-    public boolean isExploring() {
-        return IsisContext.getDeploymentType().isExploring();
-    }
-    public boolean isPrototyping() {
-        return IsisContext.getDeploymentType().isPrototyping();
-    }
-
-    /**
-     * Protected so can be overridden in testing if required.
-     */
-    protected boolean isDebugMode() {
-        // TODO: need to figure out how to switch into debug mode;
-        // probably call a Debug toggle page, and stuff into
-        // Session.getMetaData()
-        return true;
-    }
-
-    //endregion
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/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
deleted file mode 100644
index efc68c1..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsLinkFactory.java
+++ /dev/null
@@ -1,229 +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 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.Session;
-import org.apache.wicket.markup.html.link.AbstractLink;
-import org.apache.wicket.markup.html.link.Link;
-import org.apache.isis.applib.RecoverableException;
-import org.apache.isis.applib.annotation.Bulk;
-import org.apache.isis.applib.annotation.Bulk.InteractionContext.InvokedAs;
-import org.apache.isis.applib.services.command.Command;
-import org.apache.isis.applib.services.command.Command.Executor;
-import org.apache.isis.applib.services.command.CommandContext;
-import org.apache.isis.core.commons.authentication.AuthenticationSession;
-import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider;
-import org.apache.isis.core.commons.authentication.MessageBroker;
-import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
-import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
-import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
-import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
-import org.apache.isis.core.runtime.system.context.IsisContext;
-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.ActionModel;
-import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
-import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
-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;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuItem;
-import org.apache.isis.viewer.wicket.ui.errors.JGrowlBehaviour;
-
-public final class BulkActionsLinkFactory implements ActionLinkFactory {
-    
-    private static final long serialVersionUID = 1L;
-    private final EntityCollectionModel model;
-    
-    private final ObjectAdapterToggleboxColumn toggleboxColumn;
-
-    public BulkActionsLinkFactory(
-            final EntityCollectionModel model,
-            final ObjectAdapterToggleboxColumn toggleboxColumn) {
-        this.model = model;
-        this.toggleboxColumn = toggleboxColumn;
-    }
-
-
-    @Override
-    public LinkAndLabel newLink(
-            final ObjectAdapterMemento serviceAdapterMemento,
-            final ObjectAction objectAction,
-            final String linkId,
-            final ActionPromptProvider actionPromptProvider) {
-        
-        final ActionMemento actionMemento = new ActionMemento(objectAction);
-        final AbstractLink link = new Link<Object>(linkId) {
-            
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            public void onClick() {
-                final ObjectAction objectAction = actionMemento.getAction();
-                final ConcurrencyChecking concurrencyChecking = 
-                        ConcurrencyChecking.concurrencyCheckingFor(objectAction.getSemantics());
-
-                try {
-                    final List<ObjectAdapterMemento> toggleMementosList = model.getToggleMementosList();
-
-                    final Iterable<ObjectAdapter> toggledAdapters = 
-                            Iterables.transform(toggleMementosList, ObjectAdapterMemento.Functions.fromMemento(concurrencyChecking));
-                    
-                    final List<Object> domainObjects = Lists.newArrayList(Iterables.transform(toggledAdapters, ObjectAdapter.Functions.getObject()));
-                    
-                    
-                    final Bulk.InteractionContext bulkInteractionContext = Bulk.InteractionContext.current.get();
-                    if (bulkInteractionContext != null) {
-                        bulkInteractionContext.setInvokedAs(InvokedAs.BULK);
-                        bulkInteractionContext.setDomainObjects(domainObjects);
-                    }
-                    
-                    final CommandContext commandContext = getServicesInjector().lookupService(CommandContext.class);
-                    final Command command;
-                    if (commandContext != null) {
-                        command = commandContext.getCommand();
-                        command.setExecutor(Executor.USER);
-                    }
-
-
-                    ObjectAdapter lastReturnedAdapter = null;
-                    int i=0;
-                    for(final ObjectAdapter adapter : toggledAdapters) {
-    
-                        int numParameters = objectAction.getParameterCount();
-                        if(numParameters != 0) {
-                            return;
-                        }
-                        if (bulkInteractionContext != null) {
-                            bulkInteractionContext.setIndex(i++);
-                        }
-
-                        lastReturnedAdapter = objectAction.executeWithRuleChecking(adapter, new ObjectAdapter[]{}, getAuthenticationSession(), ActionModel.WHERE_FOR_ACTION_INVOCATION);
-                    }
-
-
-                    
-                    model.clearToggleMementosList();
-                    toggleboxColumn.clearToggles();
-                    final ActionModel actionModelHint = model.getActionModelHint();
-                    if(actionModelHint != null && actionModelHint.getActionMemento().getAction().getSemantics().isIdempotentInNature()) {
-                        ObjectAdapter resultAdapter = actionModelHint.getObject();
-                        model.setObjectList(resultAdapter);
-                    } else {
-                        model.setObject(persistentAdaptersWithin(model.getObject()));
-                    }
-                    
-                    if(lastReturnedAdapter != null) {
-                        final ActionResultResponse resultResponse = 
-                                ActionResultResponseType.determineAndInterpretResult(actionModelHint, null, lastReturnedAdapter);
-                        resultResponse.getHandlingStrategy().handleResults(this, resultResponse);
-                    }
-
-                } catch(final ConcurrencyException ex) {
-                    
-                    recover();
-                    // display a warning to the user so that they know that the action wasn't performed
-                    getMessageBroker().addWarning(ex.getMessage());
-                    return;
-
-                } catch(final RuntimeException ex) {
-                    
-                    final RecoverableException appEx = ActionModel.getApplicationExceptionIfAny(ex);
-                    if (appEx != null) {
-
-                        recover();
-                        
-                        getMessageBroker().setApplicationError(appEx.getMessage());
-                        
-                        // there's no need to abort the transaction, it will have already been done
-                        // (in IsisTransactionManager#executeWithinTransaction(...)). 
-                        return;
-                    } 
-                    throw ex;
-                }
-            }
-            
-            private void recover() {
-                // resync with the objectstore
-                final List<ObjectAdapterMemento> toggleMementosList = Lists.newArrayList(model.getToggleMementosList());
-                for (ObjectAdapterMemento oam : toggleMementosList) {
-                    // just requesting the adapter will sync the OAM's version with the objectstore
-                    oam.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-                }
-                
-                // discard any adapters that might have been deleted
-                model.setObject(persistentAdaptersWithin(model.getObject()));
-                
-                // attempt to preserve the toggled adapters
-                final List<ObjectAdapter> adapters = model.getObject();
-                model.clearToggleMementosList();
-                for (ObjectAdapterMemento oam : toggleMementosList) {
-                    final ObjectAdapter objectAdapter = oam.getObjectAdapter(ConcurrencyChecking.NO_CHECK);
-                    if(adapters.contains(objectAdapter)) {
-                        // in case it has been deleted...
-                        model.toggleSelectionOn(objectAdapter);
-                    }
-                }
-            }
-
-            private List<ObjectAdapter> persistentAdaptersWithin(List<ObjectAdapter> adapters) {
-                return Lists.newArrayList(Iterables.filter(adapters, new Predicate<ObjectAdapter>() {
-                    @Override
-                    public boolean apply(ObjectAdapter input) {
-                        return !input.isTransient() && !input.isDestroyed();
-                    }
-                }));
-            }
-
-        };
-        link.add(new JGrowlBehaviour());
-        final boolean explorationOrPrototype = CssMenuItem.isExplorationOrPrototype(objectAction);
-        final String actionIdentifier = CssMenuItem.actionIdentifierFor(objectAction);
-        final String cssClass = CssMenuItem.cssClassFor(objectAction);
-        final String cssClassFa = CssMenuItem.cssClassFaFor(objectAction);
-
-        return new LinkAndLabel(link, objectAction.getName(), null, false, explorationOrPrototype, actionIdentifier, cssClass, cssClassFa);
-    }
-    
-    
-    ///////////////////////////////////////////////////////
-    // Dependencies (from context)
-    ///////////////////////////////////////////////////////
-
-    public AuthenticationSession getAuthenticationSession() {
-        final AuthenticationSessionProvider asa = (AuthenticationSessionProvider) Session.get();
-        return asa.getAuthenticationSession();
-    }
-
-    protected MessageBroker getMessageBroker() {
-        return getAuthenticationSession().getMessageBroker();
-    }
-
-    protected ServicesInjector getServicesInjector() {
-        return IsisContext.getPersistenceSession().getServicesInjector();
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsProvider.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsProvider.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsProvider.java
deleted file mode 100644
index 2ab87a3..0000000
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/BulkActionsProvider.java
+++ /dev/null
@@ -1,28 +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.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
-
-public interface BulkActionsProvider {
-
-    void configureBulkActionsProvider(ObjectAdapterToggleboxColumn toggleboxColumn);
-
-    ObjectAdapterToggleboxColumn createToggleboxColumn();
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/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 b53427b..6158ba3 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
@@ -40,11 +40,13 @@ import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
 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.ObjectAssociation;
-import org.apache.isis.viewer.wicket.model.common.SelectionHandler;
+import org.apache.isis.viewer.wicket.model.common.OnConcurrencyExceptionHandler;
 import org.apache.isis.viewer.wicket.model.hints.UiHintPathSignificant;
 import org.apache.isis.viewer.wicket.model.isis.WicketViewerSettings;
 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;
+import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsProvider;
 import org.apache.isis.viewer.wicket.ui.components.collection.count.CollectionCountProvider;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ColumnAbstract;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterPropertyColumn;
@@ -91,41 +93,13 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         ObjectAdapterToggleboxColumn toggleboxColumn = null;
         if(bulkActionsProvider != null) {
 
-//            List<ObjectAction> bulkActions = bulkActionsProvider.getBulkActions();
-//            if(!bulkActions.isEmpty()) {
-
             toggleboxColumn = bulkActionsProvider.createToggleboxColumn();
             if(toggleboxColumn != null) {
                 columns.add(toggleboxColumn);
             }
-            bulkActionsProvider.configureBulkActionsProvider(toggleboxColumn);
-
-//            }
-
+            bulkActionsProvider.configureBulkActions(toggleboxColumn);
         }
 
-//        } else {
-//        if(bulkActions.isEmpty() || getModel().isParented()) {
-//            //permanentlyHide(ID_ENTITY_ACTIONS);
-//            getBulkActionsProvider().configureBulkActionsProvider(null, null);
-//        } else {
-
-//            actionLinkFactoryDelegating = new ActionLinkFactoryDelegating();
-//            actionPromptProviderDelegating = new ActionPromptProviderDelegating();
-
-            //getBulkActionsProvider().configureBulkActionsProvider(linkFactory, this);
-//            getBulkActionsProvider().configureBulkActionsProvider(linkFactory, null);
-
-//            final CssMenuBuilder cssMenuBuilder = new CssMenuBuilder(null, bulkActions, actionLinkFactoryDelegating, actionPromptProviderDelegating, null);
-//            final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions");
-//
-//            this.addOrReplace(cssMenuPanel);
-
-  //      }
-
-        //List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions();
-
-
         final EntityCollectionModel model = getModel();
         addTitleColumn(columns, model.getParentObjectAdapterMemento(), getSettings().getMaxTitleLengthInStandaloneTables(), getSettings().getMaxTitleLengthInStandaloneTables());
         addPropertyColumnsIfRequired(columns);
@@ -136,19 +110,11 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
         dataTable.honourHints();
 
         if(toggleboxColumn != null) {
-            final SelectionHandler handler = new SelectionHandler() {
+            final OnConcurrencyExceptionHandler handler2 = new OnConcurrencyExceptionHandler() {
 
                 private static final long serialVersionUID = 1L;
 
                 @Override
-                public void onSelected(
-                        final Component context,
-                        final ObjectAdapter selectedAdapter,
-                        final AjaxRequestTarget ajaxRequestTarget) {
-                    model.toggleSelectionOn(selectedAdapter);
-                }
-
-                @Override
                 public void onConcurrencyException(
                         final Component context,
                         final ObjectAdapter selectedAdapter,
@@ -164,11 +130,8 @@ public class CollectionContentsAsAjaxTablePanel extends PanelAbstract<EntityColl
                     ajaxRequestTarget.add(dataTable);
                 }
             };
-            toggleboxColumn.setHandler(handler);
+            toggleboxColumn.setOnConcurrencyExceptionHandler(handler2);
         }
-
-        //addActionPromptModalWindow();
-
     }
 
     private BulkActionsProvider getBulkActionsProvider() {

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
index 31bb8ce..612abcd 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/ajaxtable/columns/ObjectAdapterToggleboxColumn.java
@@ -30,7 +30,8 @@ import org.apache.wicket.model.IModel;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager.ConcurrencyChecking;
 import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
-import org.apache.isis.viewer.wicket.model.common.SelectionHandler;
+import org.apache.isis.viewer.wicket.model.common.OnConcurrencyExceptionHandler;
+import org.apache.isis.viewer.wicket.model.common.OnSelectionHandler;
 import org.apache.isis.viewer.wicket.model.models.EntityModel;
 import org.apache.isis.viewer.wicket.ui.components.widgets.checkbox.ContainedToggleboxPanel;
 import org.apache.isis.viewer.wicket.ui.util.CssClassAppender;
@@ -39,21 +40,43 @@ public final class ObjectAdapterToggleboxColumn extends ColumnAbstract<ObjectAda
 
     private static final long serialVersionUID = 1L;
 
-    private SelectionHandler handler;
 
     public ObjectAdapterToggleboxColumn() {
-        this(null);
+        this(null, null);
     }
     
-    public ObjectAdapterToggleboxColumn(final SelectionHandler handler) {
+    public ObjectAdapterToggleboxColumn(
+            final OnSelectionHandler onSelectionHandler,
+            final OnConcurrencyExceptionHandler onConcurrencyExceptionHandler) {
         super("");
-        this.handler = handler;
+        this.onSelectionHandler = onSelectionHandler;
+        this.onConcurrencyExceptionHandler = onConcurrencyExceptionHandler;
     }
 
-    public void setHandler(SelectionHandler handler) {
-        this.handler = handler;
+    //region > OnSelectionHandler
+    private OnSelectionHandler onSelectionHandler;
+    public OnSelectionHandler getOnSelectionHandler() {
+        return onSelectionHandler;
     }
 
+    public void setOnSelectionHandler(OnSelectionHandler onSelectionHandler) {
+        this.onSelectionHandler = onSelectionHandler;
+    }
+    //endregion
+
+    //region > OnConcurrencyExceptionHandler
+
+    private OnConcurrencyExceptionHandler onConcurrencyExceptionHandler;
+    public OnConcurrencyExceptionHandler getOnConcurrencyExceptionHandler() {
+        return onConcurrencyExceptionHandler;
+    }
+
+    public void setOnConcurrencyExceptionHandler(OnConcurrencyExceptionHandler onConcurrencyExceptionHandler) {
+        this.onConcurrencyExceptionHandler = onConcurrencyExceptionHandler;
+    }
+    //endregion
+
+
     @Override
     public Component getHeader(String componentId) {
         
@@ -90,15 +113,15 @@ public final class ObjectAdapterToggleboxColumn extends ColumnAbstract<ObjectAda
                 ObjectAdapter selectedAdapter = null;
                 try {
                     selectedAdapter = entityModel.load(ConcurrencyChecking.CHECK);
-                    if(handler != null) {
-                        handler.onSelected(this, selectedAdapter, target);
+                    if(onSelectionHandler != null) {
+                        onSelectionHandler.onSelected(this, selectedAdapter, target);
                     }
                 } catch(ConcurrencyException ex) {
 
                     // should work second time, because the previous attempt will have updated the OAM's OIDs version.
                     selectedAdapter = entityModel.load(ConcurrencyChecking.CHECK);
-                    if(handler != null) {
-                        handler.onConcurrencyException(this, selectedAdapter, ex, target);
+                    if(onConcurrencyExceptionHandler != null) {
+                        onConcurrencyExceptionHandler.onConcurrencyException(this, selectedAdapter, ex, target);
                     }
                     
                     entityModel.setException(ex);

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java
index e4a37b3..0a7019e 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/collectioncontents/multiple/CollectionContentsMultipleViewsPanel.java
@@ -91,12 +91,15 @@ public class CollectionContentsMultipleViewsPanel
     private void addUnderlyingViews() {
         final EntityCollectionModel model = getModel();
 
-        final int selected = selectorHelper.honourViewHintElseDefault(getSelectorDropdownPanel());
-        final List<ComponentFactory> componentFactories = selectorHelper.findOtherComponentFactories(getComponentFactoryRegistry());
+        final CollectionSelectorPanel selectorDropdownPanelIfAny = getSelectorDropdownPanel();
+        final int selected = selectorDropdownPanelIfAny != null
+                ? selectorHelper.honourViewHintElseDefault(selectorDropdownPanelIfAny)
+                : 0;
+        final List<ComponentFactory> componentFactories = selectorHelper.getComponentFactories();
 
         // create all, hide the one not selected
-        underlyingViews = new Component[MAX_NUM_UNDERLYING_VIEWS];
         int i = 0;
+        underlyingViews = new Component[MAX_NUM_UNDERLYING_VIEWS];
         final EntityCollectionModel emptyModel = model.asDummy();
         for (ComponentFactory componentFactory : componentFactories) {
             final String underlyingId = underlyingIdPrefix + "-" + i;
@@ -106,6 +109,12 @@ public class CollectionContentsMultipleViewsPanel
             this.addOrReplace(underlyingView);
         }
 
+        if(selectorDropdownPanelIfAny != null) {
+
+        } else {
+
+        }
+
         // hide any unused placeholders
         while(i<MAX_NUM_UNDERLYING_VIEWS) {
             String underlyingId = underlyingIdPrefix + "-" + i;
@@ -138,9 +147,15 @@ public class CollectionContentsMultipleViewsPanel
         final UiHintContainer uiHintContainer = uiHintEvent.getUiHintContainer();
 
         int underlyingViewNum = 0;
-        String viewStr = uiHintContainer.getHint(this.getSelectorDropdownPanel(), UIHINT_VIEW);
+        final CollectionSelectorPanel selectorDropdownPanel = this.getSelectorDropdownPanel();
+        if(selectorDropdownPanel == null) {
+            // not expected, because this event shouldn't be called.
+            // but no harm in simply returning...
+            return;
+        }
+        String viewStr = uiHintContainer.getHint(selectorDropdownPanel, UIHINT_VIEW);
 
-        List<ComponentFactory> componentFactories = selectorHelper.findOtherComponentFactories(getComponentFactoryRegistry());
+        List<ComponentFactory> componentFactories = selectorHelper.getComponentFactories();
 
         if(viewStr != null) {
             try {
@@ -170,7 +185,7 @@ public class CollectionContentsMultipleViewsPanel
 
         final AjaxRequestTarget target = uiHintEvent.getTarget();
         if(target != null) {
-            target.add(this, getSelectorDropdownPanel());
+            target.add(this, selectorDropdownPanel);
         }
 
     }
@@ -205,18 +220,15 @@ public class CollectionContentsMultipleViewsPanel
     /**
      * Searches up the component hierarchy looking for a parent that implements
      * {@link org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorProvider}.
-     * @return
+     *
+     * @return the panel, or null (if there are no alternative views)
      */
     private CollectionSelectorPanel getSelectorDropdownPanel() {
         Component component = this;
         while(component != null) {
             if(component instanceof CollectionSelectorProvider) {
-                final CollectionSelectorPanel selectorDropdownPanel1 = ((CollectionSelectorProvider) component).getSelectorDropdownPanel();
-                if(selectorDropdownPanel1 == null) {
-                    throw new IllegalStateException("Found parent that implements HasSelectorDropdownPanel, but no SelectorDropdownPanel available (is null)");
-
-                }
-                return selectorDropdownPanel1;
+                final CollectionSelectorPanel selectorDropdownPanelIfAny = ((CollectionSelectorProvider) component).getSelectorDropdownPanel();
+                return selectorDropdownPanelIfAny;
             }
             component = component.getParent();
         }

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
index beee965..93288b1 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/collections/EntityCollectionsPanel.java
@@ -130,7 +130,7 @@ public class EntityCollectionsPanel extends PanelAbstract<EntityModel> {
 
         final CollectionSelectorHelper selectorHelper = new CollectionSelectorHelper(entityCollectionModel, getComponentFactoryRegistry());
 
-        final List<ComponentFactory> componentFactories = selectorHelper.findOtherComponentFactories(getComponentFactoryRegistry());
+        final List<ComponentFactory> componentFactories = selectorHelper.getComponentFactories();
 
         if (componentFactories.size() <= 1) {
             permanentlyHide(ID_SELECTOR_DROPDOWN);

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
index a4e76ce..0473974 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/standalonecollection/StandaloneCollectionPanel.java
@@ -20,9 +20,13 @@
 package org.apache.isis.viewer.wicket.ui.components.standalonecollection;
 
 import java.util.List;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.model.Model;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.viewer.wicket.model.common.OnSelectionHandler;
 import org.apache.isis.viewer.wicket.model.models.ActionModel;
 import org.apache.isis.viewer.wicket.model.models.ActionPromptProvider;
 import org.apache.isis.viewer.wicket.model.models.EntityCollectionModel;
@@ -34,12 +38,11 @@ import org.apache.isis.viewer.wicket.ui.components.collection.count.CollectionCo
 import org.apache.isis.viewer.wicket.ui.components.collection.selector.CollectionSelectorHelper;
 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.BulkActionsHelper;
-import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.BulkActionsLinkFactory;
-import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.BulkActionsProvider;
+import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsHelper;
+import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsLinkFactory;
+import org.apache.isis.viewer.wicket.ui.components.collection.bulk.BulkActionsProvider;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn;
 import org.apache.isis.viewer.wicket.ui.components.collectioncontents.multiple.CollectionContentsMultipleViewsPanelFactory;
-import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.ActionLinkFactory;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuBuilder;
 import org.apache.isis.viewer.wicket.ui.components.widgets.cssmenu.CssMenuPanel;
 import org.apache.isis.viewer.wicket.ui.panels.PanelAbstract;
@@ -66,30 +69,23 @@ public class StandaloneCollectionPanel extends PanelAbstract<EntityCollectionMod
         bulkActionsHelper = new BulkActionsHelper(entityCollectionModel);
     }
 
+    /**
+     * note that the bulk actions components are added in {@link #configureBulkActions(org.apache.isis.viewer.wicket.ui.components.collectioncontents.ajaxtable.columns.ObjectAdapterToggleboxColumn)}.
+     */
     private void buildGui(final EntityCollectionModel entityCollectionModel) {
 
         ActionModel actionModel = entityCollectionModel.getActionModelHint();
         ObjectAction action = actionModel.getActionMemento().getAction();
         addOrReplace(new Label(StandaloneCollectionPanel.ID_ACTION_NAME, Model.of(action.getName())));
 
-        final CollectionSelectorHelper selectorHelper = new CollectionSelectorHelper(entityCollectionModel, getComponentFactoryRegistry());
-
-        final List<ComponentFactory> componentFactories = selectorHelper.findOtherComponentFactories(getComponentFactoryRegistry());
-
-
-
-        addActionPromptModalWindow();
-
-        // bulkactions ... in configureBulkActionsProvider
+        // action prompt
+        this.actionPromptModalWindow = ActionPromptModalWindow.newModalWindow(ID_ACTION_PROMPT_MODAL_WINDOW);
+        addOrReplace(actionPromptModalWindow);
 
-//        List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions();
-//
-//        if(bulkActions.isEmpty() || getModel().isParented()) {
-//            permanentlyHide(ID_ENTITY_ACTIONS);
-//        } else {
-//
-//        }
+        // selector
+        final CollectionSelectorHelper selectorHelper = new CollectionSelectorHelper(entityCollectionModel, getComponentFactoryRegistry());
 
+        final List<ComponentFactory> componentFactories = selectorHelper.getComponentFactories();
 
         if (componentFactories.size() <= 1) {
             permanentlyHide(ID_SELECTOR_DROPDOWN);
@@ -114,19 +110,6 @@ public class StandaloneCollectionPanel extends PanelAbstract<EntityCollectionMod
         componentFactoryRegistry.addOrReplaceComponent(this, ComponentType.COLLECTION_CONTENTS, entityCollectionModel);
     }
 
-    @Override
-    public Integer getCount() {
-        final EntityCollectionModel model = getModel();
-        return model.getCount();
-    }
-
-    @Override
-    public CollectionSelectorPanel getSelectorDropdownPanel() {
-        return selectorDropdownPanel;
-    }
-
-
-
     //region > ActionPromptModalWindowProvider
 
     private ActionPromptModalWindow actionPromptModalWindow;
@@ -134,97 +117,73 @@ public class StandaloneCollectionPanel extends PanelAbstract<EntityCollectionMod
         return ActionPromptModalWindow.getActionPromptModalWindowIfEnabled(actionPromptModalWindow);
     }
 
-    private void addActionPromptModalWindow() {
-        this.actionPromptModalWindow = ActionPromptModalWindow.newModalWindow(ID_ACTION_PROMPT_MODAL_WINDOW);
-        addOrReplace(actionPromptModalWindow);
-    }
-
     //endregion
 
-
-
+    //region > BulkActionsProvider
 
     @Override
-    public void configureBulkActionsProvider(ObjectAdapterToggleboxColumn toggleboxColumn) {
-        BulkActionsLinkFactory linkFactory = new BulkActionsLinkFactory(getModel(), toggleboxColumn);
-        configureBulkActionsProvider(linkFactory, this);
-    }
+    public ObjectAdapterToggleboxColumn createToggleboxColumn() {
 
-    private void configureBulkActionsProvider(
-            final ActionLinkFactory linkFactory,
-            final ActionPromptProvider actionPromptProvider) {
+        final List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions();
 
-        if(linkFactory != null) {
-            final List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions();
+        final EntityCollectionModel entityCollectionModel = getModel();
+        if(bulkActions.isEmpty() || entityCollectionModel.isParented()) {
+            return null;
+        }
 
-            final CssMenuBuilder cssMenuBuilder = new CssMenuBuilder(null, bulkActions, linkFactory, actionPromptProvider != null? actionPromptProvider: this, null);
-            final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions");
+        final ObjectAdapterToggleboxColumn toggleboxColumn = new ObjectAdapterToggleboxColumn();
+        final OnSelectionHandler handler = new OnSelectionHandler() {
 
-            addOrReplace(cssMenuPanel);
+            private static final long serialVersionUID = 1L;
 
-        } else {
-            permanentlyHide(ID_ENTITY_ACTIONS);
+            @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 List<ObjectAction> getBulkActions() {
-        return bulkActionsHelper.getBulkActions();
-    }
+        final BulkActionsLinkFactory linkFactory =
+                new BulkActionsLinkFactory(getModel(), toggleboxColumn);
+
+        final List<ObjectAction> bulkActions = bulkActionsHelper.getBulkActions();
 
-//    public static class ActionLinkFactoryDelegating implements ActionLinkFactory {
-//
-//        private ActionLinkFactory delegate;
-//
-//        public ActionLinkFactory getDelegate() {
-//            return delegate;
-//        }
-//
-//        public void setDelegate(ActionLinkFactory delegate) {
-//            this.delegate = delegate;
-//        }
-//
-//        @Override
-//        public LinkAndLabel newLink(
-//                final ObjectAdapterMemento adapter,
-//                final ObjectAction noAction,
-//                final String linkId,
-//                final ActionPromptProvider actionPromptProvider) {
-//            return delegate.newLink(adapter, noAction, linkId, actionPromptProvider);
-//        }
-//    }
-//
-//    public static class ActionPromptProviderDelegating implements ActionPromptProvider {
-//
-//        private ActionPromptProvider delegate;
-//
-//        public ActionPromptProvider getDelegate() {
-//            return delegate;
-//        }
-//
-//        public void setDelegate(ActionPromptProvider delegate) {
-//            this.delegate = delegate;
-//        }
-//
-//        @Override
-//        public ActionPrompt getActionPrompt() {
-//            return delegate.getActionPrompt();
-//        }
-//    }
+        final CssMenuBuilder cssMenuBuilder =
+                new CssMenuBuilder(null, bulkActions, linkFactory, this, null);
+        final CssMenuPanel cssMenuPanel = cssMenuBuilder.buildPanel(ID_ENTITY_ACTIONS, "Actions");
 
+        addOrReplace(cssMenuPanel);
+
+    }
+    //endregion
+
+    //region > CollectionSelectorProvider
 
     @Override
-    public ObjectAdapterToggleboxColumn createToggleboxColumn() {
+    public CollectionSelectorPanel getSelectorDropdownPanel() {
+        return selectorDropdownPanel;
+    }
 
-        final List<ObjectAction> bulkActions = getBulkActions();
+    //endregion
 
-        final EntityCollectionModel entityCollectionModel = getModel();
-        if(bulkActions.isEmpty() || entityCollectionModel.isParented()) {
-            return null;
-        }
+    //region > CollectionCountProvider
 
-        return new ObjectAdapterToggleboxColumn();
+    @Override
+    public Integer getCount() {
+        final EntityCollectionModel model = getModel();
+        return model.getCount();
     }
 
+    //endregion
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/cb2bea9a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
----------------------------------------------------------------------
diff --git a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
index 1a19d48..1cced6d 100644
--- a/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
+++ b/component/viewer/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/widgets/cssmenu/ActionLinkFactoryAbstract.java
@@ -86,7 +86,8 @@ public abstract class ActionLinkFactoryAbstract implements ActionLinkFactory {
      */
     protected AbstractLink newLink(
             final String linkId,
-            final ObjectAdapter objectAdapter, final ObjectAction action,
+            final ObjectAdapter objectAdapter,
+            final ObjectAction action,
             final ActionPromptProvider actionPromptProvider) {
         
         final ActionPrompt actionPrompt = actionPromptProvider.getActionPrompt();