You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2013/03/12 12:50:50 UTC

svn commit: r1455500 [1/2] - in /syncope/trunk: client/src/main/java/org/apache/syncope/client/services/proxy/ common/src/main/java/org/apache/syncope/common/services/ common/src/main/java/org/apache/syncope/common/to/ console/src/main/java/org/apache/...

Author: fmartelli
Date: Tue Mar 12 11:50:48 2013
New Revision: 1455500

URL: http://svn.apache.org/r1455500
Log:
SYNCOPE-198: provided table implementation and bulk actions for users

Added:
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java   (with props)
    syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java   (with props)
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionModalPage.java
      - copied, changed from r1450790, syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionResultModalPage.java
      - copied, changed from r1455107, syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResultStatusModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java   (with props)
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/ActionResultColumn.java   (with props)
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/CheckBoxGroupSelectorPanel.java   (with props)
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/CheckBoxPanel.java   (with props)
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/CheckGroupColumn.java   (with props)
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BulkActionModalPage.html
      - copied, changed from r1450790, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/StatusModalPage.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BulkActionModalPage.properties
      - copied, changed from r1450790, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BasePage.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BulkActionModalPage_it.properties
      - copied, changed from r1450790, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BasePage_it.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BulkActionResultModalPage.html
      - copied, changed from r1450790, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/StatusModalPage.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BulkActionResultModalPage.properties
      - copied, changed from r1450790, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BasePage.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BulkActionResultModalPage_it.properties
      - copied, changed from r1450790, syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/BasePage_it.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.html   (with props)
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/html/
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/html/repeater/
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/CheckBoxGroupSelectorPanel.html   (with props)
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/CheckBoxPanel.html   (with props)
    syncope/trunk/console/src/main/webapp/css/bulk.css   (with props)
    syncope/trunk/console/src/main/webapp/img/actions/bulk.png   (with props)
    syncope/trunk/console/src/main/webapp/img/actions/reactivate.png   (with props)
    syncope/trunk/console/src/main/webapp/img/actions/suspend.png   (with props)
Modified:
    syncope/trunk/client/src/main/java/org/apache/syncope/client/services/proxy/UserServiceProxy.java
    syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Configuration.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ReportModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Resources.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Schema.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/TaskModalPage.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Users.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PoliciesPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PropagationTasks.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SelectOnlyUserSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasks.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/UserSearchResultPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/AbstractAttributableRestClient.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/RoleRestClient.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/rest/UserRestClient.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/ActionLink.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/ActionLinksPanel.java
    syncope/trunk/console/src/main/java/org/apache/syncope/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/Users_it.properties
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.html
    syncope/trunk/console/src/main/resources/org/apache/syncope/console/wicket/markup/html/form/ActionLinksPanel.html
    syncope/trunk/console/src/test/java/org/apache/syncope/console/RoleTestITCase.java
    syncope/trunk/console/src/test/java/org/apache/syncope/console/UserTestITCase.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/policy/AccountPolicyEnforcer.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/rest/controller/UserController.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/services/UserServiceImpl.java
    syncope/trunk/core/src/main/java/org/apache/syncope/core/workflow/WorkflowUserSuspender.java
    syncope/trunk/core/src/test/java/org/apache/syncope/core/rest/UserTestITCase.java

Modified: syncope/trunk/client/src/main/java/org/apache/syncope/client/services/proxy/UserServiceProxy.java
URL: http://svn.apache.org/viewvc/syncope/trunk/client/src/main/java/org/apache/syncope/client/services/proxy/UserServiceProxy.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/client/src/main/java/org/apache/syncope/client/services/proxy/UserServiceProxy.java (original)
+++ syncope/trunk/client/src/main/java/org/apache/syncope/client/services/proxy/UserServiceProxy.java Tue Mar 12 11:50:48 2013
@@ -21,13 +21,13 @@ package org.apache.syncope.client.servic
 import java.net.URI;
 import java.util.Arrays;
 import java.util.List;
-
 import javax.ws.rs.core.Response;
-
 import org.apache.syncope.common.SyncopeConstants;
 import org.apache.syncope.common.mod.UserMod;
 import org.apache.syncope.common.search.NodeCond;
 import org.apache.syncope.common.services.UserService;
+import org.apache.syncope.common.to.BulkAction;
+import org.apache.syncope.common.to.BulkActionRes;
 import org.apache.syncope.common.to.PropagationRequestTO;
 import org.apache.syncope.common.to.UserTO;
 import org.springframework.web.client.RestTemplate;
@@ -179,4 +179,9 @@ public class UserServiceProxy extends Sp
     public int searchCount(final NodeCond searchCondition) {
         return getRestTemplate().postForObject(baseUrl + "user/search/count.json", searchCondition, Integer.class);
     }
+
+    @Override
+    public BulkActionRes bulkAction(final BulkAction bulkActions) {
+        return getRestTemplate().postForObject(baseUrl + "user/bulk", bulkActions, BulkActionRes.class);
+    }
 }

Modified: syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java (original)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/services/UserService.java Tue Mar 12 11:50:48 2013
@@ -19,7 +19,6 @@
 package org.apache.syncope.common.services;
 
 import java.util.List;
-
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
@@ -28,9 +27,10 @@ import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Response;
-
 import org.apache.syncope.common.mod.UserMod;
 import org.apache.syncope.common.search.NodeCond;
+import org.apache.syncope.common.to.BulkAction;
+import org.apache.syncope.common.to.BulkActionRes;
 import org.apache.syncope.common.to.PropagationRequestTO;
 import org.apache.syncope.common.to.UserTO;
 
