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 2015/02/05 17:01:02 UTC

[31/52] syncope git commit: [SYNCOPE-620] Console (JAR) in, now time for console-reference

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSearchResultPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSearchResultPanel.java
new file mode 100644
index 0000000..3762dee
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSearchResultPanel.java
@@ -0,0 +1,175 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.ResultStatusModalPage;
+import org.apache.syncope.client.console.pages.RoleModalPage;
+import org.apache.syncope.client.console.pages.StatusModalPage;
+import org.apache.syncope.client.console.rest.AbstractSubjectRestClient;
+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.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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.repeater.Item;
+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 String fiql, final PageReference callerRef, final AbstractSubjectRestClient restClient) {
+
+        super(id, filtered, fiql, callerRef, restClient);
+        initResultTable();
+    }
+
+    @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<RoleTO>(
+                                        page.getPageReference(), statusmodal, (RoleTO) model.getObject());
+                            }
+                        });
+
+                        statusmodal.show(target);
+                    }
+                }, ActionLink.ActionType.MANAGE_RESOURCES, 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, 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().getETagValue(), model.getObject().getKey());
+
+                            page.setModalResult(true);
+
+                            editmodal.setPageCreator(new ModalWindow.PageCreator() {
+
+                                private static final long serialVersionUID = -7834632442532690940L;
+
+                                @Override
+                                public Page createPage() {
+                                    return new ResultStatusModalPage.Builder(editmodal, roleTO).build();
+                                }
+                            });
+
+                            editmodal.show(target);
+                        } catch (SyncopeClientException scce) {
+                            error(getString(Constants.OPERATION_ERROR) + ": " + scce.getMessage());
+                            feedbackPanel.refresh(target);
+                        }
+                    }
+                }, 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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSecurityPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSecurityPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSecurityPanel.java
new file mode 100644
index 0000000..b60d1e4
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSecurityPanel.java
@@ -0,0 +1,198 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.PolicyRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractPolicyTO;
+import org.apache.syncope.common.lib.types.PolicyType;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.ChoiceRenderer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RoleSecurityPanel extends Panel {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(RoleSecurityPanel.class);
+
+    private static final long serialVersionUID = -7982691107029848579L;
+
+    @SpringBean
+    private PolicyRestClient policyRestClient;
+
+    private IModel<Map<Long, String>> passwordPolicies = null;
+
+    private IModel<Map<Long, String>> accountPolicies = null;
+
+    public <T extends AbstractAttributableTO> RoleSecurityPanel(final String id, final T entityTO) {
+        super(id);
+
+        setOutputMarkupId(true);
+
+        passwordPolicies = new LoadableDetachableModel<Map<Long, String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected Map<Long, String> load() {
+                Map<Long, String> res = new HashMap<>();
+                for (AbstractPolicyTO policyTO : policyRestClient.getPolicies(PolicyType.PASSWORD, false)) {
+                    res.put(policyTO.getKey(), policyTO.getDescription());
+                }
+                return res;
+            }
+        };
+
+        accountPolicies = new LoadableDetachableModel<Map<Long, String>>() {
+
+            private static final long serialVersionUID = -2012833443695917883L;
+
+            @Override
+            protected Map<Long, String> load() {
+                Map<Long, String> res = new HashMap<>();
+                for (AbstractPolicyTO policyTO : policyRestClient.getPolicies(PolicyType.ACCOUNT, false)) {
+                    res.put(policyTO.getKey(), policyTO.getDescription());
+                }
+                return res;
+            }
+        };
+
+        final WebMarkupContainer securityContainer = new WebMarkupContainer("security");
+
+        securityContainer.setOutputMarkupId(true);
+        add(securityContainer);
+
+        // -------------------------------
+        // Password policy specification
+        // -------------------------------
+        final AjaxDropDownChoicePanel<Long> passwordPolicy = new AjaxDropDownChoicePanel<Long>("passwordPolicy",
+                "passwordPolicy", new PropertyModel<Long>(entityTO, "passwordPolicy"));
+
+        passwordPolicy.setChoiceRenderer(new PolicyRenderer(PolicyType.PASSWORD));
+
+        passwordPolicy.setChoices(new ArrayList<Long>(passwordPolicies.getObject().keySet()));
+
+        ((DropDownChoice<?>) passwordPolicy.getField()).setNullValid(true);
+
+        securityContainer.add(passwordPolicy);
+
+        final AjaxCheckBoxPanel inhPasswordPolicy = new AjaxCheckBoxPanel("inheritPasswordPolicy",
+                "inheritPasswordPolicy", new PropertyModel<Boolean>(entityTO, "inheritPasswordPolicy"));
+
+        passwordPolicy.setReadOnly(inhPasswordPolicy.getModelObject());
+
+        inhPasswordPolicy.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                passwordPolicy.setReadOnly(inhPasswordPolicy.getModelObject());
+                target.add(passwordPolicy);
+            }
+        });
+
+        securityContainer.add(inhPasswordPolicy);
+        // -------------------------------
+
+        // -------------------------------
+        // Account policy specification
+        // -------------------------------
+        final AjaxDropDownChoicePanel<Long> accountPolicy = new AjaxDropDownChoicePanel<Long>("accountPolicy",
+                "accountPolicy", new PropertyModel<Long>(entityTO, "accountPolicy"));
+
+        accountPolicy.setChoiceRenderer(new PolicyRenderer(PolicyType.ACCOUNT));
+
+        accountPolicy.setChoices(new ArrayList<Long>(accountPolicies.getObject().keySet()));
+
+        ((DropDownChoice<?>) accountPolicy.getField()).setNullValid(true);
+
+        securityContainer.add(accountPolicy);
+
+        final AjaxCheckBoxPanel inhAccountPolicy = new AjaxCheckBoxPanel("inheritAccountPolicy",
+                "inheritAccountPolicy", new PropertyModel<Boolean>(entityTO, "inheritAccountPolicy"));
+        accountPolicy.setReadOnly(inhAccountPolicy.getModelObject());
+
+        inhAccountPolicy.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                accountPolicy.setReadOnly(inhAccountPolicy.getModelObject());
+                target.add(accountPolicy);
+            }
+        });
+
+        securityContainer.add(inhAccountPolicy);
+        // -------------------------------
+    }
+
+    private class PolicyRenderer extends ChoiceRenderer<Long> {
+
+        private static final long serialVersionUID = 8060500161321947000L;
+
+        private PolicyType type;
+
+        public PolicyRenderer(final PolicyType type) {
+            super();
+            this.type = type;
+        }
+
+        @Override
+        public Object getDisplayValue(final Long object) {
+            Object displayValue;
+            switch (type) {
+                case ACCOUNT:
+                    displayValue = accountPolicies.getObject().get(object);
+                    break;
+                case PASSWORD:
+                    displayValue = passwordPolicies.getObject().get(object);
+                    break;
+                default:
+                    displayValue = "";
+            }
+            return displayValue;
+        }
+
+        @Override
+        public String getIdValue(Long object, int index) {
+            return String.valueOf(object != null
+                    ? object
+                    : 0L);
+        }
+    };
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSummaryPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSummaryPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSummaryPanel.java
new file mode 100644
index 0000000..d7663be
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleSummaryPanel.java
@@ -0,0 +1,153 @@
+/*
+ * 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.panels;
+
+import java.io.Serializable;
+import org.apache.syncope.client.console.commons.XMLRolesReader;
+import org.apache.syncope.client.console.pages.RoleModalPage;
+import org.apache.syncope.client.console.rest.RoleRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RoleSummaryPanel extends Panel {
+
+    private static final long serialVersionUID = 643769814985593156L;
+
+    /**
+     * Logger.
+     */
+    private static final Logger LOG = LoggerFactory.getLogger(RoleSummaryPanel.class);
+
+    @SpringBean
+    private XMLRolesReader xmlRolesReader;
+
+    @SpringBean
+    private RoleRestClient restClient;
+
+    private RoleTO selectedNode;
+
+    public static class Builder implements Serializable {
+
+        private static final long serialVersionUID = 4164563358509351832L;
+
+        private String id;
+
+        private ModalWindow window;
+
+        private PageReference callerPageRef;
+
+        private Long selectedNodeId = null;
+
+        public Builder(final String id) {
+            this.id = id;
+        }
+
+        public RoleSummaryPanel.Builder window(final ModalWindow window) {
+            this.window = window;
+            return this;
+        }
+
+        public RoleSummaryPanel.Builder callerPageRef(final PageReference callerPageRef) {
+            this.callerPageRef = callerPageRef;
+            return this;
+        }
+
+        public RoleSummaryPanel.Builder selectedNodeId(final Long selectedNodeId) {
+            this.selectedNodeId = selectedNodeId;
+            return this;
+        }
+
+        public RoleSummaryPanel build() {
+            return new RoleSummaryPanel(this);
+        }
+    }
+
+    private RoleSummaryPanel(final Builder builder) {
+        super(builder.id);
+
+        if (builder.selectedNodeId == null || builder.selectedNodeId == 0) {
+            selectedNode = null;
+        } else {
+            try {
+                selectedNode = restClient.read(builder.selectedNodeId);
+            } catch (SyncopeClientException e) {
+                LOG.error("Could not read {}", builder.selectedNodeId, e);
+                selectedNode = null;
+                builder.selectedNodeId = null;
+            }
+        }
+
+        Fragment fragment = new Fragment("roleSummaryPanel",
+                builder.selectedNodeId == null
+                        ? "fakerootFrag"
+                        : (builder.selectedNodeId == 0 ? "rootPanel" : "roleViewPanel"),
+                this);
+
+        if (builder.selectedNodeId != null) {
+            if (builder.selectedNodeId == 0) {
+                @SuppressWarnings("rawtypes")
+                final ActionLinksPanel links = new ActionLinksPanel("actionLinks", new Model(), builder.callerPageRef);
+                links.setOutputMarkupId(true);
+                fragment.add(links);
+
+                links.addWithRoles(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        builder.window.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new RoleModalPage(builder.callerPageRef, builder.window, new RoleTO());
+                            }
+                        });
+
+                        builder.window.show(target);
+                    }
+                }, ActionLink.ActionType.CREATE, xmlRolesReader.getEntitlement("Roles", "create"));
+            } else {
+                RoleTabPanel roleTabPanel =
+                        new RoleTabPanel("nodeViewPanel", selectedNode, builder.window, builder.callerPageRef);
+                roleTabPanel.setOutputMarkupId(true);
+                fragment.add(roleTabPanel);
+            }
+        }
+        add(fragment);
+    }
+
+    public RoleTO getSelectedNode() {
+        return selectedNode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleTabPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleTabPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleTabPanel.java
new file mode 100644
index 0000000..7c483b5
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleTabPanel.java
@@ -0,0 +1,195 @@
+/*
+ * 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.panels;
+
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.Mode;
+import org.apache.syncope.client.console.commons.XMLRolesReader;
+import org.apache.syncope.client.console.pages.ResultStatusModalPage;
+import org.apache.syncope.client.console.pages.RoleModalPage;
+import org.apache.syncope.client.console.pages.Roles;
+import org.apache.syncope.client.console.pages.StatusModalPage;
+import org.apache.syncope.client.console.rest.RoleRestClient;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxButton;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.CompoundPropertyModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class RoleTabPanel extends Panel {
+
+    private static final long serialVersionUID = 859236186975983959L;
+
+    @SpringBean
+    private XMLRolesReader xmlRolesReader;
+
+    @SpringBean
+    private RoleRestClient roleRestClient;
+
+    @SpringBean
+    private UserRestClient userRestClient;
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public RoleTabPanel(final String id, final RoleTO selectedNode, final ModalWindow window,
+            final PageReference pageRef) {
+
+        super(id);
+
+        this.add(new Label("displayName", selectedNode.getDisplayName()));
+
+        final ActionLinksPanel links = new ActionLinksPanel("actionLinks", new Model(), pageRef);
+        links.setOutputMarkupId(true);
+        this.add(links);
+        links.addWithRoles(new ActionLink() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        RoleTO roleTO = new RoleTO();
+                        roleTO.setParent(selectedNode.getKey());
+                        return new RoleModalPage(pageRef, window, roleTO);
+                    }
+                });
+
+                window.show(target);
+            }
+        }, ActionLink.ActionType.CREATE, xmlRolesReader.getEntitlement("Roles", "create"));
+        links.addWithRoles(new ActionLink() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new StatusModalPage<RoleTO>(pageRef, window, roleRestClient.read(selectedNode.getKey()));
+                    }
+                });
+
+                window.show(target);
+            }
+        }, ActionLink.ActionType.MANAGE_RESOURCES, xmlRolesReader.getEntitlement("Roles", "update"));
+        links.addWithRoles(new ActionLink() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        RoleTO roleTO = roleRestClient.read(selectedNode.getKey());
+                        return new RoleModalPage(pageRef, window, roleTO);
+                    }
+                });
+
+                window.show(target);
+            }
+        }, ActionLink.ActionType.EDIT, xmlRolesReader.getEntitlement("Roles", "update"));
+        links.addWithRoles(new ActionLink() {
+
+            private static final long serialVersionUID = -3722207913631435501L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                try {
+                    final RoleTO roleTO = roleRestClient.delete(selectedNode.getETagValue(), selectedNode.getKey());
+
+                    ((Roles) pageRef.getPage()).setModalResult(true);
+
+                    window.setPageCreator(new ModalWindow.PageCreator() {
+
+                        private static final long serialVersionUID = -7834632442532690940L;
+
+                        @Override
+                        public Page createPage() {
+                            return new ResultStatusModalPage.Builder(window, roleTO).build();
+                        }
+                    });
+
+                    window.show(target);
+                } catch (SyncopeClientException e) {
+                    error(getString(Constants.OPERATION_ERROR) + ": " + e.getMessage());
+                    ((Roles) pageRef.getPage()).getFeedbackPanel().refresh(target);
+                }
+            }
+        }, ActionLink.ActionType.DELETE, xmlRolesReader.getEntitlement("Roles", "delete"));
+
+        final Form form = new Form("roleForm");
+        form.setModel(new CompoundPropertyModel(selectedNode));
+        form.setOutputMarkupId(true);
+
+        final RolePanel rolePanel = new RolePanel.Builder("rolePanel").form(form).roleTO(selectedNode).
+                roleModalPageMode(Mode.ADMIN).build();
+        rolePanel.setEnabled(false);
+        form.add(rolePanel);
+
+        final WebMarkupContainer userListContainer = new WebMarkupContainer("userListContainer");
+
+        userListContainer.setOutputMarkupId(true);
+        userListContainer.setEnabled(true);
+        userListContainer.add(new UserSearchResultPanel("userList", true, null, pageRef, userRestClient));
+        userListContainer.add(new ClearIndicatingAjaxButton("search", new ResourceModel("search"), pageRef) {
+
+            private static final long serialVersionUID = -958724007591692537L;
+
+            @Override
+            protected void onSubmitInternal(final AjaxRequestTarget target, final Form<?> form) {
+                userListContainer.replace(new UserSearchResultPanel("userList",
+                        true,
+                        SyncopeClient.getUserSearchConditionBuilder().hasRoles(selectedNode.getKey()).query(),
+                        pageRef,
+                        userRestClient));
+
+                target.add(userListContainer);
+            }
+        });
+
+        form.add(userListContainer);
+        add(form);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
new file mode 100644
index 0000000..bbc10b7
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
@@ -0,0 +1,286 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.SchedTaskModalPage;
+import org.apache.syncope.client.console.pages.Tasks;
+import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+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.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.wicket.Component;
+import org.apache.wicket.Page;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
+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.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.StringResourceModel;
+import org.apache.wicket.request.http.WebResponse;
+
+public class SchedTasks extends AbstractTasks {
+
+    private static final long serialVersionUID = 525486152284253354L;
+
+    private int paginatorRows;
+
+    private WebMarkupContainer container;
+
+    private ModalWindow window;
+
+    private AjaxDataTablePanel<AbstractTaskTO, String> table;
+
+    public SchedTasks(final String id, final PageReference pageRef) {
+        super(id, pageRef);
+
+        container = new WebMarkupContainer("container");
+        container.setOutputMarkupId(true);
+        add(container);
+
+        window = new ModalWindow("taskWin");
+        window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
+        window.setInitialHeight(WIN_HEIGHT);
+        window.setInitialWidth(WIN_WIDTH);
+        window.setCookieName(VIEW_TASK_WIN_COOKIE_NAME);
+        add(window);
+
+        ((Tasks) pageRef.getPage()).setWindowClosedCallback(window, container);
+
+        paginatorRows = prefMan.getPaginatorRows(getWebRequest(), Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS);
+
+        table = Tasks.updateTaskTable(
+                getColumns(),
+                new TasksProvider<SchedTaskTO>(restClient, paginatorRows, getId(), SchedTaskTO.class),
+                container,
+                0,
+                pageRef,
+                restClient);
+
+        container.add(table);
+
+        @SuppressWarnings("rawtypes")
+        Form paginatorForm = new Form("PaginatorForm");
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
+                prefMan.getPaginatorChoices());
+
+        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                prefMan.set(getWebRequest(), (WebResponse) getResponse(), Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS,
+                        String.valueOf(paginatorRows));
+
+                table = Tasks.updateTaskTable(
+                        getColumns(),
+                        new TasksProvider<SchedTaskTO>(restClient, paginatorRows, getId(), SchedTaskTO.class),
+                        container,
+                        table == null ? 0 : (int) table.getCurrentPage(),
+                        pageRef,
+                        restClient);
+
+                target.add(container);
+            }
+        });
+
+        paginatorForm.add(rowsChooser);
+        add(paginatorForm);
+
+        AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", pageRef) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                window.setPageCreator(new ModalWindow.PageCreator() {
+
+                    private static final long serialVersionUID = -7834632442532690940L;
+
+                    @Override
+                    public Page createPage() {
+                        return new SchedTaskModalPage(window, new SchedTaskTO(), pageRef);
+                    }
+                });
+
+                window.show(target);
+            }
+        };
+
+        MetaDataRoleAuthorizationStrategy.authorize(
+                createLink, RENDER, xmlRolesReader.getEntitlement(TASKS, "create"));
+
+        add(createLink);
+    }
+
+    private List<IColumn<AbstractTaskTO, String>> getColumns() {
+        final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<IColumn<AbstractTaskTO, String>>();
+
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("id", this, null), "id", "id"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("name", this, null), "name", "name"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("description", this, null), "description", "description"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("class", this, null), "jobClassName", "jobClassName"));
+        columns.add(new DatePropertyColumn<AbstractTaskTO>(
+                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
+        columns.add(new DatePropertyColumn<AbstractTaskTO>(
+                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
+        columns.add(new PropertyColumn<AbstractTaskTO, String>(
+                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+
+        columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
+
+            private static final long serialVersionUID = 2054811145491901166L;
+
+            @Override
+            public ActionLinksPanel getActions(final String componentId, final IModel<AbstractTaskTO> model) {
+
+                final SchedTaskTO taskTO = (SchedTaskTO) model.getObject();
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, pageRef);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        window.setPageCreator(new ModalWindow.PageCreator() {
+
+                            private static final long serialVersionUID = -7834632442532690940L;
+
+                            @Override
+                            public Page createPage() {
+                                return new SchedTaskModalPage(window, taskTO, pageRef);
+                            }
+                        });
+
+                        window.show(target);
+                    }
+                }, ActionLink.ActionType.EDIT, TASKS);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            restClient.startExecution(taskTO.getKey(), false);
+                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+
+                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                        target.add(container);
+                    }
+                }, ActionLink.ActionType.EXECUTE, TASKS);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            restClient.startExecution(taskTO.getKey(), true);
+                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+
+                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                        target.add(container);
+                    }
+                }, ActionLink.ActionType.DRYRUN, TASKS);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        try {
+                            restClient.delete(taskTO.getKey(), SchedTaskTO.class);
+                            info(getString(Constants.OPERATION_SUCCEEDED));
+                        } catch (SyncopeClientException scce) {
+                            error(scce.getMessage());
+                        }
+                        target.add(container);
+                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
+                    }
+                }, ActionLink.ActionType.DELETE, TASKS);
+
+                return panel;
+            }
+
+            @Override
+            public Component getHeader(final String componentId) {
+                @SuppressWarnings("rawtypes")
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        if (target != null) {
+                            target.add(table);
+                        }
+                    }
+                }, ActionLink.ActionType.RELOAD, TASKS, "list");
+
+                return panel;
+            }
+        });
+        return columns;
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) {
+            ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(container);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java
new file mode 100644
index 0000000..488a2cf
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchClause.java
@@ -0,0 +1,129 @@
+/*
+ * 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.panels;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+public class SearchClause implements Serializable {
+
+    private static final long serialVersionUID = 2010794463096110104L;
+
+    public enum Operator {
+
+        AND,
+        OR;
+
+    }
+
+    public enum Type {
+
+        ATTRIBUTE,
+        MEMBERSHIP,
+        RESOURCE,
+        ENTITLEMENT;
+
+    }
+
+    public enum Comparator {
+
+        IS_NULL,
+        IS_NOT_NULL,
+        EQUALS,
+        NOT_EQUALS,
+        GREATER_OR_EQUALS,
+        GREATER_THAN,
+        LESS_OR_EQUALS,
+        LESS_THAN;
+
+    }
+
+    private Operator operator;
+
+    private Type type;
+
+    private String property;
+
+    private Comparator comparator;
+
+    private String value;
+
+    public SearchClause() {
+        setOperator(SearchClause.Operator.AND);
+        setComparator(SearchClause.Comparator.EQUALS);
+    }
+
+    public Operator getOperator() {
+        return operator;
+    }
+
+    public void setOperator(final Operator operator) {
+        this.operator = operator;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(final Type type) {
+        this.type = type;
+    }
+
+    public String getProperty() {
+        return property;
+    }
+
+    public void setProperty(final String property) {
+        this.property = property;
+    }
+
+    public Comparator getComparator() {
+        return comparator;
+    }
+
+    public void setComparator(final Comparator comparator) {
+        this.comparator = comparator;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java
new file mode 100644
index 0000000..b432d82
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SearchView.java
@@ -0,0 +1,461 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.ajax.markup.html.AjaxLink;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.PropertyModel;
+
+public class SearchView extends ListView<SearchClause> {
+
+    private static final long serialVersionUID = -527351923968737757L;
+
+    private final WebMarkupContainer searchFormContainer;
+
+    private final boolean required;
+
+    private final IModel<List<SearchClause.Type>> types;
+
+    private final IModel<List<String>> anames;
+
+    private final IModel<List<String>> dnames;
+
+    private final IModel<List<String>> roleNames;
+
+    private final IModel<List<String>> resourceNames;
+
+    private final IModel<List<String>> entitlements;
+
+    public SearchView(final String id, final List<? extends SearchClause> list,
+            final WebMarkupContainer searchFormContainer,
+            final boolean required,
+            final IModel<List<SearchClause.Type>> types,
+            final IModel<List<String>> anames,
+            final IModel<List<String>> dnames,
+            final IModel<List<String>> roleNames,
+            final IModel<List<String>> resourceNames,
+            final IModel<List<String>> entitlements) {
+
+        super(id, list);
+
+        this.searchFormContainer = searchFormContainer;
+        this.required = required;
+        this.types = types;
+        this.anames = anames;
+        this.dnames = dnames;
+        this.roleNames = roleNames;
+        this.resourceNames = resourceNames;
+        this.entitlements = entitlements;
+    }
+
+    @Override
+    protected void populateItem(final ListItem<SearchClause> item) {
+        final SearchClause searchClause = item.getModelObject();
+
+        final DropDownChoice<SearchClause.Operator> operator = new DropDownChoice<SearchClause.Operator>("operator",
+                new PropertyModel<SearchClause.Operator>(searchClause, "operator"),
+                Arrays.asList(SearchClause.Operator.values()));
+        operator.setOutputMarkupPlaceholderTag(true);
+        operator.setNullValid(false);
+        operator.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+            }
+        });
+        item.add(operator);
+        if (item.getIndex() == 0) {
+            operator.setVisible(false);
+        }
+
+        final DropDownChoice<SearchClause.Type> type = new DropDownChoice<SearchClause.Type>("type",
+                new PropertyModel<SearchClause.Type>(searchClause, "type"), types);
+        type.setOutputMarkupId(true);
+        type.setRequired(required);
+        type.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                target.add(searchFormContainer);
+            }
+        });
+        item.add(type);
+
+        @SuppressWarnings("unchecked")
+        final DropDownChoice<String> property = new DropDownChoice<String>("property",
+                new PropertyModel<String>(searchClause, "property"), (IModel) null);
+        property.setOutputMarkupId(true);
+        property.setRequired(required);
+        property.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+            }
+        });
+        item.add(property);
+
+        final TextField<String> value = new TextField<String>("value",
+                new PropertyModel<String>(searchClause, "value"));
+        value.setOutputMarkupId(true);
+        value.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+            }
+        });
+        item.add(value);
+
+        final DropDownChoice<SearchClause.Comparator> comparator =
+                new DropDownChoice<SearchClause.Comparator>("comparator",
+                        new PropertyModel<SearchClause.Comparator>(searchClause, "comparator"),
+                        Collections.<SearchClause.Comparator>emptyList());
+        comparator.setOutputMarkupId(true);
+        comparator.setNullValid(false);
+        comparator.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                if (type.getModelObject() == SearchClause.Type.ATTRIBUTE) {
+                    if (comparator.getModelObject() == SearchClause.Comparator.IS_NULL
+                            || comparator.getModelObject() == SearchClause.Comparator.IS_NOT_NULL) {
+
+                        value.setModelObject(null);
+                        value.setEnabled(false);
+                    } else {
+                        value.setEnabled(true);
+                    }
+                    target.add(value);
+                }
+            }
+        });
+        comparator.setRequired(required);
+        item.add(comparator);
+
+        AjaxLink<Void> drop = new IndicatingAjaxLink<Void>("drop") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                SearchView.this.getModel().getObject().remove(item.getModelObject());
+                target.add(searchFormContainer);
+            }
+        };
+        item.add(drop);
+        if (item.getIndex() == 0) {
+            drop.setVisible(false);
+            drop.setEnabled(false);
+        } else {
+            drop.setVisible(true);
+            drop.setEnabled(true);
+        }
+
+        final AjaxLink<Void> add = new IndicatingAjaxLink<Void>("add") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                SearchClause clause = new SearchClause();
+                SearchView.this.getModel().getObject().add(clause);
+                target.add(searchFormContainer);
+            }
+        };
+        item.add(add);
+
+        if (searchClause == null || searchClause.getType() == null) {
+            property.setChoices(Collections.<String>emptyList());
+        } else {
+            switch (searchClause.getType()) {
+                case ATTRIBUTE:
+                    final List<String> names = new ArrayList<String>(dnames.getObject());
+                    if (anames.getObject() != null && !anames.getObject().isEmpty()) {
+                        names.addAll(anames.getObject());
+                    }
+                    Collections.sort(names);
+                    property.setChoices(names);
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            return Arrays.asList(SearchClause.Comparator.values());
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case IS_NULL:
+                                    display = "NULL";
+                                    break;
+
+                                case IS_NOT_NULL:
+                                    display = "NOT NULL";
+                                    break;
+
+                                case EQUALS:
+                                    display = "==";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "!=";
+                                    break;
+
+                                case LESS_THAN:
+                                    display = "<";
+                                    break;
+
+                                case LESS_OR_EQUALS:
+                                    display = "<=";
+                                    break;
+
+                                case GREATER_THAN:
+                                    display = ">";
+                                    break;
+
+                                case GREATER_OR_EQUALS:
+                                    display = ">=";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+                    if (!comparator.isEnabled()) {
+                        comparator.setEnabled(true);
+                        comparator.setRequired(true);
+                    }
+
+                    if (!value.isEnabled()) {
+                        value.setEnabled(true);
+                    }
+                    break;
+
+                case MEMBERSHIP:
+                    property.setChoices(roleNames);
+                    property.setChoiceRenderer(new IChoiceRenderer<String>() {
+
+                        private static final long serialVersionUID = -4288397951948436434L;
+
+                        @Override
+                        public Object getDisplayValue(final String object) {
+                            return object;
+                        }
+
+                        @Override
+                        public String getIdValue(final String object, final int index) {
+                            return object;
+                        }
+                    });
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            List<SearchClause.Comparator> comparators = new ArrayList<SearchClause.Comparator>();
+                            comparators.add(SearchClause.Comparator.EQUALS);
+                            comparators.add(SearchClause.Comparator.NOT_EQUALS);
+                            return comparators;
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case EQUALS:
+                                    display = "IN";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "NOT IN";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, final int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+
+                    value.setEnabled(false);
+                    value.setModelObject("");
+
+                    break;
+
+                case RESOURCE:
+                    property.setChoices(resourceNames);
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            List<SearchClause.Comparator> comparators = new ArrayList<SearchClause.Comparator>();
+                            comparators.add(SearchClause.Comparator.EQUALS);
+                            comparators.add(SearchClause.Comparator.NOT_EQUALS);
+                            return comparators;
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case EQUALS:
+                                    display = "HAS";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "HAS NOT";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, final int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+
+                    value.setEnabled(false);
+                    value.setModelObject("");
+
+                    break;
+
+                case ENTITLEMENT:
+                    property.setChoices(entitlements);
+
+                    comparator.setChoices(new LoadableDetachableModel<List<SearchClause.Comparator>>() {
+
+                        private static final long serialVersionUID = 5275935387613157437L;
+
+                        @Override
+                        protected List<SearchClause.Comparator> load() {
+                            List<SearchClause.Comparator> comparators = new ArrayList<SearchClause.Comparator>();
+                            comparators.add(SearchClause.Comparator.EQUALS);
+                            comparators.add(SearchClause.Comparator.NOT_EQUALS);
+                            return comparators;
+                        }
+                    });
+                    comparator.setChoiceRenderer(new IChoiceRenderer<SearchClause.Comparator>() {
+
+                        private static final long serialVersionUID = -9086043750227867686L;
+
+                        @Override
+                        public Object getDisplayValue(final SearchClause.Comparator object) {
+                            String display;
+
+                            switch (object) {
+                                case EQUALS:
+                                    display = "HAS";
+                                    break;
+
+                                case NOT_EQUALS:
+                                    display = "HAS NOT";
+                                    break;
+
+                                default:
+                                    display = StringUtils.EMPTY;
+                            }
+
+                            return display;
+                        }
+
+                        @Override
+                        public String getIdValue(final SearchClause.Comparator object, final int index) {
+                            return getDisplayValue(object).toString();
+                        }
+                    });
+
+                    value.setEnabled(false);
+                    value.setModelObject("");
+
+                    break;
+
+                default:
+                    property.setChoices(Collections.<String>emptyList());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java
new file mode 100644
index 0000000..8658cf6
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionPanel.java
@@ -0,0 +1,98 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.TreeMap;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.SecurityQuestionRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.to.SecurityQuestionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+public class SecurityQuestionPanel extends Panel {
+
+    private static final long serialVersionUID = -790642213865180146L;
+
+    private final Map<Long, String> questions = new TreeMap<Long, String>();
+
+    @SpringBean
+    private SecurityQuestionRestClient restClient;
+
+    public SecurityQuestionPanel(final String id, final UserTO userTO) {
+        super(id);
+        setOutputMarkupId(true);
+
+        for (SecurityQuestionTO secQues : restClient.list()) {
+            questions.put(secQues.getKey(), secQues.getContent());
+        }
+
+        final AjaxTextFieldPanel securityAnswer = new AjaxTextFieldPanel("securityAnswer", "securityAnswer",
+                new PropertyModel<String>(userTO, "securityAnswer"));
+        securityAnswer.getField().setOutputMarkupId(true);
+        securityAnswer.setEnabled(false);
+        add(securityAnswer);
+
+        final AjaxDropDownChoicePanel<Long> securityQuestion =
+                new AjaxDropDownChoicePanel<>("securityQuestion", "securityQuestion",
+                        new PropertyModel<Long>(userTO, "securityQuestion"));
+        ((DropDownChoice) securityQuestion.getField()).setNullValid(true);
+        securityQuestion.setChoices(new ArrayList<>(questions.keySet()));
+        securityQuestion.setStyleSheet("ui-widget-content ui-corner-all long_dynamicsize");
+        securityQuestion.getField().setOutputMarkupId(true);
+        securityQuestion.setChoiceRenderer(new IChoiceRenderer<Long>() {
+
+            private static final long serialVersionUID = 2693996850376268294L;
+
+            @Override
+            public Object getDisplayValue(final Long object) {
+                return questions.get(object);
+            }
+
+            @Override
+            public String getIdValue(final Long object, final int index) {
+                return questions.get(object);
+            }
+        });
+        securityQuestion.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                if (securityQuestion.getModelObject() == null) {
+                    securityAnswer.setModelObject(null);
+                } else {
+                    securityAnswer.setEnabled(true);
+                }
+                target.add(SecurityQuestionPanel.this);
+            }
+        });
+        add(securityQuestion);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java
new file mode 100644
index 0000000..a55db53
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectOnlyUserSearchResultPanel.java
@@ -0,0 +1,93 @@
+/*
+ * 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.panels;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.syncope.client.console.pages.DisplayAttributesModalPage;
+import org.apache.syncope.client.console.rest.UserRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+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.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.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+
+public class SelectOnlyUserSearchResultPanel extends UserSearchResultPanel {
+
+    private static final long serialVersionUID = 2146781496050131930L;
+
+    private final PageReference pageRef;
+
+    private final ModalWindow window;
+
+    public <T extends AbstractAttributableTO> SelectOnlyUserSearchResultPanel(final String id, final boolean filtered,
+            final String fiql, final PageReference pageRef, final ModalWindow window, final UserRestClient restClient) {
+
+        super(id, filtered, fiql, pageRef, restClient);
+
+        this.pageRef = pageRef;
+        this.window = window;
+    }
+
+    @Override
+    protected List<IColumn<AbstractAttributableTO, String>> getColumns() {
+        final List<IColumn<AbstractAttributableTO, String>> columns =
+                new ArrayList<IColumn<AbstractAttributableTO, String>>();
+        for (String name : DisplayAttributesModalPage.DEFAULT_SELECTION) {
+            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 = 8263694778917279290L;
+
+            @Override
+            public void populateItem(final Item<ICellPopulator<AbstractAttributableTO>> cellItem,
+                    final String componentId, final IModel<AbstractAttributableTO> rowModel) {
+
+                final ActionLinksPanel panel = new ActionLinksPanel(componentId, rowModel, pageRef);
+
+                panel.add(new ActionLink() {
+
+                    private static final long serialVersionUID = -3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        send(pageRef.getPage(), Broadcast.BREADTH,
+                                new RoleDetailsPanel.UserOwnerSelectPayload(rowModel.getObject().getKey()));
+                        window.close(target);
+                    }
+                }, ActionLink.ActionType.SELECT, "Users");
+
+                cellItem.add(panel);
+            }
+        });
+
+        return columns;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/32707b3b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java
----------------------------------------------------------------------
diff --git a/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java
new file mode 100644
index 0000000..96c8d77
--- /dev/null
+++ b/syncope620/client/console/src/main/java/org/apache/syncope/client/console/panels/SelectedEventsPanel.java
@@ -0,0 +1,167 @@
+/*
+ * 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.panels;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.form.ListMultipleChoice;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.util.ListModel;
+
+public class SelectedEventsPanel extends Panel {
+
+    private static final long serialVersionUID = -4832450230348213500L;
+
+    private final WebMarkupContainer selectionContainer;
+
+    private ListMultipleChoice<String> selectedEvents;
+
+    private final IModel<List<String>> model;
+
+    public SelectedEventsPanel(final String id, final IModel<List<String>> model) {
+        super(id);
+
+        this.model = model;
+
+        selectionContainer = new WebMarkupContainer("selectionContainer");
+        selectionContainer.setOutputMarkupId(true);
+        add(selectionContainer);
+
+        selectedEvents = new ListMultipleChoice<String>("selectedEvents", new ListModel<String>(), model) {
+
+            private static final long serialVersionUID = 1226677544225737338L;
+
+            @Override
+            protected void onComponentTag(final ComponentTag tag) {
+                super.onComponentTag(tag);
+                tag.remove("size");
+                tag.remove("multiple");
+                tag.put("size", 5);
+            }
+        };
+
+        selectedEvents.setMaxRows(5);
+        selectedEvents.setChoiceRenderer(new IChoiceRenderer<String>() {
+
+            private static final long serialVersionUID = -4288397951948436434L;
+
+            @Override
+            public Object getDisplayValue(final String object) {
+                return object;
+            }
+
+            @Override
+            public String getIdValue(final String object, final int index) {
+                return object;
+            }
+        });
+
+        selectedEvents.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -151291731388673682L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                send(SelectedEventsPanel.this.getPage(),
+                        Broadcast.BREADTH,
+                        new InspectSelectedEvent(target, selectedEvents.getModelValue()));
+            }
+        });
+
+        selectionContainer.add(selectedEvents);
+    }
+
+    @Override
+    public void onEvent(final IEvent<?> event) {
+        if (event.getPayload() instanceof EventSelectionChanged) {
+            final EventSelectionChanged eventSelectionChanged = (EventSelectionChanged) event.getPayload();
+
+            for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
+                model.getObject().remove(toBeRemoved);
+            }
+
+            for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
+                if (!model.getObject().contains(toBeAdded)) {
+                    model.getObject().add(toBeAdded);
+                }
+            }
+
+            eventSelectionChanged.getTarget().add(selectionContainer);
+        }
+    }
+
+    public static class InspectSelectedEvent {
+
+        private final AjaxRequestTarget target;
+
+        private final String event;
+
+        public InspectSelectedEvent(final AjaxRequestTarget target, final String event) {
+            this.target = target;
+            this.event = event;
+        }
+
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+
+        public String getEvent() {
+            return event;
+        }
+    }
+
+    public static class EventSelectionChanged {
+
+        private final AjaxRequestTarget target;
+
+        private final Set<String> toBeRemoved;
+
+        private final Set<String> toBeAdded;
+
+        public EventSelectionChanged(
+                final AjaxRequestTarget target,
+                final Set<String> toBeAdded,
+                final Set<String> toBeRemoved) {
+            this.target = target;
+            this.toBeAdded = toBeAdded;
+            this.toBeRemoved = toBeRemoved;
+        }
+
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+
+        public Set<String> getToBeRemoved() {
+            return toBeRemoved;
+        }
+
+        public Set<String> getToBeAdded() {
+            return toBeAdded;
+        }
+    }
+}