You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2016/03/31 17:29:01 UTC

[07/10] syncope git commit: [SYNCOPE-156] Internal refactoring

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
new file mode 100644
index 0000000..ec404dc
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusDirectoryPanel.java
@@ -0,0 +1,277 @@
+/*
+ * 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.syncope.client.console.status;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
+import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
+import org.apache.syncope.client.console.commons.status.Status;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.console.panels.DirectoryPanel;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
+import org.apache.syncope.client.console.rest.AnyObjectRestClient;
+import org.apache.syncope.client.console.rest.GroupRestClient;
+import org.apache.syncope.client.console.rest.ResourceRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.status.StatusDirectoryPanel.AttributableStatusProvider;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.StringResourceModel;
+
+public class StatusDirectoryPanel
+        extends DirectoryPanel<StatusBean, StatusBean, AttributableStatusProvider, AbstractAnyRestClient<?>>
+        implements ModalPanel<StatusBean> {
+
+    private static final long serialVersionUID = -9148734710505211261L;
+
+    private final BaseModal<?> baseModal;
+
+    private final MultilevelPanel multiLevelPanelRef;
+
+    private final AnyTO anyTO;
+
+    private final boolean statusOnly;
+
+    public StatusDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final PageReference pageRef,
+            final AnyTO anyTO) {
+
+        this(baseModal, multiLevelPanelRef, pageRef, anyTO, false);
+    }
+
+    public StatusDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final PageReference pageRef,
+            final AnyTO anyTO,
+            final boolean statusOnly) {
+
+        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef);
+        this.baseModal = baseModal;
+        this.multiLevelPanelRef = multiLevelPanelRef;
+        this.statusOnly = statusOnly;
+        this.anyTO = anyTO;
+        this.itemKeyFieldName = statusOnly ? "anyKey" : "resourceName";
+
+        if (anyTO instanceof UserTO) {
+            this.restClient = new UserRestClient();
+        } else if (anyTO instanceof GroupTO) {
+            this.restClient = new GroupRestClient();
+        } else {
+            this.restClient = new AnyObjectRestClient();
+        }
+
+        initResultTable();
+    }
+
+    @Override
+    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<StatusBean, String> resultTableBuilder) {
+        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
+    }
+
+    @Override
+    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public void onError(final AjaxRequestTarget target, final Form<?> form) {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    public StatusBean getItem() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    protected List<IColumn<StatusBean, String>> getColumns() {
+        final List<IColumn<StatusBean, String>> columns = new ArrayList<>();
+
+        columns.add(new AbstractColumn<StatusBean, String>(
+                new StringResourceModel("resourceName", this, null), "resourceName") {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<StatusBean>> cellItem,
+                    final String componentId,
+                    final IModel<StatusBean> model) {
+
+                cellItem.add(new Label(componentId, model.getObject().getResourceName()) {
+
+                    private static final long serialVersionUID = 8432079838783825801L;
+
+                    @Override
+                    protected void onComponentTag(final ComponentTag tag) {
+                        if (model.getObject().isLinked()) {
+                            super.onComponentTag(tag);
+                        } else {
+                            tag.put("style", "color: #DDDDDD");
+                        }
+                    }
+                });
+            }
+        });
+
+        columns.add(new PropertyColumn<StatusBean, String>(
+                new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink"));
+
+        columns.add(new AbstractColumn<StatusBean, String>(new StringResourceModel("status", this, null)) {
+
+            private static final long serialVersionUID = -3503023501954863131L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<StatusBean>> cellItem,
+                    final String componentId,
+                    final IModel<StatusBean> model) {
+
+                if (model.getObject().isLinked()) {
+                    cellItem.add(StatusUtils.getStatusImage(componentId, model.getObject().getStatus()));
+                } else {
+                    cellItem.add(new Label(componentId, ""));
+                }
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected Collection<ActionLink.ActionType> getBulkActions() {
+        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
+        if (statusOnly) {
+            bulkActions.add(ActionLink.ActionType.SUSPEND);
+            bulkActions.add(ActionLink.ActionType.REACTIVATE);
+        } else {
+            bulkActions.add(ActionLink.ActionType.UNLINK);
+            bulkActions.add(ActionLink.ActionType.LINK);
+            bulkActions.add(ActionLink.ActionType.DEPROVISION);
+            bulkActions.add(ActionLink.ActionType.PROVISION);
+            bulkActions.add(ActionLink.ActionType.ASSIGN);
+            bulkActions.add(ActionLink.ActionType.UNASSIGN);
+
+        }
+        return bulkActions;
+    }
+
+    @Override
+    protected AttributableStatusProvider dataProvider() {
+        return new AttributableStatusProvider();
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return StringUtils.EMPTY;
+    }
+
+    public class AttributableStatusProvider extends AbstractStatusBeanProvider {
+
+        private static final long serialVersionUID = 4586969457669796621L;
+
+        private final StatusUtils statusUtils;
+
+        AttributableStatusProvider() {
+            super(statusOnly ? "resourceName" : "connObjectLink");
+            statusUtils = new StatusUtils(restClient);
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public List<StatusBean> getStatusBeans() {
+            // this is required to retrieve updated data by reloading table
+            final AnyTO actual = restClient.read(anyTO.getKey());
+
+            final List<String> resources = new ArrayList<>();
+            for (ResourceTO resourceTO : new ResourceRestClient().getAll()) {
+                resources.add(resourceTO.getKey());
+            }
+
+            final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(actual);
+
+            final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1);
+
+            for (ConnObjectWrapper entry : connObjects) {
+                final StatusBean statusBean = statusUtils.getStatusBean(actual,
+                        entry.getResourceName(),
+                        entry.getConnObjectTO(),
+                        actual instanceof GroupTO);
+
+                statusBeans.add(statusBean);
+                resources.remove(entry.getResourceName());
+            }
+
+            if (statusOnly) {
+                final StatusBean syncope = new StatusBean(actual, "Syncope");
+
+                syncope.setConnObjectLink(((UserTO) actual).getUsername());
+
+                Status syncopeStatus = Status.UNDEFINED;
+                if (((UserTO) actual).getStatus() != null) {
+                    try {
+                        syncopeStatus = Status.valueOf(((UserTO) actual).getStatus().toUpperCase());
+                    } catch (IllegalArgumentException e) {
+                        LOG.warn("Unexpected status found: {}", ((UserTO) actual).getStatus(), e);
+                    }
+                }
+                syncope.setStatus(syncopeStatus);
+
+                statusBeans.add(syncope);
+            } else {
+                for (String resource : resources) {
+                    final StatusBean statusBean = statusUtils.getStatusBean(actual,
+                            resource,
+                            null,
+                            actual instanceof GroupTO);
+
+                    statusBean.setLinked(false);
+                    statusBeans.add(statusBean);
+                }
+            }
+
+            return statusBeans;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
index 799c304..374454f 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusModal.java
@@ -37,7 +37,7 @@ public class StatusModal<T extends AnyTO> extends Panel implements ModalPanel<An
         super(BaseModal.CONTENT_ID);
 
         final MultilevelPanel mlp = new MultilevelPanel("status");
-        add(mlp.setFirstLevel(new StatusSearchResultPanel(baseModal, mlp, pageReference, anyTO, statusOnly)));
+        add(mlp.setFirstLevel(new StatusDirectoryPanel(baseModal, mlp, pageReference, anyTO, statusOnly)));
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/status/StatusSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/status/StatusSearchResultPanel.java
deleted file mode 100644
index 11adf29..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/status/StatusSearchResultPanel.java
+++ /dev/null
@@ -1,277 +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.syncope.client.console.status;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.status.AbstractStatusBeanProvider;
-import org.apache.syncope.client.console.commons.status.ConnObjectWrapper;
-import org.apache.syncope.client.console.commons.status.Status;
-import org.apache.syncope.client.console.commons.status.StatusBean;
-import org.apache.syncope.client.console.commons.status.StatusUtils;
-import org.apache.syncope.client.console.panels.AbstractSearchResultPanel;
-import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
-import org.apache.syncope.client.console.panels.ModalPanel;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.rest.AbstractAnyRestClient;
-import org.apache.syncope.client.console.rest.AnyObjectRestClient;
-import org.apache.syncope.client.console.rest.GroupRestClient;
-import org.apache.syncope.client.console.rest.ResourceRestClient;
-import org.apache.syncope.client.console.rest.UserRestClient;
-import org.apache.syncope.client.console.status.StatusSearchResultPanel.AttributableStatusProvider;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
-import org.apache.wicket.markup.ComponentTag;
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.form.Form;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.StringResourceModel;
-
-public class StatusSearchResultPanel
-        extends AbstractSearchResultPanel<StatusBean, StatusBean, AttributableStatusProvider, AbstractAnyRestClient<?>>
-        implements ModalPanel<StatusBean> {
-
-    private static final long serialVersionUID = -9148734710505211261L;
-
-    private final BaseModal<?> baseModal;
-
-    private final MultilevelPanel multiLevelPanelRef;
-
-    private final AnyTO anyTO;
-
-    private final boolean statusOnly;
-
-    public StatusSearchResultPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final PageReference pageRef,
-            final AnyTO anyTO) {
-
-        this(baseModal, multiLevelPanelRef, pageRef, anyTO, false);
-    }
-
-    public StatusSearchResultPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final PageReference pageRef,
-            final AnyTO anyTO,
-            final boolean statusOnly) {
-
-        super(MultilevelPanel.FIRST_LEVEL_ID, pageRef);
-        this.baseModal = baseModal;
-        this.multiLevelPanelRef = multiLevelPanelRef;
-        this.statusOnly = statusOnly;
-        this.anyTO = anyTO;
-        this.itemKeyFieldName = statusOnly ? "anyKey" : "resourceName";
-
-        if (anyTO instanceof UserTO) {
-            this.restClient = new UserRestClient();
-        } else if (anyTO instanceof GroupTO) {
-            this.restClient = new GroupRestClient();
-        } else {
-            this.restClient = new AnyObjectRestClient();
-        }
-
-        initResultTable();
-    }
-
-    @Override
-    protected void resultTableCustomChanges(final AjaxDataTablePanel.Builder<StatusBean, String> resultTableBuilder) {
-        resultTableBuilder.setMultiLevelPanel(baseModal, multiLevelPanelRef);
-    }
-
-    @Override
-    public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public void onError(final AjaxRequestTarget target, final Form<?> form) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    public StatusBean getItem() {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-
-    @Override
-    protected List<IColumn<StatusBean, String>> getColumns() {
-        final List<IColumn<StatusBean, String>> columns = new ArrayList<IColumn<StatusBean, String>>();
-
-        columns.add(new AbstractColumn<StatusBean, String>(
-                new StringResourceModel("resourceName", this, null), "resourceName") {
-
-            private static final long serialVersionUID = 2054811145491901166L;
-
-            @Override
-            public void populateItem(
-                    final Item<ICellPopulator<StatusBean>> cellItem,
-                    final String componentId,
-                    final IModel<StatusBean> model) {
-
-                cellItem.add(new Label(componentId, model.getObject().getResourceName()) {
-
-                    private static final long serialVersionUID = 8432079838783825801L;
-
-                    @Override
-                    protected void onComponentTag(final ComponentTag tag) {
-                        if (model.getObject().isLinked()) {
-                            super.onComponentTag(tag);
-                        } else {
-                            tag.put("style", "color: #DDDDDD");
-                        }
-                    }
-                });
-            }
-        });
-
-        columns.add(new PropertyColumn<StatusBean, String>(
-                new StringResourceModel("connObjectLink", this, null), "connObjectLink", "connObjectLink"));
-
-        columns.add(new AbstractColumn<StatusBean, String>(new StringResourceModel("status", this, null)) {
-
-            private static final long serialVersionUID = -3503023501954863131L;
-
-            @Override
-            public void populateItem(
-                    final Item<ICellPopulator<StatusBean>> cellItem,
-                    final String componentId,
-                    final IModel<StatusBean> model) {
-
-                if (model.getObject().isLinked()) {
-                    cellItem.add(StatusUtils.getStatusImage(componentId, model.getObject().getStatus()));
-                } else {
-                    cellItem.add(new Label(componentId, ""));
-                }
-            }
-        });
-
-        return columns;
-    }
-
-    @Override
-    protected Collection<ActionLink.ActionType> getBulkActions() {
-        final List<ActionLink.ActionType> bulkActions = new ArrayList<>();
-        if (statusOnly) {
-            bulkActions.add(ActionLink.ActionType.SUSPEND);
-            bulkActions.add(ActionLink.ActionType.REACTIVATE);
-        } else {
-            bulkActions.add(ActionLink.ActionType.UNLINK);
-            bulkActions.add(ActionLink.ActionType.LINK);
-            bulkActions.add(ActionLink.ActionType.DEPROVISION);
-            bulkActions.add(ActionLink.ActionType.PROVISION);
-            bulkActions.add(ActionLink.ActionType.ASSIGN);
-            bulkActions.add(ActionLink.ActionType.UNASSIGN);
-
-        }
-        return bulkActions;
-    }
-
-    @Override
-    protected AttributableStatusProvider dataProvider() {
-        return new AttributableStatusProvider();
-    }
-
-    @Override
-    protected String paginatorRowsKey() {
-        return StringUtils.EMPTY;
-    }
-
-    public class AttributableStatusProvider extends AbstractStatusBeanProvider {
-
-        private static final long serialVersionUID = 4586969457669796621L;
-
-        private final StatusUtils statusUtils;
-
-        AttributableStatusProvider() {
-            super(statusOnly ? "resourceName" : "connObjectLink");
-            statusUtils = new StatusUtils(restClient);
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public List<StatusBean> getStatusBeans() {
-            // this is required to retrieve updated data by reloading table
-            final AnyTO actual = restClient.read(anyTO.getKey());
-
-            final List<String> resources = new ArrayList<>();
-            for (ResourceTO resourceTO : new ResourceRestClient().getAll()) {
-                resources.add(resourceTO.getKey());
-            }
-
-            final List<ConnObjectWrapper> connObjects = statusUtils.getConnectorObjects(actual);
-
-            final List<StatusBean> statusBeans = new ArrayList<>(connObjects.size() + 1);
-
-            for (ConnObjectWrapper entry : connObjects) {
-                final StatusBean statusBean = statusUtils.getStatusBean(actual,
-                        entry.getResourceName(),
-                        entry.getConnObjectTO(),
-                        actual instanceof GroupTO);
-
-                statusBeans.add(statusBean);
-                resources.remove(entry.getResourceName());
-            }
-
-            if (statusOnly) {
-                final StatusBean syncope = new StatusBean(actual, "Syncope");
-
-                syncope.setConnObjectLink(((UserTO) actual).getUsername());
-
-                Status syncopeStatus = Status.UNDEFINED;
-                if (((UserTO) actual).getStatus() != null) {
-                    try {
-                        syncopeStatus = Status.valueOf(((UserTO) actual).getStatus().toUpperCase());
-                    } catch (IllegalArgumentException e) {
-                        LOG.warn("Unexpected status found: {}", ((UserTO) actual).getStatus(), e);
-                    }
-                }
-                syncope.setStatus(syncopeStatus);
-
-                statusBeans.add(syncope);
-            } else {
-                for (String resource : resources) {
-                    final StatusBean statusBean = statusUtils.getStatusBean(actual,
-                            resource,
-                            null,
-                            actual instanceof GroupTO);
-
-                    statusBean.setLinked(false);
-                    statusBeans.add(statusBean);
-                }
-            }
-
-            return statusBeans;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
new file mode 100644
index 0000000..12a2523
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskDirectoryPanel.java
@@ -0,0 +1,225 @@
+/*
+ * 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.syncope.client.console.tasks;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.TaskDataProvider;
+import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.to.PropagationTaskTO;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+
+/**
+ * Tasks page.
+ */
+public abstract class PropagationTaskDirectoryPanel
+        extends TaskDirectoryPanel<PropagationTaskTO> implements ModalPanel<PropagationTaskTO> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    private final String resource;
+
+    protected PropagationTaskDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final String resource,
+            final PageReference pageRef) {
+        super(baseModal, multiLevelPanelRef, pageRef);
+        this.resource = resource;
+        initResultTable();
+    }
+
+    @Override
+    protected List<IColumn<PropagationTaskTO, String>> getColumns() {
+        final List<IColumn<PropagationTaskTO, String>> columns = new ArrayList<>();
+
+        columns.add(new PropertyColumn<PropagationTaskTO, String>(
+                new StringResourceModel("key", this, null), "key", "key"));
+
+        columns.add(new PropertyColumn<PropagationTaskTO, String>(new StringResourceModel(
+                "operation", this, null), "operation", "operation"));
+
+        columns.add(new PropertyColumn<PropagationTaskTO, String>(
+                new StringResourceModel("anyTypeKind", this, null), "anyTypeKind", "anyTypeKind"));
+
+        columns.add(new PropertyColumn<PropagationTaskTO, String>(
+                new StringResourceModel("anyKey", this, null), "anyKey", "anyKey"));
+
+        columns.add(new PropertyColumn<PropagationTaskTO, String>(
+                new StringResourceModel("connObjectKey", this, null), "connObjectKey", "connObjectKey"));
+
+        columns.add(new DatePropertyColumn<PropagationTaskTO>(
+                new StringResourceModel("start", this, null), "start", "start"));
+
+        columns.add(new DatePropertyColumn<PropagationTaskTO>(
+                new StringResourceModel("end", this, null), "end", "end"));
+
+        columns.add(new PropertyColumn<PropagationTaskTO, String>(
+                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+
+        columns.add(new ActionColumn<PropagationTaskTO, String>(new ResourceModel("actions")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public ActionLinksPanel<PropagationTaskTO> getActions(
+                    final String componentId, final IModel<PropagationTaskTO> model) {
+
+                final PropagationTaskTO taskTO = model.getObject();
+
+                final ActionLinksPanel<PropagationTaskTO> panel = ActionLinksPanel.<PropagationTaskTO>builder().
+                        add(new ActionLink<PropagationTaskTO>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final PropagationTaskTO modelObject) {
+                                viewTask(taskTO, target);
+                            }
+                        }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ).
+                        add(new ActionLink<PropagationTaskTO>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final PropagationTaskTO modelObject) {
+                                try {
+                                    restClient.startExecution(taskTO.getKey(), new Date());
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                    target.add(container);
+                                } catch (SyncopeClientException e) {
+                                    error(StringUtils.isBlank(e.getMessage())
+                                            ? e.getClass().getName() : e.getMessage());
+                                    LOG.error("While running {}", taskTO.getKey(), e);
+                                }
+                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                            }
+                        }, ActionLink.ActionType.EXECUTE, StandardEntitlement.TASK_EXECUTE).
+                        add(new ActionLink<PropagationTaskTO>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final PropagationTaskTO modelObject) {
+                                try {
+                                    restClient.delete(taskTO.getKey(), PropagationTaskTO.class);
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                    target.add(container);
+                                } catch (SyncopeClientException e) {
+                                    LOG.error("While deleting {}", taskTO.getKey(), e);
+                                    error(StringUtils.isBlank(e.getMessage())
+                                            ? e.getClass().getName() : e.getMessage());
+                                }
+                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                            }
+                        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE).build(componentId);
+
+                return panel;
+            }
+
+            @Override
+            public ActionLinksPanel<PropagationTaskTO> getHeader(final String componentId) {
+                final ActionLinksPanel.Builder<PropagationTaskTO> panel = ActionLinksPanel.builder();
+
+                return panel.add(new ActionLink<PropagationTaskTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final PropagationTaskTO ignore) {
+                        if (target != null) {
+                            target.add(container);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.TASK_LIST).build(componentId);
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected Collection<ActionType> getBulkActions() {
+        final List<ActionType> bulkActions = new ArrayList<>();
+        bulkActions.add(ActionType.DELETE);
+        bulkActions.add(ActionType.EXECUTE);
+        return bulkActions;
+    }
+
+    @Override
+    protected PropagationTasksProvider dataProvider() {
+        return new PropagationTasksProvider(rows, this.resource);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_PROPAGATION_TASKS_PAGINATOR_ROWS;
+    }
+
+    public class PropagationTasksProvider extends TaskDataProvider<PropagationTaskTO> {
+
+        private static final long serialVersionUID = 4725679400450513556L;
+
+        private final String resource;
+
+        public PropagationTasksProvider(final int paginatorRows, final String resource) {
+            super(paginatorRows, TaskType.PROPAGATION, restClient);
+            this.resource = resource;
+        }
+
+        @Override
+        public Iterator<PropagationTaskTO> iterator(final long first, final long count) {
+            final int page = ((int) first / paginatorRows);
+
+            final List<PropagationTaskTO> tasks = restClient.listPropagationTasks(
+                    resource, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+
+            Collections.sort(tasks, getComparator());
+            return tasks.iterator();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskSearchResultPanel.java
deleted file mode 100644
index 767eea3..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTaskSearchResultPanel.java
+++ /dev/null
@@ -1,225 +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.syncope.client.console.tasks;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.SyncopeConsoleSession;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.commons.TaskDataProvider;
-import org.apache.syncope.client.console.panels.ModalPanel;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
-import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
-import org.apache.syncope.common.lib.to.PropagationTaskTO;
-import org.apache.syncope.common.lib.types.StandardEntitlement;
-import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.ResourceModel;
-import org.apache.wicket.model.StringResourceModel;
-
-/**
- * Tasks page.
- */
-public abstract class PropagationTaskSearchResultPanel extends TaskSearchResultPanel<PropagationTaskTO>
-        implements ModalPanel<PropagationTaskTO> {
-
-    private static final long serialVersionUID = 4984337552918213290L;
-
-    private final String resource;
-
-    protected PropagationTaskSearchResultPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final String resource,
-            final PageReference pageRef) {
-        super(baseModal, multiLevelPanelRef, pageRef);
-        this.resource = resource;
-        initResultTable();
-    }
-
-    @Override
-    protected List<IColumn<PropagationTaskTO, String>> getColumns() {
-        final List<IColumn<PropagationTaskTO, String>> columns = new ArrayList<>();
-
-        columns.add(new PropertyColumn<PropagationTaskTO, String>(
-                new StringResourceModel("key", this, null), "key", "key"));
-
-        columns.add(new PropertyColumn<PropagationTaskTO, String>(new StringResourceModel(
-                "operation", this, null), "operation", "operation"));
-
-        columns.add(new PropertyColumn<PropagationTaskTO, String>(
-                new StringResourceModel("anyTypeKind", this, null), "anyTypeKind", "anyTypeKind"));
-
-        columns.add(new PropertyColumn<PropagationTaskTO, String>(
-                new StringResourceModel("anyKey", this, null), "anyKey", "anyKey"));
-
-        columns.add(new PropertyColumn<PropagationTaskTO, String>(
-                new StringResourceModel("connObjectKey", this, null), "connObjectKey", "connObjectKey"));
-
-        columns.add(new DatePropertyColumn<PropagationTaskTO>(
-                new StringResourceModel("start", this, null), "start", "start"));
-
-        columns.add(new DatePropertyColumn<PropagationTaskTO>(
-                new StringResourceModel("end", this, null), "end", "end"));
-
-        columns.add(new PropertyColumn<PropagationTaskTO, String>(
-                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
-
-        columns.add(new ActionColumn<PropagationTaskTO, String>(new ResourceModel("actions")) {
-
-            private static final long serialVersionUID = 2054811145491901166L;
-
-            @Override
-            public String getCssClass() {
-                return "action";
-            }
-
-            @Override
-            public ActionLinksPanel<PropagationTaskTO> getActions(
-                    final String componentId, final IModel<PropagationTaskTO> model) {
-
-                final PropagationTaskTO taskTO = model.getObject();
-
-                final ActionLinksPanel<PropagationTaskTO> panel = ActionLinksPanel.<PropagationTaskTO>builder().
-                        add(new ActionLink<PropagationTaskTO>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final PropagationTaskTO modelObject) {
-                                viewTask(taskTO, target);
-                            }
-                        }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ).
-                        add(new ActionLink<PropagationTaskTO>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final PropagationTaskTO modelObject) {
-                                try {
-                                    restClient.startExecution(taskTO.getKey(), new Date());
-                                    info(getString(Constants.OPERATION_SUCCEEDED));
-                                    target.add(container);
-                                } catch (SyncopeClientException e) {
-                                    error(StringUtils.isBlank(e.getMessage())
-                                            ? e.getClass().getName() : e.getMessage());
-                                    LOG.error("While running {}", taskTO.getKey(), e);
-                                }
-                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
-                            }
-                        }, ActionLink.ActionType.EXECUTE, StandardEntitlement.TASK_EXECUTE).
-                        add(new ActionLink<PropagationTaskTO>() {
-
-                            private static final long serialVersionUID = -3722207913631435501L;
-
-                            @Override
-                            public void onClick(final AjaxRequestTarget target, final PropagationTaskTO modelObject) {
-                                try {
-                                    restClient.delete(taskTO.getKey(), PropagationTaskTO.class);
-                                    info(getString(Constants.OPERATION_SUCCEEDED));
-                                    target.add(container);
-                                } catch (SyncopeClientException e) {
-                                    LOG.error("While deleting {}", taskTO.getKey(), e);
-                                    error(StringUtils.isBlank(e.getMessage())
-                                            ? e.getClass().getName() : e.getMessage());
-                                }
-                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
-                            }
-                        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE).build(componentId);
-
-                return panel;
-            }
-
-            @Override
-            public ActionLinksPanel<PropagationTaskTO> getHeader(final String componentId) {
-                final ActionLinksPanel.Builder<PropagationTaskTO> panel = ActionLinksPanel.builder();
-
-                return panel.add(new ActionLink<PropagationTaskTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final PropagationTaskTO ignore) {
-                        if (target != null) {
-                            target.add(container);
-                        }
-                    }
-                }, ActionLink.ActionType.RELOAD, StandardEntitlement.TASK_LIST).build(componentId);
-            }
-        });
-
-        return columns;
-    }
-
-    @Override
-    protected Collection<ActionType> getBulkActions() {
-        final List<ActionType> bulkActions = new ArrayList<>();
-        bulkActions.add(ActionType.DELETE);
-        bulkActions.add(ActionType.EXECUTE);
-        return bulkActions;
-    }
-
-    @Override
-    protected PropagationTasksProvider dataProvider() {
-        return new PropagationTasksProvider(rows, this.resource);
-    }
-
-    @Override
-    protected String paginatorRowsKey() {
-        return Constants.PREF_PROPAGATION_TASKS_PAGINATOR_ROWS;
-    }
-
-    public class PropagationTasksProvider extends TaskDataProvider<PropagationTaskTO> {
-
-        private static final long serialVersionUID = 4725679400450513556L;
-
-        private final String resource;
-
-        public PropagationTasksProvider(final int paginatorRows, final String resource) {
-            super(paginatorRows, TaskType.PROPAGATION, restClient);
-            this.resource = resource;
-        }
-
-        @Override
-        public Iterator<PropagationTaskTO> iterator(final long first, final long count) {
-            final int page = ((int) first / paginatorRows);
-
-            final List<PropagationTaskTO> tasks = restClient.listPropagationTasks(
-                    resource, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
-
-            Collections.sort(tasks, getComparator());
-            return tasks.iterator();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTasks.java
index 7f3bb9c..c49bdf3 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTasks.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PropagationTasks.java
@@ -36,7 +36,7 @@ public class PropagationTasks extends AbstractTasks {
         final MultilevelPanel mlp = new MultilevelPanel("tasks");
         add(mlp);
 
-        mlp.setFirstLevel(new PropagationTaskSearchResultPanel(baseModal, mlp, resource, pageReference) {
+        mlp.setFirstLevel(new PropagationTaskDirectoryPanel(baseModal, mlp, resource, pageReference) {
 
             private static final long serialVersionUID = -2195387360323687302L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskDirectoryPanel.java
new file mode 100644
index 0000000..8b0d9dc
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskDirectoryPanel.java
@@ -0,0 +1,128 @@
+/*
+ * 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.syncope.client.console.tasks;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.common.lib.to.AbstractProvisioningTaskTO;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.model.StringResourceModel;
+
+/**
+ * Tasks page.
+ *
+ * @param <T> Sched task type.
+ */
+public abstract class ProvisioningTaskDirectoryPanel<T extends AbstractProvisioningTaskTO>
+        extends SchedTaskDirectoryPanel<T> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    private final String resource;
+
+    protected ProvisioningTaskDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final Class<T> reference,
+            final String resource,
+            final PageReference pageRef) {
+        super(baseModal, multiLevelPanelRef, reference, pageRef);
+        this.resource = resource;
+
+        this.schedTaskTO.setResource(resource);
+
+        // super in order to call the parent implementation
+        super.initResultTable();
+    }
+
+    @Override
+    protected void initResultTable() {
+        // DO nothing in order to disable the call performed by the parent
+    }
+
+    @Override
+    protected List<IColumn<T, String>> getFieldColumns() {
+        final List<IColumn<T, String>> columns = new ArrayList<>();
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("key", this, null), "key", "key"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("name", this, null), "name", "name"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("description", this, null), "description", "description"));
+
+        if (reference == PullTaskTO.class) {
+            columns.add(new PropertyColumn<T, String>(
+                    new StringResourceModel("destinationRealm", this, null), "destinationRealm", "destinationRealm"));
+        }
+
+        columns.add(new DatePropertyColumn<T>(
+                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
+
+        columns.add(new DatePropertyColumn<T>(
+                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("active", this, null), "active", "active"));
+
+        return columns;
+    }
+
+    public class ProvisioningTasksProvider<T extends AbstractProvisioningTaskTO> extends SchedTasksProvider<T> {
+
+        private static final long serialVersionUID = 4725679400450513556L;
+
+        private final Class<T> reference;
+
+        public ProvisioningTasksProvider(final Class<T> reference, final TaskType id, final int paginatorRows) {
+            super(reference, id, paginatorRows);
+            this.reference = reference;
+        }
+
+        @Override
+        public long size() {
+            return restClient.count(resource, id);
+        }
+
+        @Override
+        public Iterator<T> iterator(final long first, final long count) {
+            final int page = ((int) first / paginatorRows);
+
+            final List<T> tasks = restClient.list(
+                    resource, reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+
+            Collections.sort(tasks, getComparator());
+            return tasks.iterator();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskSearchResultPanel.java
deleted file mode 100644
index c0c85e2..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/ProvisioningTaskSearchResultPanel.java
+++ /dev/null
@@ -1,128 +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.syncope.client.console.tasks;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.common.lib.to.AbstractProvisioningTaskTO;
-import org.apache.syncope.common.lib.to.PullTaskTO;
-import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.wicket.PageReference;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
-import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
-import org.apache.wicket.model.StringResourceModel;
-
-/**
- * Tasks page.
- *
- * @param <T> Sched task type.
- */
-public abstract class ProvisioningTaskSearchResultPanel<T extends AbstractProvisioningTaskTO>
-        extends SchedTaskSearchResultPanel<T> {
-
-    private static final long serialVersionUID = 4984337552918213290L;
-
-    private final String resource;
-
-    protected ProvisioningTaskSearchResultPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final Class<T> reference,
-            final String resource,
-            final PageReference pageRef) {
-        super(baseModal, multiLevelPanelRef, reference, pageRef);
-        this.resource = resource;
-
-        this.schedTaskTO.setResource(resource);
-
-        // super in order to call the parent implementation
-        super.initResultTable();
-    }
-
-    @Override
-    protected void initResultTable() {
-        // DO nothing in order to disable the call performed by the parent
-    }
-
-    @Override
-    protected List<IColumn<T, String>> getFieldColumns() {
-        final List<IColumn<T, String>> columns = new ArrayList<>();
-
-        columns.add(new PropertyColumn<T, String>(
-                new StringResourceModel("key", this, null), "key", "key"));
-
-        columns.add(new PropertyColumn<T, String>(
-                new StringResourceModel("name", this, null), "name", "name"));
-
-        columns.add(new PropertyColumn<T, String>(
-                new StringResourceModel("description", this, null), "description", "description"));
-
-        if (reference == PullTaskTO.class) {
-            columns.add(new PropertyColumn<T, String>(
-                    new StringResourceModel("destinationRealm", this, null), "destinationRealm", "destinationRealm"));
-        }
-
-        columns.add(new DatePropertyColumn<T>(
-                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
-
-        columns.add(new DatePropertyColumn<T>(
-                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
-
-        columns.add(new PropertyColumn<T, String>(
-                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
-
-        columns.add(new PropertyColumn<T, String>(
-                new StringResourceModel("active", this, null), "active", "active"));
-
-        return columns;
-    }
-
-    public class ProvisioningTasksProvider<T extends AbstractProvisioningTaskTO> extends SchedTasksProvider<T> {
-
-        private static final long serialVersionUID = 4725679400450513556L;
-
-        private final Class<T> reference;
-
-        public ProvisioningTasksProvider(final Class<T> reference, final TaskType id, final int paginatorRows) {
-            super(reference, id, paginatorRows);
-            this.reference = reference;
-        }
-
-        @Override
-        public long size() {
-            return restClient.count(resource, id);
-        }
-
-        @Override
-        public Iterator<T> iterator(final long first, final long count) {
-            final int page = ((int) first / paginatorRows);
-
-            final List<T> tasks = restClient.list(
-                    resource, reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
-
-            Collections.sort(tasks, getComparator());
-            return tasks.iterator();
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskDirectoryPanel.java
new file mode 100644
index 0000000..dcf99e6
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskDirectoryPanel.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.tasks;
+
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.wicket.PageReference;
+
+public abstract class PullTaskDirectoryPanel extends ProvisioningTaskDirectoryPanel<PullTaskTO> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    protected PullTaskDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final String resource,
+            final PageReference pageRef) {
+        super(baseModal, multiLevelPanelRef, PullTaskTO.class, resource, pageRef);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_PUSH_TASKS_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected ProvisioningTasksProvider<PullTaskTO> dataProvider() {
+        return new ProvisioningTasksProvider<>(reference, TaskType.PULL, rows);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskSearchResultPanel.java
deleted file mode 100644
index dd01779..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTaskSearchResultPanel.java
+++ /dev/null
@@ -1,49 +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.syncope.client.console.tasks;
-
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.common.lib.to.PullTaskTO;
-import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.wicket.PageReference;
-
-public abstract class PullTaskSearchResultPanel extends ProvisioningTaskSearchResultPanel<PullTaskTO> {
-
-    private static final long serialVersionUID = 4984337552918213290L;
-
-    protected PullTaskSearchResultPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final String resource,
-            final PageReference pageRef) {
-        super(baseModal, multiLevelPanelRef, PullTaskTO.class, resource, pageRef);
-    }
-
-    @Override
-    protected String paginatorRowsKey() {
-        return Constants.PREF_PUSH_TASKS_PAGINATOR_ROWS;
-    }
-
-    @Override
-    protected ProvisioningTasksProvider<PullTaskTO> dataProvider() {
-        return new ProvisioningTasksProvider<>(reference, TaskType.PULL, rows);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTasks.java
index 559469b..39540f5 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTasks.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PullTasks.java
@@ -38,7 +38,7 @@ public class PullTasks extends AbstractTasks {
         final MultilevelPanel mlp = new MultilevelPanel("tasks");
         add(mlp);
 
-        mlp.setFirstLevel(new PullTaskSearchResultPanel(baseModal, mlp, resource, pageReference) {
+        mlp.setFirstLevel(new PullTaskDirectoryPanel(baseModal, mlp, resource, pageReference) {
 
             private static final long serialVersionUID = -2195387360323687302L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskDirectoryPanel.java
new file mode 100644
index 0000000..440b0e2
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskDirectoryPanel.java
@@ -0,0 +1,52 @@
+/*
+ * 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.syncope.client.console.tasks;
+
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.wicket.PageReference;
+
+/**
+ * Push Tasks page.
+ */
+public abstract class PushTaskDirectoryPanel extends ProvisioningTaskDirectoryPanel<PushTaskTO> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    protected PushTaskDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final String resource,
+            final PageReference pageRef) {
+        super(baseModal, multiLevelPanelRef, PushTaskTO.class, resource, pageRef);
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_PUSH_TASKS_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected ProvisioningTasksProvider<PushTaskTO> dataProvider() {
+        return new ProvisioningTasksProvider<>(reference, TaskType.PUSH, rows);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskSearchResultPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskSearchResultPanel.java
deleted file mode 100644
index 2d0d245..0000000
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTaskSearchResultPanel.java
+++ /dev/null
@@ -1,52 +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.syncope.client.console.tasks;
-
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.panels.MultilevelPanel;
-import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
-import org.apache.syncope.common.lib.to.PushTaskTO;
-import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.wicket.PageReference;
-
-/**
- * Push Tasks page.
- */
-public abstract class PushTaskSearchResultPanel extends ProvisioningTaskSearchResultPanel<PushTaskTO> {
-
-    private static final long serialVersionUID = 4984337552918213290L;
-
-    protected PushTaskSearchResultPanel(
-            final BaseModal<?> baseModal,
-            final MultilevelPanel multiLevelPanelRef,
-            final String resource,
-            final PageReference pageRef) {
-        super(baseModal, multiLevelPanelRef, PushTaskTO.class, resource, pageRef);
-    }
-
-    @Override
-    protected String paginatorRowsKey() {
-        return Constants.PREF_PUSH_TASKS_PAGINATOR_ROWS;
-    }
-
-    @Override
-    protected ProvisioningTasksProvider<PushTaskTO> dataProvider() {
-        return new ProvisioningTasksProvider<PushTaskTO>(reference, TaskType.PUSH, rows);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTasks.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTasks.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTasks.java
index 87810aa..d23e980 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTasks.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/PushTasks.java
@@ -38,7 +38,7 @@ public class PushTasks extends AbstractTasks {
         final MultilevelPanel mlp = new MultilevelPanel("tasks");
         add(mlp);
 
-        mlp.setFirstLevel(new PushTaskSearchResultPanel(baseModal, mlp, resource, pageReference) {
+        mlp.setFirstLevel(new PushTaskDirectoryPanel(baseModal, mlp, resource, pageReference) {
 
             private static final long serialVersionUID = -2195387360323687302L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/3e8912c3/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
new file mode 100644
index 0000000..1ef8b50
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskDirectoryPanel.java
@@ -0,0 +1,315 @@
+/*
+ * 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.syncope.client.console.tasks;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.TaskDataProvider;
+import org.apache.syncope.client.console.panels.ModalPanel;
+import org.apache.syncope.client.console.panels.MultilevelPanel;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink.ActionType;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
+
+/**
+ * Tasks page.
+ *
+ * @param <T> Sched task type.
+ */
+public abstract class SchedTaskDirectoryPanel<T extends SchedTaskTO>
+        extends TaskDirectoryPanel<T> implements ModalPanel<T> {
+
+    private static final long serialVersionUID = 4984337552918213290L;
+
+    protected final Class<T> reference;
+
+    protected T schedTaskTO;
+
+    private final StartAtTogglePanel startAt;
+
+    protected SchedTaskDirectoryPanel(
+            final BaseModal<?> baseModal,
+            final MultilevelPanel multiLevelPanelRef,
+            final Class<T> reference,
+            final PageReference pageRef) {
+        super(baseModal, multiLevelPanelRef, pageRef);
+        this.reference = reference;
+
+        try {
+            schedTaskTO = reference.newInstance();
+        } catch (InstantiationException | IllegalAccessException e) {
+            LOG.error("Falure instantiating task", e);
+        }
+
+        this.addNewItemPanelBuilder(new SchedTaskWizardBuilder<>(schedTaskTO, pageRef), true);
+
+        MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, ENABLE, StandardEntitlement.TASK_CREATE);
+
+        initResultTable();
+
+        startAt = new StartAtTogglePanel(container);
+        addInnerObject(startAt);
+    }
+
+    protected List<IColumn<T, String>> getFieldColumns() {
+        final List<IColumn<T, String>> columns = new ArrayList<>();
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("key", this, null), "key", "key"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("name", this, null), "name", "name"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("description", this, null), "description", "description"));
+
+        columns.add(new PropertyColumn<T, String>(new StringResourceModel(
+                "jobDelegateClassName", this, null), "jobDelegateClassName", "jobDelegateClassName") {
+
+            private static final long serialVersionUID = -3223917055078733093L;
+
+            @Override
+            public void populateItem(
+                    final Item<ICellPopulator<T>> item, final String componentId, final IModel<T> rowModel) {
+                final IModel<?> model = getDataModel(rowModel);
+                if (model != null && model.getObject() instanceof String) {
+                    String value = String.class.cast(model.getObject());
+                    if (value.length() > 20) {
+                        item.add(new Label(componentId, new Model<>("..." + value.substring(value.length() - 17))));
+                    } else {
+                        item.add(new Label(componentId, getDataModel(rowModel)));
+                    }
+                } else {
+                    super.populateItem(item, componentId, rowModel);
+                }
+            }
+
+        });
+
+        columns.add(new DatePropertyColumn<T>(
+                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
+
+        columns.add(new DatePropertyColumn<T>(
+                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+
+        columns.add(new PropertyColumn<T, String>(
+                new StringResourceModel("active", this, null), "active", "active"));
+
+        return columns;
+    }
+
+    @Override
+    protected final List<IColumn<T, String>> getColumns() {
+        final List<IColumn<T, String>> columns = new ArrayList<>();
+
+        columns.addAll(getFieldColumns());
+
+        columns.add(new ActionColumn<T, String>(new ResourceModel("actions")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public String getCssClass() {
+                return "action";
+            }
+
+            @Override
+            public ActionLinksPanel<T> getActions(
+                    final String componentId, final IModel<T> model) {
+
+                final T taskTO = model.getObject();
+
+                final ActionLinksPanel<T> panel = ActionLinksPanel.<T>builder().
+                        add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                viewTask(taskTO, target);
+                            }
+                        }, ActionLink.ActionType.VIEW, StandardEntitlement.TASK_READ).
+                        add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                send(SchedTaskDirectoryPanel.this, Broadcast.EXACT,
+                                        new AjaxWizard.EditItemActionEvent<>(
+                                                restClient.readSchedTask(reference, model.getObject().getKey()),
+                                                target));
+                            }
+                        }, ActionLink.ActionType.EDIT, StandardEntitlement.TASK_UPDATE).
+                        add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                final T clone = SerializationUtils.clone(model.getObject());
+                                clone.setKey(0L);
+                                send(SchedTaskDirectoryPanel.this, Broadcast.EXACT,
+                                        new AjaxWizard.EditItemActionEvent<>(clone, target));
+                            }
+                        }, ActionLink.ActionType.CLONE, StandardEntitlement.TASK_CREATE).
+                        add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                startAt.setTaskTO(target, model.getObject());
+                                startAt.toggle(target, true);
+                            }
+                        }, ActionLink.ActionType.EXECUTE, StandardEntitlement.TASK_EXECUTE).
+                        add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                try {
+                                    restClient.startExecution(taskTO.getKey(), null, true);
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                    target.add(container);
+                                } catch (SyncopeClientException e) {
+                                    error(StringUtils.isBlank(e.getMessage())
+                                            ? e.getClass().getName() : e.getMessage());
+                                    LOG.error("While running propagation task {}", taskTO.getKey(), e);
+                                }
+                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                            }
+                        }, ActionLink.ActionType.DRYRUN, StandardEntitlement.TASK_EXECUTE).
+                        add(new ActionLink<T>() {
+
+                            private static final long serialVersionUID = -3722207913631435501L;
+
+                            @Override
+                            public void onClick(final AjaxRequestTarget target, final T ignore) {
+                                try {
+                                    restClient.delete(taskTO.getKey(), reference);
+                                    info(getString(Constants.OPERATION_SUCCEEDED));
+                                    target.add(container);
+                                } catch (SyncopeClientException e) {
+                                    error(StringUtils.isBlank(e.getMessage())
+                                            ? e.getClass().getName() : e.getMessage());
+                                    LOG.error("While deleting propagation task {}", taskTO.getKey(), e);
+                                }
+                                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+                            }
+                        }, ActionLink.ActionType.DELETE, StandardEntitlement.TASK_DELETE).build(componentId);
+
+                return panel;
+            }
+
+            @Override
+            public ActionLinksPanel<T> getHeader(final String componentId) {
+                final ActionLinksPanel.Builder<T> panel = ActionLinksPanel.builder();
+
+                return panel.add(new ActionLink<T>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final T ignore) {
+                        if (target != null) {
+                            target.add(container);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, StandardEntitlement.TASK_LIST).build(componentId);
+            }
+        });
+
+        return columns;
+    }
+
+    @Override
+    protected String paginatorRowsKey() {
+        return Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS;
+    }
+
+    @Override
+    protected Collection<ActionType> getBulkActions() {
+        final List<ActionType> bulkActions = new ArrayList<>();
+        bulkActions.add(ActionType.DELETE);
+        bulkActions.add(ActionType.EXECUTE);
+        bulkActions.add(ActionType.DRYRUN);
+        return bulkActions;
+    }
+
+    @Override
+    protected SchedTasksProvider<T> dataProvider() {
+        return new SchedTasksProvider<>(reference, TaskType.SCHEDULED, rows);
+    }
+
+    public class SchedTasksProvider<T extends SchedTaskTO> extends TaskDataProvider<T> {
+
+        private static final long serialVersionUID = 4725679400450513556L;
+
+        private final Class<T> reference;
+
+        public SchedTasksProvider(final Class<T> reference, final TaskType id, final int paginatorRows) {
+            super(paginatorRows, id, restClient);
+            this.reference = reference;
+        }
+
+        @Override
+        public Iterator<T> iterator(final long first, final long count) {
+            final int page = ((int) first / paginatorRows);
+
+            final List<T> tasks = restClient.list(
+                    reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort());
+
+            Collections.sort(tasks, getComparator());
+            return tasks.iterator();
+        }
+    }
+}