@@ -66,7 +66,7 @@ public interface UserService {
     @Path("{userId}")
     UserTO delete(@PathParam("userId") Long userId);
 
-   @GET
+    @GET
     List<UserTO> list();
 
     @GET
@@ -132,4 +132,7 @@ public interface UserService {
     @Path("{userId}")
     UserTO update(@PathParam("userId") Long userId, UserMod userMod);
 
+    @POST
+    @Path("bulk")
+    BulkActionRes bulkAction(BulkAction bulkAction);
 }

Added: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java?rev=1455500&view=auto
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java (added)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java Tue Mar 12 11:50:48 2013
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.syncope.common.to;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.AbstractBaseBean;
+
+@XmlRootElement(name = "bulkAction")
+@XmlType
+public class BulkAction extends AbstractBaseBean {
+
+    @XmlEnum
+    @XmlType(name = "bulkActionType")
+    public enum Type {
+
+        DELETE,
+        REACTIVATE,
+        SUSPEND
+
+    }
+
+    private Type operation;
+
+    /**
+     * Serialized identifiers.
+     */
+    private Collection<String> targets;
+
+    public Type getOperation() {
+        return operation;
+    }
+
+    public void setOperation(Type operation) {
+        this.operation = operation;
+    }
+
+    public void setTargets(final Collection<String> targets) {
+        this.targets = targets;
+    }
+
+    public Collection<String> getTargets() {
+        return targets;
+    }
+
+    public void addTarget(final String target) {
+        if (this.targets == null) {
+            this.targets = new ArrayList();
+        }
+
+        this.targets.add(target);
+    }
+
+    public int size() {
+        return targets == null ? 0 : targets.size();
+    }
+}

Propchange: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkAction.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java
URL: http://svn.apache.org/viewvc/syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java?rev=1455500&view=auto
==============================================================================
--- syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java (added)
+++ syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java Tue Mar 12 11:50:48 2013
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.syncope.common.to;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.AbstractBaseBean;
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+@XmlRootElement(name = "BulkActionRes")
+@XmlType
+public class BulkActionRes extends AbstractBaseBean {
+
+    @XmlEnum
+    @XmlType(name = "bulkActionStatus")
+    public enum Status {
+
+        SUCCESS,
+        FAILURE
+
+    }
+
+    private List<Result> results;
+
+    public void setResults(final List<Result> results) {
+        this.results = results;
+    }
+
+    public List<Result> getResults() {
+        return results;
+    }
+
+    @JsonIgnore
+    public void add(final Object id, final Status status) {
+        if (results == null) {
+            results = new ArrayList<Result>();
+        }
+
+        if (id != null) {
+            results.add(new Result(id.toString(), status));
+        }
+    }
+
+    @JsonIgnore
+    public Map<String, Status> getResultMap() {
+        final Map<String, Status> res = new HashMap<String, Status>();
+        if (results != null) {
+            for (Result result : results) {
+                res.put(result.getKey(), result.getValue());
+            }
+        }
+        return res;
+    }
+
+    @JsonIgnore
+    public List getResultByStatus(final Status status) {
+        final List<String> res = new ArrayList<String>();
+        if (results != null) {
+            for (Result result : results) {
+                if (result.getValue() == status) {
+                    res.add(result.getKey());
+                }
+            }
+        }
+        return res;
+    }
+
+    public static class Result {
+
+        private String key;
+
+        private Status value;
+
+        public Result() {
+        }
+
+        public Result(String key, Status value) {
+            this.key = key;
+            this.value = value;
+        }
+
+        public String getKey() {
+            return key;
+        }
+
+        public Status getValue() {
+            return value;
+        }
+
+        public void setKey(String key) {
+            this.key = key;
+        }
+
+        public void setValue(Status value) {
+            this.value = value;
+        }
+    }
+}

Propchange: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: syncope/trunk/common/src/main/java/org/apache/syncope/common/to/BulkActionRes.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Copied: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionModalPage.java (from r1450790, syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionModalPage.java?p2=syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionModalPage.java&p1=syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java&r1=1450790&r2=1455500&rev=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/StatusModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionModalPage.java Tue Mar 12 11:50:48 2013
@@ -18,127 +18,139 @@
  */
 package org.apache.syncope.console.pages;
 
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
-import org.apache.syncope.common.to.AbstractAttributableTO;
-import org.apache.syncope.common.to.UserTO;
-import org.apache.syncope.console.commons.StatusBean;
-import org.apache.syncope.console.pages.panels.StatusPanel;
-import org.apache.syncope.console.rest.UserRestClient;
+import org.apache.syncope.common.to.BulkAction;
+import org.apache.syncope.common.to.BulkActionRes;
+import org.apache.syncope.console.rest.BaseRestClient;
 import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxButton;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
 import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
 import org.apache.wicket.model.ResourceModel;
-import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.springframework.beans.BeanUtils;
 
-public class StatusModalPage extends BaseModalPage {
+public class BulkActionModalPage<T, S> extends BaseModalPage {
 
-    private static final long serialVersionUID = 4114026480146090961L;
+    private static final long serialVersionUID = 4114026480146090962L;
 
-    @SpringBean
-    private UserRestClient userRestClient;
-
-    public StatusModalPage(final PageReference pageRef, final ModalWindow window,
-            final AbstractAttributableTO attributable) {
+    public BulkActionModalPage(
+            final PageReference pageRef,
+            final ModalWindow window,
+            final List<T> items,
+            final List<IColumn<T, S>> columns,
+            final Collection<ActionLink.ActionType> actions,
+            final BaseRestClient bulkActionExecutor,
+            final String idFieldName,
+            final String pageId) {
 
         super();
 
-        final Form form = new Form("form");
-        add(form);
-
-        final List<StatusBean> statuses = new ArrayList<StatusBean>();
-
-        final StatusPanel statusPanel = new StatusPanel("statuspanel", attributable, statuses);
-        form.add(statusPanel);
-
-        final AjaxButton disable;
-        if (attributable instanceof UserTO) {
-            disable = new ClearIndicatingAjaxButton("disable", new ResourceModel("disable", "Disable"), pageRef) {
+        final SortableDataProvider<T, S> dataProvider = new SortableDataProvider<T, S>() {
 
-                private static final long serialVersionUID = -958724007591692537L;
-
-                @Override
-                protected void onSubmitInternal(final AjaxRequestTarget target, final Form form) {
-                    try {
-                        userRestClient.suspend(attributable.getId(), statuses);
+            @Override
+            public Iterator<? extends T> iterator(long first, long count) {
+                return items.iterator();
+            }
 
-                        if (pageRef.getPage() instanceof BasePage) {
-                            ((BasePage) pageRef.getPage()).setModalResult(true);
-                        }
+            @Override
+            public long size() {
+                return items.size();
+            }
 
-                        window.close(target);
-                    } catch (Exception e) {
-                        LOG.error("Error disabling resources", e);
-                        error(getString("error") + ":" + e.getMessage());
-                        target.add(feedbackPanel);
-                    }
-                }
+            @Override
+            public IModel<T> model(T object) {
+                return new CompoundPropertyModel<T>(object);
+            }
+        };
 
-                @Override
-                protected void onError(final AjaxRequestTarget target, final Form<?> form) {
-                    target.add(feedbackPanel);
+        add(new AjaxFallbackDefaultDataTable<T, S>(
+                "selectedObjects",
+                new ArrayList<IColumn<T, S>>(columns.subList(1, columns.size() - 1)),
+                dataProvider,
+                Integer.MAX_VALUE).setVisible(items != null && !items.isEmpty()));
+
+        final ActionLinksPanel actionPanel = new ActionLinksPanel("actions", new Model(), getPageReference());
+        add(actionPanel);
+
+        for (ActionLink.ActionType action : actions) {
+            final BulkAction bulkAction = new BulkAction();
+            for (Object item : items) {
+                try {
+                    bulkAction.addTarget(getTargetId(item, idFieldName).toString());
+                } catch (Exception e) {
+                    LOG.error("Error retrieving item id {}", idFieldName, e);
                 }
-            };
-        } else {
-            disable = new AjaxButton("disable") {
-
-                private static final long serialVersionUID = 5538299138211283825L;
-
-            };
-            disable.setVisible(false);
-        }
-        form.add(disable);
+            }
 
-        final AjaxButton enable;
-        if (attributable instanceof UserTO) {
-            enable = new ClearIndicatingAjaxButton("enable", new ResourceModel("enable", "Enable"), pageRef) {
+            switch (action) {
+                case DELETE:
+                    bulkAction.setOperation(BulkAction.Type.DELETE);
+                    break;
+                case SUSPEND:
+                    bulkAction.setOperation(BulkAction.Type.SUSPEND);
+                    break;
+                case REACTIVATE:
+                    bulkAction.setOperation(BulkAction.Type.REACTIVATE);
+                    break;
+                default:
+                    LOG.error("Bulk action type not supported");
+            }
 
-                private static final long serialVersionUID = -958724007591692537L;
+            actionPanel.add(new ActionLink() {
 
                 @Override
-                protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                public void onClick(final AjaxRequestTarget target) {
                     try {
-                        userRestClient.reactivate(attributable.getId(), statuses);
-
-                        ((BasePage) pageRef.getPage()).setModalResult(true);
+                        final BulkActionRes res = (BulkActionRes) bulkActionExecutor.getClass().
+                                getMethod("bulkAction", BulkAction.class).invoke(bulkActionExecutor, bulkAction);
 
-                        window.close(target);
+                        setResponsePage(new BulkActionResultModalPage(pageRef, window, items, columns, res, idFieldName));
                     } catch (Exception e) {
-                        LOG.error("Error enabling resources", e);
-                        error(getString("error") + ":" + e.getMessage());
-                        target.add(feedbackPanel);
+                        LOG.error("Operation {} not supported", bulkAction.getOperation(), e);
                     }
-                }
 
-                @Override
-                protected void onError(final AjaxRequestTarget target, final Form<?> form) {
-
-                    target.add(feedbackPanel);
                 }
-            };
-        } else {
-            enable = new AjaxButton("enable") {
+            }, action, pageId, !items.isEmpty());
+        }
 
-                private static final long serialVersionUID = 5538299138211283825L;
+        final Form form = new Form("form");
+        add(form);
 
-            };
-            enable.setVisible(false);
-        }
-        form.add(enable);
+        final AjaxButton cancel =
+                new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), getPageReference()) {
 
-        final AjaxButton cancel = new ClearIndicatingAjaxButton("cancel", new ResourceModel("cancel"), pageRef) {
+                    private static final long serialVersionUID = -958724007591692537L;
 
-            private static final long serialVersionUID = -958724007591692537L;
+                    @Override
+                    protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                        window.close(target);
+                    }
+                };
 
-            @Override
-            protected void onSubmitInternal(final AjaxRequestTarget target, final Form form) {
-                window.close(target);
-            }
-        };
         cancel.setDefaultFormProcessing(false);
         form.add(cancel);
     }
+
+    private Object getTargetId(final Object target, final String idFieldName)
+            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+        final PropertyDescriptor propDesc =
+                BeanUtils.getPropertyDescriptor(target.getClass(), idFieldName);
+        final Object id = propDesc.getReadMethod().invoke(target, new Object[0]);
+        return id;
+    }
 }

Copied: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionResultModalPage.java (from r1455107, syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResultStatusModalPage.java)
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionResultModalPage.java?p2=syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionResultModalPage.java&p1=syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResultStatusModalPage.java&r1=1455107&r2=1455500&rev=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ResultStatusModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/BulkActionResultModalPage.java Tue Mar 12 11:50:48 2013
@@ -19,347 +19,79 @@
 package org.apache.syncope.console.pages;
 
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.syncope.common.to.AbstractAttributableTO;
-import org.apache.syncope.common.to.AttributeTO;
-import org.apache.syncope.common.to.ConnObjectTO;
-import org.apache.syncope.common.to.PropagationStatusTO;
-import org.apache.syncope.common.to.RoleTO;
-import org.apache.syncope.common.to.UserTO;
-import org.apache.syncope.common.types.PropagationTaskExecStatus;
-import org.apache.syncope.console.commons.StatusUtils;
-import org.apache.syncope.console.rest.UserRestClient;
-import org.apache.wicket.Component;
+import org.apache.syncope.common.to.BulkActionRes;
+import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionResultColumn;
+import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
-import org.apache.wicket.behavior.Behavior;
 import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.image.Image;
-import org.apache.wicket.markup.html.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.model.ResourceModel;
-import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.IModel;
 
 /**
  * Show user or role status after performing a successful operation.
  */
-public class ResultStatusModalPage extends BaseModalPage {
+public class BulkActionResultModalPage<T, S> extends BaseModalPage {
 
     /**
      * Serial version id.
      */
-    private static final long serialVersionUID = 2646115294319713723L;
+    private static final long serialVersionUID = 2646115294319713724L;
 
-    @SpringBean
-    private UserRestClient userRestClient;
-
-    private final AbstractAttributableTO attributable;
-
-    /**
-     * Status management utilities.
-     */
-    private final StatusUtils statusUtils;
-
-    public ResultStatusModalPage(final ModalWindow window, final AbstractAttributableTO attributable) {
-        this(window, UserModalPage.Mode.ADMIN, attributable);
-    }
-
-    /**
-     * @param window guest modal window.
-     * @param mode operation mode.
-     * @param attributable User TO.
-     */
-    public ResultStatusModalPage(final ModalWindow window, final UserModalPage.Mode mode,
-            final AbstractAttributableTO attributable) {
+    public BulkActionResultModalPage(
+            final PageReference pageRef,
+            final ModalWindow window,
+            final List<T> items,
+            final List<IColumn<T, S>> columns,
+            final BulkActionRes results,
+            final String idFieldName) {
 
         super();
-        this.attributable = attributable;
-        statusUtils = new StatusUtils(this.userRestClient);
 
-        final BaseModalPage page = this;
+        final List<IColumn<T, S>> newColumnList = new ArrayList<IColumn<T, S>>(columns.subList(1, columns.size() - 1));
+        newColumnList.add(newColumnList.size(), new ActionResultColumn<T, S>(results, idFieldName));
 
-        final WebMarkupContainer container = new WebMarkupContainer("container");
-        container.setOutputMarkupId(true);
-        add(container);
-
-        final Fragment fragment = new Fragment("resultFrag", mode == UserModalPage.Mode.SELF
-                ? "userRequestResultFrag"
-                : "propagationResultFrag", this);
-        fragment.setOutputMarkupId(true);
-        container.add(fragment);
-
-        if (mode == UserModalPage.Mode.ADMIN) {
-            // add Syncope propagation status
-            PropagationStatusTO syncope = new PropagationStatusTO();
-            syncope.setResource("Syncope");
-            syncope.setStatus(PropagationTaskExecStatus.SUCCESS);
-
-            List<PropagationStatusTO> propagations = new ArrayList<PropagationStatusTO>();
-            propagations.add(syncope);
-            propagations.addAll(attributable.getPropagationStatusTOs());
-
-            fragment.add(new Label("info",
-                    ((attributable instanceof UserTO) && ((UserTO) attributable).getUsername() != null)
-                    ? ((UserTO) attributable).getUsername()
-                    : ((attributable instanceof RoleTO) && ((RoleTO) attributable).getName() != null)
-                    ? ((RoleTO) attributable).getName()
-                    : String.valueOf(attributable.getId())));
-
-            final ListView<PropagationStatusTO> propRes = new ListView<PropagationStatusTO>("resources", propagations) {
-
-                private static final long serialVersionUID = -1020475259727720708L;
-
-                @Override
-                protected void populateItem(final ListItem<PropagationStatusTO> item) {
-                    final PropagationStatusTO propTO = (PropagationStatusTO) item.getDefaultModelObject();
-
-                    final ListView attributes = getConnObjectView(propTO);
-
-                    final Fragment attrhead;
-                    if (attributes.getModelObject() == null || attributes.getModelObject().isEmpty()) {
-                        attrhead = new Fragment("attrhead", "emptyAttrHeadFrag", page);
-                    } else {
-                        attrhead = new Fragment("attrhead", "attrHeadFrag", page);
-                    }
-
-                    item.add(attrhead);
-                    item.add(attributes);
-
-                    attrhead.add(new Label("resource", propTO.getResource()));
-
-                    attrhead.add(new Label("propagation", propTO.getStatus() == null
-                            ? "UNDEFINED" : propTO.getStatus().toString()));
-
-                    final Image image;
-                    final String alt, title;
-                    switch (propTO.getStatus()) {
-
-                        case SUCCESS:
-                        case SUBMITTED:
-                        case CREATED:
-                            image = new Image("icon", "statuses/active.png");
-                            alt = "success icon";
-                            title = "success";
-                            break;
-
-                        default:
-                            image = new Image("icon", "statuses/inactive.png");
-                            alt = "failure icon";
-                            title = "failure";
-                    }
-
-                    image.add(new Behavior() {
-
-                        private static final long serialVersionUID = 1469628524240283489L;
-
-                        @Override
-                        public void onComponentTag(final Component component, final ComponentTag tag) {
-                            tag.put("alt", alt);
-                            tag.put("title", title);
-                        }
-                    });
-
-                    attrhead.add(image);
-                }
-            };
-            fragment.add(propRes);
-        }
-
-        final AjaxLink close = new IndicatingAjaxLink("close") {
-
-            private static final long serialVersionUID = -7978723352517770644L;
+        final SortableDataProvider<T, S> dataProvider = new SortableDataProvider<T, S>() {
 
             @Override
-            public void onClick(final AjaxRequestTarget target) {
-                window.close(target);
+            public Iterator<? extends T> iterator(long first, long count) {
+                return items.iterator();
             }
-        };
-        container.add(close);
 
-        setOutputMarkupId(true);
-    }
-
-    /**
-     * Get remote attributes list view.
-     *
-     * @param propTO propagation TO.
-     * @return list view.
-     */
-    private ListView getConnObjectView(final PropagationStatusTO propTO) {
-        final ConnObjectTO before = propTO.getBeforeObj();
-        final ConnObjectTO after = propTO.getAfterObj();
-
-        // sorted in reversed presentation order
-        final List<String> head = new ArrayList<String>();
-        if (attributable instanceof UserTO) {
-            head.add("__PASSWORD__");
-            head.add("__ENABLE__");
-        }
-        head.add("__UID__");
-        head.add("__NAME__");
-
-        final Map<String, AttributeTO> beforeAttrMap;
-        if (before == null) {
-            beforeAttrMap = Collections.<String, AttributeTO>emptyMap();
-        } else {
-            beforeAttrMap = before.getAttributeMap();
-        }
-
-        final Map<String, AttributeTO> afterAttrMap;
-        if (after == null) {
-            afterAttrMap = Collections.<String, AttributeTO>emptyMap();
-        } else {
-            afterAttrMap = after.getAttributeMap();
-        }
-
-        final Set<String> attributes = new HashSet<String>();
-        attributes.addAll(beforeAttrMap.keySet());
-        attributes.addAll(afterAttrMap.keySet());
-
-        if (!(attributable instanceof UserTO)) {
-            attributes.remove("__PASSWORD__");
-            attributes.remove("__ENABLE__");
-        }
-
-        final List<String> profile = new ArrayList<String>();
-        profile.addAll(attributes);
-        profile.removeAll(head);
-        Collections.sort(profile);
-
-        for (String attr : head) {
-            if (attributes.contains(attr)) {
-                profile.add(0, attr);
+            @Override
+            public long size() {
+                return items.size();
             }
-        }
-
-        return new ListView("attributes", profile) {
-
-            private static final long serialVersionUID = 4949588177564901031L;
 
             @Override
-            protected void populateItem(final ListItem item) {
-                String name = item.getModelObject().toString();
-
-                final Fragment beforeValue;
-                final Fragment afterValue;
-                if ("__ENABLE__".equals(name)) {
-                    beforeValue = getStatusIcon("beforeValue", propTO.getResource(), before);
-                    afterValue = getStatusIcon("afterValue", propTO.getResource(), after);
-                } else {
-                    beforeValue = getLabelValue("beforeValue", name, beforeAttrMap);
-                    afterValue = getLabelValue("afterValue", name, afterAttrMap);
-                }
-
-                item.add(new Label("attrName", new ResourceModel(name, name)));
-
-                item.add(beforeValue);
-                item.add(afterValue);
+            public IModel<T> model(T object) {
+                return new CompoundPropertyModel<T>(object);
             }
         };
-    }
 
-    /**
-     * Get fragment for attribute value (not remote status).
-     *
-     * @param id component id to be replaced with the fragment content.
-     * @param attrName remote attribute name
-     * @param attrMap remote attributes map.
-     * @return fragment.
-     */
-    private Fragment getLabelValue(final String id, final String attrName, final Map<String, AttributeTO> attrMap) {
-        final String value;
-
-        final AttributeTO attr = attrMap.get(attrName);
-
-        if (attr == null || attr.getValues() == null || attr.getValues().isEmpty()) {
-            value = "";
-        } else {
-            if ("__PASSWORD__".equals(attrName)) {
-                value = "********";
-            } else {
-                value = attr.getValues().size() > 1
-                        ? attr.getValues().toString()
-                        : attr.getValues().get(0);
-            }
-        }
+        add(new AjaxFallbackDefaultDataTable<T, S>(
+                "selectedObjects",
+                newColumnList,
+                dataProvider,
+                Integer.MAX_VALUE).setVisible(items != null && !items.isEmpty()));
 
-        Component label = new Label("value", value).add(new Behavior() {
+        final AjaxLink close = new IndicatingAjaxLink("close") {
 
-            private static final long serialVersionUID = 1469628524240283489L;
+            private static final long serialVersionUID = -7978723352517770644L;
 
             @Override
-            public void onComponentTag(final Component component, final ComponentTag tag) {
-                tag.put("title", value);
+            public void onClick(final AjaxRequestTarget target) {
+                window.close(target);
             }
-        });
-
-        final Fragment frag = new Fragment(id, "attrValueFrag", this);
-        frag.add(label);
-
-        return frag;
-    }
+        };
 
-    /**
-     * Get fragment for user status icon.
-     *
-     * @param id component id to be replaced with the fragment content
-     * @param resourceName resource name
-     * @param objectTO connector object TO
-     * @return fragment.
-     */
-    private Fragment getStatusIcon(final String id, final String resourceName, final ConnObjectTO objectTO) {
-        final Image image;
-        final String alt, title;
-        switch (statusUtils.getStatusBean(resourceName, objectTO).getStatus()) {
-
-            case ACTIVE:
-                image = new Image("status", "statuses/active.png");
-                alt = "active icon";
-                title = "Enabled";
-                break;
-
-            case SUSPENDED:
-                image = new Image("status", "statuses/inactive.png");
-                alt = "inactive icon";
-                title = "Disabled";
-                break;
-
-            default:
-                image = null;
-                alt = null;
-                title = null;
-        }
-
-        final Fragment frag;
-        if (image == null) {
-            frag = new Fragment(id, "emptyFrag", this);
-        } else {
-            image.add(new Behavior() {
-
-                private static final long serialVersionUID = 1469628524240283489L;
-
-                @Override
-                public void onComponentTag(final Component component, final ComponentTag tag) {
-                    tag.put("alt", alt);
-                    tag.put("title", title);
-                    tag.put("width", "12px");
-                    tag.put("height", "12px");
-                }
-            });
-
-            frag = new Fragment(id, "remoteStatusFrag", this);
-            frag.add(image);
-        }
+        add(close);
 
-        return frag;
     }
 }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Configuration.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Configuration.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Configuration.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Configuration.java Tue Mar 12 11:50:48 2013
@@ -255,7 +255,7 @@ public class Configuration extends BaseP
 
                         editConfigWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Configuration", "read");
+                }, ActionLink.ActionType.EDIT, "Configuration");
 
                 panel.add(new ActionLink() {
 
@@ -276,7 +276,7 @@ public class Configuration extends BaseP
 
                         target.add(confContainer);
                     }
-                }, ActionLink.ActionType.DELETE, "Configuration", "delete");
+                }, ActionLink.ActionType.DELETE, "Configuration");
 
                 cellItem.add(panel);
             }
@@ -424,7 +424,7 @@ public class Configuration extends BaseP
 
                         editNotificationWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Notification", "read");
+                }, ActionLink.ActionType.EDIT, "Notification");
 
                 panel.add(new ActionLink() {
 
@@ -445,7 +445,7 @@ public class Configuration extends BaseP
 
                         target.add(notificationContainer);
                     }
-                }, ActionLink.ActionType.DELETE, "Notification", "delete");
+                }, ActionLink.ActionType.DELETE, "Notification");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ReportModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ReportModalPage.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ReportModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/ReportModalPage.java Tue Mar 12 11:50:48 2013
@@ -483,7 +483,7 @@ public class ReportModalPage extends Bas
                         });
                         reportExecMessageWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Reports", "read", StringUtils.hasText(model.getObject().getMessage()));
+                }, ActionLink.ActionType.EDIT, "Reports", StringUtils.hasText(model.getObject().getMessage()));
 
                 panel.add(new ActionLink() {
 
@@ -504,7 +504,7 @@ public class ReportModalPage extends Bas
                         });
                         reportExecExportWin.show(target);
                     }
-                }, ActionLink.ActionType.EXPORT, "Reports", "read", ReportExecStatus.SUCCESS.name().equals(
+                }, ActionLink.ActionType.EXPORT, "Reports", ReportExecStatus.SUCCESS.name().equals(
                         model.getObject().getStatus()));
 
                 panel.add(new ActionLink() {
@@ -526,7 +526,7 @@ public class ReportModalPage extends Bas
                         target.add(feedbackPanel);
                         target.add(executions);
                     }
-                }, ActionLink.ActionType.DELETE, "Reports", "delete");
+                }, ActionLink.ActionType.DELETE, "Reports");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Reports.java Tue Mar 12 11:50:48 2013
@@ -174,7 +174,7 @@ public class Reports extends BasePage {
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Reports", "read");
+                }, ActionLink.ActionType.EDIT, "Reports");
 
                 panel.add(new ActionLink() {
 
@@ -192,7 +192,7 @@ public class Reports extends BasePage {
                         target.add(feedbackPanel);
                         target.add(reportContainer);
                     }
-                }, ActionLink.ActionType.EXECUTE, "Reports", "execute");
+                }, ActionLink.ActionType.EXECUTE, "Reports");
 
                 panel.add(new ActionLink() {
 
@@ -209,7 +209,7 @@ public class Reports extends BasePage {
                         target.add(reportContainer);
                         target.add(feedbackPanel);
                     }
-                }, ActionLink.ActionType.DELETE, "Reports", "delete");
+                }, ActionLink.ActionType.DELETE, "Reports");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Resources.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Resources.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Resources.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Resources.java Tue Mar 12 11:50:48 2013
@@ -238,7 +238,7 @@ public class Resources extends BasePage 
 
                         editResourceWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Resources", "read");
+                }, ActionLink.ActionType.EDIT, "Resources");
 
                 panel.add(new ActionLink() {
 
@@ -260,7 +260,7 @@ public class Resources extends BasePage 
                         target.add(feedbackPanel);
                         target.add(resourceContainer);
                     }
-                }, ActionLink.ActionType.DELETE, "Resources", "delete");
+                }, ActionLink.ActionType.DELETE, "Resources");
 
                 cellItem.add(panel);
             }
@@ -387,7 +387,7 @@ public class Resources extends BasePage 
 
                         editConnectorWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Connectors", "read");
+                }, ActionLink.ActionType.EDIT, "Connectors");
 
                 panel.add(new ActionLink() {
 
@@ -407,7 +407,7 @@ public class Resources extends BasePage 
                         target.add(connectorContainer);
                         target.add(feedbackPanel);
                     }
-                }, ActionLink.ActionType.DELETE, "Connectors", "delete");
+                }, ActionLink.ActionType.DELETE, "Connectors");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Schema.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Schema.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Schema.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Schema.java Tue Mar 12 11:50:48 2013
@@ -734,7 +734,7 @@ public class Schema extends BasePage {
 
                 final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
 
-                panel.add(new ActionLink() {
+                panel.addWithRoles(new ActionLink() {
 
                     private static final long serialVersionUID = -3722207913631435501L;
 
@@ -759,7 +759,7 @@ public class Schema extends BasePage {
                     }
                 }, ActionType.EDIT, readPermissions);
 
-                panel.add(new ActionLink() {
+                panel.addWithRoles(new ActionLink() {
 
                     private static final long serialVersionUID = -3722207913631435501L;
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/TaskModalPage.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/TaskModalPage.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/TaskModalPage.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/TaskModalPage.java Tue Mar 12 11:50:48 2013
@@ -148,7 +148,7 @@ public abstract class TaskModalPage exte
                         });
                         taskExecMessageWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Tasks", "read", StringUtils.hasText(model.getObject().getMessage()));
+                }, ActionLink.ActionType.EDIT, "Tasks", StringUtils.hasText(model.getObject().getMessage()));
 
                 panel.add(new ActionLink() {
 
@@ -169,7 +169,7 @@ public abstract class TaskModalPage exte
                         target.add(feedbackPanel);
                         target.add(executions);
                     }
-                }, ActionLink.ActionType.DELETE, "Tasks", "delete");
+                }, ActionLink.ActionType.DELETE, "Tasks");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Todo.java Tue Mar 12 11:50:48 2013
@@ -153,7 +153,7 @@ public class Todo extends BasePage {
                         target.add(feedbackPanel);
                         target.add(approvalContainer);
                     }
-                }, ActionLink.ActionType.CLAIM, "Approval", "claim");
+                }, ActionLink.ActionType.CLAIM, "Approval");
 
                 panel.add(new ActionLink() {
 
@@ -173,7 +173,7 @@ public class Todo extends BasePage {
 
                         editApprovalWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Approval", "read",
+                }, ActionLink.ActionType.EDIT, "Approval",
                         SyncopeSession.get().getUserId().equals(formTO.getOwner()));
 
                 cellItem.add(panel);
@@ -269,7 +269,7 @@ public class Todo extends BasePage {
 
                         editUserRequestWin.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "UserRequest", "read",
+                }, ActionLink.ActionType.EDIT, "UserRequest",
                         model.getObject().getType() != UserRequestType.DELETE);
 
                 panel.add(new ActionLink() {
@@ -292,7 +292,7 @@ public class Todo extends BasePage {
 
                         target.add(userRequestContainer);
                     }
-                }, ActionLink.ActionType.DELETE, "Users", "delete",
+                }, ActionLink.ActionType.DELETE, "Users",
                         model.getObject().getType() == UserRequestType.DELETE);
 
                 panel.add(new ActionLink() {
@@ -314,7 +314,7 @@ public class Todo extends BasePage {
 
                         target.add(userRequestContainer);
                     }
-                }, ActionLink.ActionType.DELETE, "UserRequest", "delete");
+                }, ActionLink.ActionType.DELETE, "UserRequest");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Users.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Users.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Users.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/Users.java Tue Mar 12 11:50:48 2013
@@ -31,6 +31,7 @@ import org.apache.wicket.Page;
 import org.apache.wicket.Session;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
@@ -69,6 +70,7 @@ public class Users extends BasePage {
                 new UserSearchResultPanel("listResult", false, null, getPageReference(), restClient);
         add(listResult);
 
+
         // create new user
         final AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", getPageReference()) {
 

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AbstractSearchResultPanel.java Tue Mar 12 11:50:48 2013
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.console.pages.panels;
 
+import java.util.Collection;
 import java.util.List;
 import org.apache.syncope.common.search.NodeCond;
 import org.apache.syncope.common.to.AbstractAttributableTO;
@@ -30,6 +31,7 @@ import org.apache.syncope.console.pages.
 import org.apache.syncope.console.rest.AbstractAttributableRestClient;
 import org.apache.syncope.console.rest.UserRestClient;
 import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
@@ -42,7 +44,6 @@ import org.apache.wicket.event.Broadcast
 import org.apache.wicket.event.IEvent;
 import org.apache.wicket.event.IEventSource;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
-import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -137,7 +138,7 @@ public abstract class AbstractSearchResu
     /**
      * Result table.
      */
-    private AjaxFallbackDefaultDataTable<AbstractAttributableTO, String> resultTable;
+    private AjaxDataTablePanel<AbstractAttributableTO, String> resultTable;
 
     /**
      * Data provider used to search for users.
@@ -353,8 +354,16 @@ public abstract class AbstractSearchResu
                 : (int) resultTable.getCurrentPage())
                 : 0;
 
-        resultTable = new AjaxFallbackDefaultDataTable<AbstractAttributableTO, String>(
-                "resultTable", getColumns(), dataProvider, rows);
+        resultTable = new AjaxDataTablePanel<AbstractAttributableTO, String>(
+                "resultTable",
+                getColumns(),
+                dataProvider,
+                rows,
+                getBulkActions(),
+                restClient,
+                "id",
+                getPageId(),
+                page.getPageReference());
 
         resultTable.setCurrentPage(currentPage);
 
@@ -437,4 +446,8 @@ public abstract class AbstractSearchResu
             this.rows = rows;
         }
     }
+
+    protected abstract <T extends AbstractAttributableTO> Collection<ActionLink.ActionType> getBulkActions();
+
+    protected abstract String getPageId();
 }

Added: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java?rev=1455500&view=auto
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java (added)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java Tue Mar 12 11:50:48 2013
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2013 The Apache Software Foundation.
+ *
+ * Licensed 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.syncope.console.pages.panels;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.syncope.console.pages.AbstractBasePage;
+import org.apache.syncope.console.pages.BulkActionModalPage;
+import org.apache.syncope.console.pages.panels.AbstractSearchResultPanel.EventDataWrapper;
+import org.apache.syncope.console.rest.BaseRestClient;
+import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.CheckGroupColumn;
+import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
+import org.apache.wicket.markup.html.form.CheckGroup;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AjaxDataTablePanel<T, S> extends Panel {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AjaxDataTablePanel.class);
+
+    private final CheckGroup<T> group;
+
+    private final Form bulkActionForm;
+
+    private final AjaxFallbackDefaultDataTable dataTable;
+
+    public AjaxDataTablePanel(
+            final String id,
+            final List<IColumn<T, S>> columns,
+            final ISortableDataProvider<T, S> dataProvider,
+            final int rowsPerPage) {
+        super(id);
+
+        this.bulkActionForm = null;
+        this.group = null;
+        dataTable = new AjaxFallbackDefaultDataTable("dataTable", columns, dataProvider, rowsPerPage);
+
+        Fragment fragment = new Fragment("tablePanel", "bulkNotAvailable", this);
+        fragment.add(dataTable);
+
+        add(fragment);
+    }
+
+    public AjaxDataTablePanel(
+            final String id,
+            final List<IColumn<T, S>> columns,
+            final ISortableDataProvider<T, S> dataProvider,
+            final int rowsPerPage,
+            final Collection<ActionLink.ActionType> actions,
+            final BaseRestClient bulkActionExecutor,
+            final String itemIdFiled,
+            final String pageId,
+            final PageReference pageRef) {
+
+        super(id);
+
+        final ModalWindow bulkModalWin = new ModalWindow("bulkModal");
+        bulkModalWin.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        bulkModalWin.setInitialHeight(600);
+        bulkModalWin.setInitialWidth(900);
+        bulkModalWin.setCookieName("bulk-modal");
+        add(bulkModalWin);
+
+        bulkModalWin.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
+
+            private static final long serialVersionUID = 8804221891699487149L;
+
+            @Override
+            public void onClose(final AjaxRequestTarget target) {
+                final EventDataWrapper data = new EventDataWrapper();
+                data.setTarget(target);
+                data.setRows(rowsPerPage);
+
+                send(pageRef.getPage(), Broadcast.BREADTH, data);
+
+                final AbstractBasePage page = (AbstractBasePage) pageRef.getPage();
+
+                if (page.isModalResult()) {
+                    // reset modal result
+                    page.setModalResult(false);
+                    // set operation succeeded
+                    getSession().info(getString("operation_succeeded"));
+                    // refresh feedback panel
+                    target.add(page.getFeedbackPanel());
+                }
+            }
+        });
+
+        Fragment fragment = new Fragment("tablePanel", "bulkAvailable", this);
+        add(fragment);
+
+        bulkActionForm = new Form("groupForm");
+        fragment.add(bulkActionForm);
+
+        group = new CheckGroup<T>("checkgroup", new ArrayList<T>());
+        bulkActionForm.add(group);
+
+        columns.add(0, new CheckGroupColumn<T, S>(group));
+        dataTable = new AjaxFallbackDefaultDataTable("dataTable", columns, dataProvider, rowsPerPage);
+        group.add(dataTable);
+
+        fragment.add(new ClearIndicatingAjaxButton("bulkActionLink", bulkActionForm, pageRef) {
+
+            @Override
+            protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                bulkModalWin.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690941L;
+
+                    @Override
+                    public Page createPage() {
+                        return new BulkActionModalPage(
+                                getPage().getPageReference(),
+                                bulkModalWin,
+                                new ArrayList<T>(group.getModelObject()),
+                                columns,
+                                actions,
+                                bulkActionExecutor,
+                                itemIdFiled,
+                                pageId);
+                    }
+                });
+
+                bulkModalWin.show(target);
+            }
+        });
+    }
+
+    public final void setCurrentPage(final long page) {
+        dataTable.setCurrentPage(page);
+    }
+
+    public final long getRowCount() {
+        return dataTable.getRowCount();
+    }
+
+    public final long getCurrentPage() {
+        return dataTable.getCurrentPage();
+    }
+
+    public final long getPageCount() {
+        return dataTable.getPageCount();
+    }
+}

Propchange: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/AjaxDataTablePanel.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java Tue Mar 12 11:50:48 2013
@@ -144,7 +144,7 @@ public class NotificationTasks extends P
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Tasks", "read");
+                }, ActionLink.ActionType.EDIT, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -162,7 +162,7 @@ public class NotificationTasks extends P
                         target.add(getPage().get("feedback"));
                         target.add(container);
                     }
-                }, ActionLink.ActionType.EXECUTE, "Tasks", "execute");
+                }, ActionLink.ActionType.EXECUTE, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -179,7 +179,7 @@ public class NotificationTasks extends P
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.DELETE, "Tasks", "delete");
+                }, ActionLink.ActionType.DELETE, "Tasks");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PoliciesPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PoliciesPanel.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PoliciesPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PoliciesPanel.java Tue Mar 12 11:50:48 2013
@@ -169,7 +169,7 @@ public class PoliciesPanel extends Panel
 
                         mwindow.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Policies", "read");
+                }, ActionLink.ActionType.EDIT, "Policies");
 
                 panel.add(new ActionLink() {
 
@@ -192,7 +192,7 @@ public class PoliciesPanel extends Panel
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.DELETE, "Policies", "delete");
+                }, ActionLink.ActionType.DELETE, "Policies");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PropagationTasks.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PropagationTasks.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PropagationTasks.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/PropagationTasks.java Tue Mar 12 11:50:48 2013
@@ -159,7 +159,7 @@ public class PropagationTasks extends Pa
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Tasks", "read");
+                }, ActionLink.ActionType.EDIT, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -177,7 +177,7 @@ public class PropagationTasks extends Pa
                         target.add(getPage().get("feedback"));
                         target.add(container);
                     }
-                }, ActionLink.ActionType.EXECUTE, "Tasks", "execute");
+                }, ActionLink.ActionType.EXECUTE, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -194,7 +194,7 @@ public class PropagationTasks extends Pa
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.DELETE, "Tasks", "delete");
+                }, ActionLink.ActionType.DELETE, "Tasks");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/RoleSearchResultPanel.java Tue Mar 12 11:50:48 2013
@@ -19,6 +19,8 @@
 package org.apache.syncope.console.pages.panels;
 
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 import org.apache.syncope.common.search.NodeCond;
 import org.apache.syncope.common.to.AbstractAttributableTO;
@@ -29,6 +31,7 @@ import org.apache.syncope.console.pages.
 import org.apache.syncope.console.pages.StatusModalPage;
 import org.apache.syncope.console.rest.AbstractAttributableRestClient;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.console.wicket.markup.html.form.ActionLink.ActionType;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
@@ -43,116 +46,128 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
 
 public class RoleSearchResultPanel extends AbstractSearchResultPanel {
-    
+
     private static final long serialVersionUID = -1180593361914008764L;
-    
+
+    private final static String PAGEID = "Roles";
+
     public <T extends AbstractAttributableTO> RoleSearchResultPanel(final String id, final boolean filtered,
             final NodeCond searchCond, final PageReference callerRef,
             final AbstractAttributableRestClient restClient) {
-        
+
         super(id, filtered, searchCond, callerRef, restClient);
     }
-    
+
     @Override
     protected List<IColumn<AbstractAttributableTO, String>> getColumns() {
         final List<IColumn<AbstractAttributableTO, String>> columns =
                 new ArrayList<IColumn<AbstractAttributableTO, String>>();
-        
+
         final String[] colnames = {"id", "name", "entitlements"};
         for (String name : colnames) {
             columns.add(
                     new PropertyColumn<AbstractAttributableTO, String>(new ResourceModel(name, name), name, name));
         }
-        
+
         columns.add(new AbstractColumn<AbstractAttributableTO, String>(new ResourceModel("actions", "")) {
 
             private static final long serialVersionUID = -3503023501954863131L;
-            
+
             @Override
             public String getCssClass() {
                 return "action";
             }
-            
+
             @Override
             public void populateItem(final Item<ICellPopulator<AbstractAttributableTO>> cellItem,
                     final String componentId, final IModel<AbstractAttributableTO> model) {
-                
+
                 final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, page.getPageReference());
-                
+
                 panel.add(new ActionLink() {
-                    
+
                     private static final long serialVersionUID = -3722207913631435501L;
-                    
+
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         statusmodal.setPageCreator(new ModalWindow.PageCreator() {
-                            
+
                             private static final long serialVersionUID = -7834632442532690940L;
-                            
+
                             @Override
                             public Page createPage() {
                                 return new StatusModalPage(page.getPageReference(), statusmodal, model.getObject());
                             }
                         });
-                        
+
                         statusmodal.show(target);
                     }
-                }, ActionLink.ActionType.SEARCH, "Roles", "read");
-                
+                }, ActionLink.ActionType.SEARCH, PAGEID);
+
                 panel.add(new ActionLink() {
-                    
+
                     private static final long serialVersionUID = -3722207913631435501L;
-                    
+
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         editmodal.setPageCreator(new ModalWindow.PageCreator() {
-                            
+
                             private static final long serialVersionUID = -7834632442532690940L;
-                            
+
                             @Override
                             public Page createPage() {
                                 return new RoleModalPage(
                                         page.getPageReference(), editmodal, (RoleTO) model.getObject());
                             }
                         });
-                        
+
                         editmodal.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Roles", "update");
-                
+                }, ActionLink.ActionType.EDIT, PAGEID);
+
                 panel.add(new ActionLink() {
-                    
+
                     private static final long serialVersionUID = -3722207913631435501L;
-                    
+
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
                             final RoleTO roleTO = (RoleTO) restClient.delete(model.getObject().getId());
-                            
+
                             page.setModalResult(true);
-                            
+
                             editmodal.setPageCreator(new ModalWindow.PageCreator() {
-                                
+
                                 private static final long serialVersionUID = -7834632442532690940L;
-                                
+
                                 @Override
                                 public Page createPage() {
                                     return new ResultStatusModalPage(editmodal, roleTO);
                                 }
                             });
-                            
+
                             editmodal.show(target);
                         } catch (SyncopeClientCompositeErrorException scce) {
                             error(getString("operation_error") + ": " + scce.getMessage());
                             target.add(feedbackPanel);
                         }
                     }
-                }, ActionLink.ActionType.DELETE, "Roles", "delete");
-                
+                }, ActionLink.ActionType.DELETE, PAGEID);
+
                 cellItem.add(panel);
             }
         });
-        
+
         return columns;
     }
+
+    @Override
+    protected Collection<ActionType> getBulkActions() {
+        return Collections.<ActionLink.ActionType>singletonList(ActionLink.ActionType.DELETE);
+    }
+
+    @Override
+    protected String getPageId() {
+        return PAGEID;
+    }
 }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java Tue Mar 12 11:50:48 2013
@@ -158,7 +158,7 @@ public class SchedTasks extends Panel {
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Tasks", "read");
+                }, ActionLink.ActionType.EDIT, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -176,7 +176,7 @@ public class SchedTasks extends Panel {
                         target.add(getPage().get("feedback"));
                         target.add(container);
                     }
-                }, ActionLink.ActionType.EXECUTE, "Tasks", "execute");
+                }, ActionLink.ActionType.EXECUTE, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -194,7 +194,7 @@ public class SchedTasks extends Panel {
                         target.add(getPage().get("feedback"));
                         target.add(container);
                     }
-                }, ActionLink.ActionType.DRYRUN, "Tasks", "execute");
+                }, ActionLink.ActionType.DRYRUN, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -211,7 +211,7 @@ public class SchedTasks extends Panel {
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.DELETE, "Tasks", "delete");
+                }, ActionLink.ActionType.DELETE, "Tasks");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SelectOnlyUserSearchResultPanel.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SelectOnlyUserSearchResultPanel.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SelectOnlyUserSearchResultPanel.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SelectOnlyUserSearchResultPanel.java Tue Mar 12 11:50:48 2013
@@ -90,7 +90,7 @@ public class SelectOnlyUserSearchResultP
                                 rowModel.getObject().getId()));
                         window.close(target);
                     }
-                }, ActionLink.ActionType.SELECT, "Users", "read");
+                }, ActionLink.ActionType.SELECT, "Users");
 
                 cellItem.add(panel);
             }

Modified: syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasks.java
URL: http://svn.apache.org/viewvc/syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasks.java?rev=1455500&r1=1455499&r2=1455500&view=diff
==============================================================================
--- syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasks.java (original)
+++ syncope/trunk/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasks.java Tue Mar 12 11:50:48 2013
@@ -160,7 +160,7 @@ public class SyncTasks extends Panel {
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.EDIT, "Tasks", "read");
+                }, ActionLink.ActionType.EDIT, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -181,7 +181,7 @@ public class SyncTasks extends Panel {
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.USER_TEMPLATE, "Tasks", "read");
+                }, ActionLink.ActionType.USER_TEMPLATE, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -202,7 +202,7 @@ public class SyncTasks extends Panel {
 
                         window.show(target);
                     }
-                }, ActionLink.ActionType.ROLE_TEMPLATE, "Tasks", "read");
+                }, ActionLink.ActionType.ROLE_TEMPLATE, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -220,7 +220,7 @@ public class SyncTasks extends Panel {
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.EXECUTE, "Tasks", "execute");
+                }, ActionLink.ActionType.EXECUTE, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -238,7 +238,7 @@ public class SyncTasks extends Panel {
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.DRYRUN, "Tasks", "execute");
+                }, ActionLink.ActionType.DRYRUN, "Tasks");
 
                 panel.add(new ActionLink() {
 
@@ -255,7 +255,7 @@ public class SyncTasks extends Panel {
                         target.add(container);
                         target.add(getPage().get("feedback"));
                     }
-                }, ActionLink.ActionType.DELETE, "Tasks", "delete");
+                }, ActionLink.ActionType.DELETE, "Tasks");
 
                 cellItem.add(panel);
             }