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/16 09:06:55 UTC

[30/59] [abbrv] [partial] syncope git commit: [SYNCOPE-620] Re-organization completed

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/head/MetaHeaderItem.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/head/MetaHeaderItem.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/head/MetaHeaderItem.java
new file mode 100644
index 0000000..2c5150e
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/head/MetaHeaderItem.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.wicket.markup.head;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import org.apache.wicket.markup.head.HeaderItem;
+import org.apache.wicket.request.Response;
+
+public class MetaHeaderItem extends HeaderItem implements Serializable {
+
+    private static final long serialVersionUID = 7578609827530302053L;
+
+    private final String key;
+
+    private final String value;
+
+    public MetaHeaderItem(final String key, final String value) {
+        this.key = key;
+        this.value = value;
+    }
+
+    @Override
+    public Iterable<?> getRenderTokens() {
+        return Arrays.asList("meta-" + key + "-" + value);
+    }
+
+    @Override
+    public void render(final Response response) {
+        response.write("<meta http-equiv=\"" + key + "\" content=\"" + value + "\"/>");
+        response.write("\n");
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/CrontabContainer.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/CrontabContainer.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/CrontabContainer.java
new file mode 100644
index 0000000..5555616
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/CrontabContainer.java
@@ -0,0 +1,184 @@
+/*
+ * 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.wicket.markup.html;
+
+import java.util.Arrays;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.SelectChoiceRenderer;
+import org.apache.syncope.client.console.commons.SelectOption;
+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.DropDownChoice;
+import org.apache.wicket.markup.html.form.FormComponent;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+
+public class CrontabContainer extends WebMarkupContainer {
+
+    private static final long serialVersionUID = 7879593326085337650L;
+
+    private final TextField seconds;
+
+    private final TextField minutes;
+
+    private final TextField hours;
+
+    private final TextField daysOfMonth;
+
+    private final TextField months;
+
+    private final TextField daysOfWeek;
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public CrontabContainer(final String id, final PropertyModel<String> cronExpressionModel,
+            final String cronExpression) {
+
+        super(id);
+        setOutputMarkupId(true);
+
+        final SelectOption[] CRON_TEMPLATES = {
+            new SelectOption(getString("selOpt1"), "UNSCHEDULE"),
+            new SelectOption(getString("selOpt2"), "0 0/5 * * * ?"),
+            new SelectOption(getString("selOpt3"), "0 0 12 * * ?"),
+            new SelectOption(getString("selOpt4"), "0 0 0 1 * ?"),
+            new SelectOption(getString("selOpt5"), "0 0 0 L * ?"),
+            new SelectOption(getString("selOpt6"), "0 0 0 ? * 2")
+        };
+
+        final DropDownChoice<SelectOption> cronTemplateChooser =
+                new DropDownChoice<SelectOption>("cronTemplateChooser") {
+
+                    private static final long serialVersionUID = -5843424545478691442L;
+
+                    @Override
+                    protected CharSequence getDefaultChoice(final String selected) {
+                        return "<option value=\"\">" + getString("chooseForTemplate") + "</option>";
+                    }
+                };
+
+        cronTemplateChooser.setModel(new IModel<SelectOption>() {
+
+            private static final long serialVersionUID = 6762568283146531315L;
+
+            @Override
+            public SelectOption getObject() {
+                SelectOption result = null;
+                for (SelectOption so : CRON_TEMPLATES) {
+                    if (so.getKeyValue().equals(cronExpressionModel.getObject())) {
+
+                        result = so;
+                    }
+                }
+
+                return result;
+            }
+
+            @Override
+            public void setObject(final SelectOption object) {
+                cronExpressionModel.setObject(object == null || object.equals(CRON_TEMPLATES[0])
+                        ? null
+                        : object.toString());
+            }
+
+            @Override
+            public void detach() {
+                // no detach
+            }
+        });
+        cronTemplateChooser.setChoices(Arrays.asList(CRON_TEMPLATES));
+        cronTemplateChooser.setChoiceRenderer(new SelectChoiceRenderer());
+        add(cronTemplateChooser);
+
+        seconds = new TextField("seconds", new Model(getCronField(cronExpression, 0)));
+        add(seconds);
+
+        minutes = new TextField("minutes", new Model(getCronField(cronExpression, 1)));
+        add(minutes);
+
+        hours = new TextField("hours", new Model(getCronField(cronExpression, 2)));
+        add(hours);
+
+        daysOfMonth = new TextField("daysOfMonth", new Model(getCronField(cronExpression, 3)));
+        add(daysOfMonth);
+
+        months = new TextField("months", new Model(getCronField(cronExpression, 4)));
+        add(months);
+
+        daysOfWeek = new TextField("daysOfWeek", new Model(getCronField(cronExpression, 5)));
+        add(daysOfWeek);
+
+        cronTemplateChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onUpdate(final AjaxRequestTarget target) {
+                seconds.setModelObject(getCronField(cronTemplateChooser, 0));
+                minutes.setModelObject(getCronField(cronTemplateChooser, 1));
+                hours.setModelObject(getCronField(cronTemplateChooser, 2));
+                daysOfMonth.setModelObject(getCronField(cronTemplateChooser, 3));
+                months.setModelObject(getCronField(cronTemplateChooser, 4));
+                daysOfWeek.setModelObject(getCronField(cronTemplateChooser, 5));
+                target.add(CrontabContainer.this);
+            }
+        });
+    }
+
+    private String getCronField(final FormComponent formComponent, final int field) {
+        String cronField = null;
+
+        if (formComponent != null) {
+            cronField = getCronField(formComponent.getInput(), field);
+        }
+
+        return cronField;
+    }
+
+    private String getCronField(final String cron, final int field) {
+        String cronField = null;
+
+        if (cron != null && !cron.isEmpty() && !"UNSCHEDULE".equals(cron)) {
+            cronField = cron.split(" ")[field].trim();
+        }
+
+        return cronField;
+    }
+
+    public String getCronExpression() {
+        String cronExpression = null;
+
+        if (seconds != null && seconds.getInput() != null && minutes != null && minutes.getInput() != null
+                && hours != null && hours.getInput() != null && daysOfMonth != null && daysOfMonth.getInput() != null
+                && months != null && months.getInput() != null && daysOfWeek != null && daysOfWeek.getInput() != null) {
+
+            cronExpression = new StringBuilder().
+                    append(seconds.getInput().trim()).append(" ").
+                    append(minutes.getInput().trim()).append(" ").
+                    append(hours.getInput().trim()).append(" ").
+                    append(daysOfMonth.getInput().trim()).append(" ").
+                    append(months.getInput().trim()).append(" ").
+                    append(daysOfWeek.getInput().trim()).toString();
+        }
+
+        return cronExpression;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AbstractFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AbstractFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AbstractFieldPanel.java
new file mode 100644
index 0000000..30bb47c
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AbstractFieldPanel.java
@@ -0,0 +1,40 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractFieldPanel<T> extends Panel {
+
+    /**
+     * Logger.
+     */
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractFieldPanel.class);
+
+    private static final long serialVersionUID = 5958017546318855690L;
+
+    public AbstractFieldPanel(final String id, final IModel<T> model) {
+        super(id, model);
+    }
+
+    public abstract AbstractFieldPanel setModelObject(T object);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
new file mode 100644
index 0000000..159e5d9
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
@@ -0,0 +1,83 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.io.Serializable;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+
+public abstract class ActionLink implements Serializable {
+
+    private static final long serialVersionUID = 7031329706998320639L;
+
+    private boolean reloadFeedbackPanel = true;
+
+    public enum ActionType {
+
+        CREATE("create"),
+        EDIT("read"),
+        USER_TEMPLATE("read"),
+        ROLE_TEMPLATE("read"),
+        RESET("update"),
+        ENABLE("update"),
+        SEARCH("read"),
+        DELETE("delete"),
+        EXECUTE("execute"),
+        DRYRUN("execute"),
+        CLAIM("claim"),
+        SELECT("read"),
+        EXPORT("read"),
+        SUSPEND("update"),
+        REACTIVATE("update"),
+        RELOAD("reload"),
+        CHANGE_VIEW("changeView"),
+        UNLINK("update"),
+        LINK("update"),
+        UNASSIGN("update"),
+        ASSIGN("update"),
+        DEPROVISION("update"),
+        PROVISION("update"),
+        MANAGE_RESOURCES("update"),
+        MANAGE_USERS("update"),
+        MANAGE_ROLES("update");
+
+        private final String actionId;
+
+        private ActionType(final String actionId) {
+            this.actionId = actionId;
+        }
+
+        public String getActionId() {
+            return actionId;
+        }
+    }
+
+    public abstract void onClick(final AjaxRequestTarget target);
+
+    public void postClick() {
+    }
+
+    public boolean feedbackPanelAutomaticReload() {
+        return reloadFeedbackPanel;
+    }
+
+    public ActionLink feedbackPanelAutomaticReload(final boolean reloadFeedbackPanel) {
+        this.reloadFeedbackPanel = reloadFeedbackPanel;
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
new file mode 100644
index 0000000..8582741
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
@@ -0,0 +1,586 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import org.apache.syncope.client.console.commons.XMLRolesReader;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.IndicatingOnConfirmAjaxLink;
+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.markup.html.panel.Fragment;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+
+/**
+ * This empty class must exist because there not seems to be alternative to provide specialized HTML for edit links.
+ */
+public class ActionLinksPanel extends Panel {
+
+    private static final long serialVersionUID = 322966537010107771L;
+
+    /**
+     * Role reader for authorizations management.
+     */
+    @SpringBean
+    protected XMLRolesReader xmlRolesReader;
+
+    private final PageReference pageRef;
+
+    public ActionLinksPanel(final String componentId, final IModel<?> model, final PageReference pageRef) {
+        super(componentId, model);
+        this.pageRef = pageRef;
+
+        super.add(new Fragment("panelClaim", "emptyFragment", this));
+        super.add(new Fragment("panelManageResources", "emptyFragment", this));
+        super.add(new Fragment("panelManageUsers", "emptyFragment", this));
+        super.add(new Fragment("panelManageRoles", "emptyFragment", this));
+        super.add(new Fragment("panelCreate", "emptyFragment", this));
+        super.add(new Fragment("panelEdit", "emptyFragment", this));
+        super.add(new Fragment("panelReset", "emptyFragment", this));
+        super.add(new Fragment("panelUserTemplate", "emptyFragment", this));
+        super.add(new Fragment("panelRoleTemplate", "emptyFragment", this));
+        super.add(new Fragment("panelEnable", "emptyFragment", this));
+        super.add(new Fragment("panelSearch", "emptyFragment", this));
+        super.add(new Fragment("panelDelete", "emptyFragment", this));
+        super.add(new Fragment("panelExecute", "emptyFragment", this));
+        super.add(new Fragment("panelDryRun", "emptyFragment", this));
+        super.add(new Fragment("panelSelect", "emptyFragment", this));
+        super.add(new Fragment("panelExport", "emptyFragment", this));
+        super.add(new Fragment("panelSuspend", "emptyFragment", this));
+        super.add(new Fragment("panelReactivate", "emptyFragment", this));
+        super.add(new Fragment("panelReload", "emptyFragment", this));
+        super.add(new Fragment("panelChangeView", "emptyFragment", this));
+        super.add(new Fragment("panelUnlink", "emptyFragment", this));
+        super.add(new Fragment("panelLink", "emptyFragment", this));
+        super.add(new Fragment("panelUnassign", "emptyFragment", this));
+        super.add(new Fragment("panelAssign", "emptyFragment", this));
+        super.add(new Fragment("panelDeprovision", "emptyFragment", this));
+        super.add(new Fragment("panelProvision", "emptyFragment", this));
+    }
+
+    public void add(
+            final ActionLink link, final ActionLink.ActionType type, final String pageId, final String actionId) {
+
+        addWithRoles(link, type, xmlRolesReader.getEntitlement(pageId, actionId), true);
+    }
+
+    public void add(
+            final ActionLink link, final ActionLink.ActionType type, final String pageId) {
+
+        add(link, type, pageId, true);
+    }
+
+    public void add(
+            final ActionLink link, final ActionLink.ActionType type, final String pageId, final boolean enabled) {
+
+        addWithRoles(link, type, xmlRolesReader.getEntitlement(pageId, type.getActionId()), enabled);
+    }
+
+    public void addWithRoles(
+            final ActionLink link, final ActionLink.ActionType type, final String roles) {
+
+        addWithRoles(link, type, roles, true);
+    }
+
+    public void addWithRoles(
+            final ActionLink link, final ActionLink.ActionType type, final String roles, final boolean enabled) {
+
+        Fragment fragment = null;
+
+        switch (type) {
+
+            case CLAIM:
+                fragment = new Fragment("panelClaim", "fragmentClaim", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("claimLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case MANAGE_RESOURCES:
+                fragment = new Fragment("panelManageResources", "fragmentManageResources", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("manageResourcesLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610291L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case MANAGE_USERS:
+                fragment = new Fragment("panelManageUsers", "fragmentManageUsers", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("manageUsersLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610292L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case MANAGE_ROLES:
+                fragment = new Fragment("panelManageRoles", "fragmentManageRoles", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("manageRolesLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610293L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case CREATE:
+                fragment = new Fragment("panelCreate", "fragmentCreate", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("createLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case RESET:
+                fragment = new Fragment("panelReset", "fragmentReset", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("resetLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610290L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                });
+                break;
+
+            case EDIT:
+                fragment = new Fragment("panelEdit", "fragmentEdit", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("editLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case USER_TEMPLATE:
+                fragment = new Fragment("panelUserTemplate", "fragmentUserTemplate", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("userTemplateLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case ROLE_TEMPLATE:
+                fragment = new Fragment("panelRoleTemplate", "fragmentRoleTemplate", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("roleTemplateLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case ENABLE:
+                fragment = new Fragment("panelEnable", "fragmentEnable", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("enableLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case SEARCH:
+                fragment = new Fragment("panelSearch", "fragmentSearch", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("searchLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case EXECUTE:
+                fragment = new Fragment("panelExecute", "fragmentExecute", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("executeLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case DRYRUN:
+                fragment = new Fragment("panelDryRun", "fragmentDryRun", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("dryRunLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case DELETE:
+                fragment = new Fragment("panelDelete", "fragmentDelete", this);
+
+                fragment.addOrReplace(new IndicatingOnConfirmAjaxLink<Void>("deleteLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+
+                break;
+
+            case SELECT:
+                fragment = new Fragment("panelSelect", "fragmentSelect", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("selectLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+
+                break;
+
+            case EXPORT:
+                fragment = new Fragment("panelExport", "fragmentExport", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("exportLink", pageRef) {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case SUSPEND:
+                fragment = new Fragment("panelSuspend", "fragmentSuspend", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("suspendLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610291L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case REACTIVATE:
+                fragment = new Fragment("panelReactivate", "fragmentReactivate", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("reactivateLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610292L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case RELOAD:
+                fragment = new Fragment("panelReload", "fragmentReload", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("reloadLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610293L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case CHANGE_VIEW:
+                fragment = new Fragment("panelChangeView", "fragmentChangeView", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("changeViewLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610292L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case UNLINK:
+                fragment = new Fragment("panelUnlink", "fragmentUnlink", this);
+
+                fragment.addOrReplace(
+                        new IndicatingOnConfirmAjaxLink<Void>("unlinkLink", pageRef, "confirmUnlink") {
+
+                            private static final long serialVersionUID = -6957616042924610293L;
+
+                            @Override
+                            protected void onClickInternal(final AjaxRequestTarget target) {
+                                link.onClick(target);
+                            }
+                        }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case LINK:
+                fragment = new Fragment("panelLink", "fragmentLink", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("linkLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610303L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case UNASSIGN:
+                fragment = new Fragment("panelUnassign", "fragmentUnassign", this);
+
+                fragment.addOrReplace(
+                        new IndicatingOnConfirmAjaxLink<Void>("unassignLink", pageRef, "confirmUnassign") {
+
+                            private static final long serialVersionUID = -6957616042924610294L;
+
+                            @Override
+                            protected void onClickInternal(final AjaxRequestTarget target) {
+                                link.onClick(target);
+                            }
+                        }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case ASSIGN:
+                fragment = new Fragment("panelAssign", "fragmentAssign", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("assignLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610304L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case DEPROVISION:
+                fragment = new Fragment("panelDeprovision", "fragmentDeprovision", this);
+
+                fragment.addOrReplace(
+                        new IndicatingOnConfirmAjaxLink<Void>("deprovisionLink", pageRef, "confirmDeprovision") {
+
+                            private static final long serialVersionUID = -6957616042924610295L;
+
+                            @Override
+                            protected void onClickInternal(final AjaxRequestTarget target) {
+                                link.onClick(target);
+                            }
+                        }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+
+            case PROVISION:
+                fragment = new Fragment("panelProvision", "fragmentProvision", this);
+
+                fragment.addOrReplace(new ClearIndicatingAjaxLink<Void>("provisionLink", pageRef) {
+
+                    private static final long serialVersionUID = -6957616042924610305L;
+
+                    @Override
+                    protected void onClickInternal(final AjaxRequestTarget target) {
+                        link.onClick(target);
+                    }
+                }.feedbackPanelAutomaticReload(link.feedbackPanelAutomaticReload()));
+                break;
+            default:
+            // do nothing
+        }
+
+        if (fragment != null) {
+            fragment.setEnabled(enabled);
+            MetaDataRoleAuthorizationStrategy.authorize(fragment, ENABLE, roles);
+            super.addOrReplace(fragment);
+        }
+    }
+
+    public void remove(final ActionLink.ActionType type) {
+        switch (type) {
+            case CLAIM:
+                super.addOrReplace(new Fragment("panelClaim", "emptyFragment", this));
+                break;
+
+            case MANAGE_RESOURCES:
+                super.addOrReplace(new Fragment("panelManageResources", "emptyFragment", this));
+                break;
+
+            case MANAGE_USERS:
+                super.addOrReplace(new Fragment("panelManageUsers", "emptyFragment", this));
+                break;
+
+            case MANAGE_ROLES:
+                super.addOrReplace(new Fragment("panelManageRoles", "emptyFragment", this));
+                break;
+
+            case CREATE:
+                super.addOrReplace(new Fragment("panelCreate", "emptyFragment", this));
+                break;
+
+            case EDIT:
+                super.addOrReplace(new Fragment("panelEdit", "emptyFragment", this));
+                break;
+
+            case USER_TEMPLATE:
+                super.addOrReplace(new Fragment("panelUserTemplate", "emptyFragment", this));
+                break;
+
+            case SEARCH:
+                super.addOrReplace(new Fragment("panelSearch", "emptyFragment", this));
+                break;
+
+            case EXECUTE:
+                super.addOrReplace(new Fragment("panelExecute", "emptyFragment", this));
+                break;
+
+            case DRYRUN:
+                super.addOrReplace(new Fragment("panelDryRun", "emptyFragment", this));
+                break;
+
+            case DELETE:
+                super.addOrReplace(new Fragment("panelDelete", "emptyFragment", this));
+                break;
+
+            case SELECT:
+                super.addOrReplace(new Fragment("panelSelect", "emptyFragment", this));
+                break;
+
+            case EXPORT:
+                super.addOrReplace(new Fragment("panelExport", "emptyFragment", this));
+                break;
+
+            case SUSPEND:
+                super.addOrReplace(new Fragment("panelSuspend", "emptyFragment", this));
+                break;
+
+            case REACTIVATE:
+                super.addOrReplace(new Fragment("panelReactivate", "emptyFragment", this));
+                break;
+
+            case RELOAD:
+                super.addOrReplace(new Fragment("panelReload", "emptyFragment", this));
+                break;
+
+            case CHANGE_VIEW:
+                super.addOrReplace(new Fragment("panelChangeView", "emptyFragment", this));
+                break;
+
+            case UNLINK:
+                super.addOrReplace(new Fragment("panelUnlink", "emptyFragment", this));
+                break;
+
+            case LINK:
+                super.addOrReplace(new Fragment("panelLink", "emptyFragment", this));
+                break;
+
+            case UNASSIGN:
+                super.addOrReplace(new Fragment("panelUnassign", "emptyFragment", this));
+                break;
+
+            case ASSIGN:
+                super.addOrReplace(new Fragment("panelAssign", "emptyFragment", this));
+                break;
+
+            case DEPROVISION:
+                super.addOrReplace(new Fragment("panelDeprovision", "emptyFragment", this));
+                break;
+
+            case PROVISION:
+                super.addOrReplace(new Fragment("panelProvision", "emptyFragment", this));
+                break;
+            default:
+            // do nothing
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.java
new file mode 100644
index 0000000..3702aa2
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxCheckBoxPanel.java
@@ -0,0 +1,130 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.io.Serializable;
+import java.util.List;
+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.markup.html.form.CheckBox;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+public class AjaxCheckBoxPanel extends FieldPanel<Boolean> {
+
+    private static final long serialVersionUID = 5664138233103884310L;
+
+    public AjaxCheckBoxPanel(final String id, final String name, final IModel<Boolean> model) {
+        super(id, model);
+
+        field = new CheckBox("checkboxField", model);
+        add(field.setLabel(new Model<String>(name)).setOutputMarkupId(true));
+
+        if (!isReadOnly()) {
+            field.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    // nothing to do
+                }
+            });
+        }
+    }
+
+    @Override
+    public FieldPanel<Boolean> addRequiredLabel() {
+        if (!isRequired()) {
+            setRequired(true);
+        }
+
+        this.isRequiredLabelAdded = true;
+
+        return this;
+    }
+
+    @Override
+    public FieldPanel<Boolean> setNewModel(final List<Serializable> list) {
+        setNewModel(new Model<Boolean>() {
+
+            private static final long serialVersionUID = 527651414610325237L;
+
+            @Override
+            public Boolean getObject() {
+                Boolean value = null;
+
+                if (list != null && !list.isEmpty()) {
+                    value = Boolean.TRUE.toString().equalsIgnoreCase(list.get(0).toString());
+                }
+
+                return value;
+            }
+
+            @Override
+            public void setObject(final Boolean object) {
+                list.clear();
+                if (object != null) {
+                    list.add(object.toString());
+                }
+            }
+        });
+
+        return this;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public FieldPanel<Boolean> setNewModel(final ListItem item) {
+        IModel<Boolean> model = new Model<Boolean>() {
+
+            private static final long serialVersionUID = 6799404673615637845L;
+
+            @Override
+            public Boolean getObject() {
+                Boolean bool = null;
+
+                final Object obj = item.getModelObject();
+
+                if (obj != null && !obj.toString().isEmpty()) {
+                    if (obj instanceof String) {
+                        bool = Boolean.TRUE.toString().equalsIgnoreCase(obj.toString());
+                    } else if (obj instanceof Boolean) {
+                        // Don't parse anything
+                        bool = (Boolean) obj;
+                    }
+                }
+
+                return bool;
+            }
+
+            @Override
+            @SuppressWarnings("unchecked")
+            public void setObject(final Boolean object) {
+                item.setModelObject(object == null ? Boolean.FALSE.toString() : object.toString());
+            }
+        };
+
+        field.setModel(model);
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDecoratedCheckbox.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDecoratedCheckbox.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDecoratedCheckbox.java
new file mode 100644
index 0000000..547d91a
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDecoratedCheckbox.java
@@ -0,0 +1,55 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.wicket.ajax.AjaxEventBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxCheckBox;
+import org.apache.wicket.model.IModel;
+
+/**
+ * AjaxCheckBox allowing AjaxCallDecorator.
+ */
+public abstract class AjaxDecoratedCheckbox extends AjaxCheckBox {
+
+    private static final long serialVersionUID = 7345848589265633002L;
+
+    public AjaxDecoratedCheckbox(final String id) {
+        this(id, null);
+    }
+
+    public AjaxDecoratedCheckbox(final String id, final IModel<Boolean> model) {
+        super(id, model);
+
+        add(new AjaxEventBehavior(Constants.ON_CLICK) {
+
+            private static final long serialVersionUID = -295188647830294610L;
+
+            @Override
+            protected void onEvent(final AjaxRequestTarget target) {
+                refreshComponent(target);
+            }
+        });
+    }
+
+    private void refreshComponent(final AjaxRequestTarget target) {
+        target.add(this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
new file mode 100644
index 0000000..19e0e1d
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxDropDownChoicePanel.java
@@ -0,0 +1,87 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+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.markup.html.form.ChoiceRenderer;
+import org.apache.wicket.markup.html.form.DropDownChoice;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+public class AjaxDropDownChoicePanel<T extends Serializable> extends FieldPanel<T> implements Cloneable {
+
+    private static final long serialVersionUID = -4716376580659196095L;
+
+    public AjaxDropDownChoicePanel(final String id, final String name, final IModel<T> model) {
+        this(id, name, model, true);
+    }
+
+    public AjaxDropDownChoicePanel(final String id, final String name, final IModel<T> model, boolean enableOnBlur) {
+        super(id, model);
+
+        field = new DropDownChoice<T>(
+                "dropDownChoiceField", model, Collections.<T>emptyList(), new ChoiceRenderer<T>());
+        add(field.setLabel(new Model<String>(name)).setOutputMarkupId(true));
+
+        if (enableOnBlur) {
+            field.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_BLUR) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    // nothing to do
+                }
+            });
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public AjaxDropDownChoicePanel<T> setChoiceRenderer(final IChoiceRenderer renderer) {
+        ((DropDownChoice) field).setChoiceRenderer(renderer);
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public AjaxDropDownChoicePanel<T> setChoices(final List<T> choices) {
+        ((DropDownChoice) field).setChoices(choices);
+        return this;
+    }
+
+    @SuppressWarnings("unchecked")
+    public AjaxDropDownChoicePanel<T> setChoices(final IModel<? extends List<? extends T>> choices) {
+        ((DropDownChoice) field).setChoices(choices);
+        return this;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public FieldPanel clone() {
+        final AjaxDropDownChoicePanel<T> panel = (AjaxDropDownChoicePanel<T>) super.clone();
+        panel.setChoiceRenderer(((DropDownChoice) field).getChoiceRenderer());
+        panel.setChoices(((DropDownChoice) field).getChoices());
+        return panel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPalettePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPalettePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPalettePanel.java
new file mode 100644
index 0000000..91b6306
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPalettePanel.java
@@ -0,0 +1,70 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.util.Collection;
+import java.util.List;
+import org.apache.syncope.client.console.commons.SelectChoiceRenderer;
+import org.apache.wicket.extensions.markup.html.form.palette.Palette;
+import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.util.ListModel;
+
+public class AjaxPalettePanel<T> extends AbstractFieldPanel<List<T>> {
+
+    private static final long serialVersionUID = 7738499668258805567L;
+
+    protected final Palette<T> palette;
+
+    public AjaxPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices) {
+        this(id, model, choices, false);
+    }
+
+    public AjaxPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices,
+            final boolean allowOrder) {
+
+        this(id, model, choices, new SelectChoiceRenderer<T>(), allowOrder, false);
+    }
+
+    public AjaxPalettePanel(final String id, final IModel<List<T>> model, final ListModel<T> choices,
+            final IChoiceRenderer<T> renderer, final boolean allowOrder, final boolean allowMoveAll) {
+
+        super(id, model);
+
+        this.palette = createPalette(model, choices, renderer, allowOrder, allowMoveAll);
+        add(palette.setOutputMarkupId(true));
+        setOutputMarkupId(true);
+    }
+
+    protected Palette<T> createPalette(final IModel<List<T>> model, final ListModel<T> choices,
+            final IChoiceRenderer<T> renderer, final boolean allowOrder, final boolean allowMoveAll) {
+
+        return new NonI18nPalette<T>("paletteField", model, choices, renderer, 8, allowOrder, allowMoveAll);
+    }
+
+    @Override
+    public AjaxPalettePanel<T> setModelObject(final List<T> object) {
+        palette.setDefaultModelObject(object);
+        return this;
+    }
+
+    public Collection<T> getModelCollection() {
+        return palette.getModelCollection();
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPasswordFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPasswordFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPasswordFieldPanel.java
new file mode 100644
index 0000000..14fdf9e
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxPasswordFieldPanel.java
@@ -0,0 +1,60 @@
+/*
+ * 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.wicket.markup.html.form;
+
+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.markup.html.form.PasswordTextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+public class AjaxPasswordFieldPanel extends FieldPanel<String> {
+
+    private static final long serialVersionUID = -5490115280336667460L;
+
+    public AjaxPasswordFieldPanel(final String id, final String name, final IModel<String> model) {
+        super(id, model);
+
+        field = new PasswordTextField("passwordField", model);
+        add(field.setLabel(new Model<String>(name)).setRequired(false).setOutputMarkupId(true));
+
+        if (!isReadOnly()) {
+            field.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget art) {
+                    // nothing to do
+                }
+            });
+        }
+    }
+
+    @Override
+    public FieldPanel<String> addRequiredLabel() {
+        if (!isRequired()) {
+            setRequired(true);
+        }
+
+        this.isRequiredLabelAdded = true;
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxTextFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxTextFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxTextFieldPanel.java
new file mode 100644
index 0000000..6854fb0
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/AjaxTextFieldPanel.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.wicket.markup.html.form;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+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.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
+import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.validation.IValidator;
+
+public class AjaxTextFieldPanel extends FieldPanel<String> implements Cloneable {
+
+    private static final long serialVersionUID = 238940918106696068L;
+
+    private List<String> choices = Collections.emptyList();
+
+    public AjaxTextFieldPanel(final String id, final String name, final IModel<String> model) {
+        super(id, model);
+
+        final AutoCompleteSettings settings = new AutoCompleteSettings();
+        settings.setShowCompleteListOnFocusGain(true);
+        settings.setShowListOnEmptyInput(true);
+
+        field = new AutoCompleteTextField<String>("textField", model, settings) {
+
+            private static final long serialVersionUID = -6648767303091874219L;
+
+            @Override
+            protected Iterator<String> getChoices(final String input) {
+                final Pattern pattern = Pattern.compile(".*" + Pattern.quote(input) + ".*", Pattern.CASE_INSENSITIVE);
+
+                final List<String> result = new ArrayList<String>();
+
+                for (String choice : choices) {
+                    if (pattern.matcher(choice).matches()) {
+                        result.add(choice);
+                    }
+                }
+
+                return result.iterator();
+            }
+        };
+        add(field.setLabel(new Model<String>(name)).setOutputMarkupId(true));
+
+        if (!isReadOnly()) {
+            field.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    // nothing to do
+                }
+            });
+        }
+    }
+
+    public void addValidator(final IValidator<? super String> validator) {
+        this.field.add(validator);
+    }
+
+    public void setChoices(final List<String> choices) {
+        if (choices != null) {
+            this.choices = choices;
+        }
+    }
+
+    @Override
+    public FieldPanel<String> clone() {
+        final AjaxTextFieldPanel panel = (AjaxTextFieldPanel) super.clone();
+        panel.setChoices(choices);
+        return panel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
new file mode 100644
index 0000000..949cc83
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/BinaryFieldPanel.java
@@ -0,0 +1,211 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.io.ByteArrayInputStream;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.PreviewUtil;
+import org.apache.syncope.client.console.commons.HttpResourceStream;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.BaseModalPage;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.wicket.Component;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.form.AjaxFormSubmitBehavior;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxLink;
+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.form.StatelessForm;
+import org.apache.wicket.markup.html.form.TextField;
+import org.apache.wicket.markup.html.form.upload.FileUpload;
+import org.apache.wicket.markup.html.form.upload.FileUploadField;
+import org.apache.wicket.markup.html.link.Link;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.request.handler.resource.ResourceStreamRequestHandler;
+import org.apache.wicket.request.resource.ContentDisposition;
+import org.apache.wicket.spring.injection.annot.SpringBean;
+import org.apache.wicket.util.crypt.Base64;
+import org.apache.wicket.util.lang.Bytes;
+
+public class BinaryFieldPanel extends FieldPanel<String> {
+
+    private static final long serialVersionUID = 6264462604183088931L;
+
+    private final String mimeType;
+
+    private final WebMarkupContainer container;
+
+    private final Link<Void> downloadLink;
+
+    private final Form<?> uploadForm;
+
+    private final Fragment emptyFragment;
+
+    @SpringBean
+    private PreviewUtil previewUtil;
+
+    public BinaryFieldPanel(final String id, final String name, final IModel<String> model, final String mimeType) {
+        super(id, model);
+        this.mimeType = mimeType;
+
+        uploadForm = new StatelessForm<Void>("uploadForm");
+        uploadForm.setMultiPart(true);
+        uploadForm.setMaxSize(Bytes.megabytes(4));
+        add(uploadForm);
+
+        container = new WebMarkupContainer("previewContainer");
+        container.setOutputMarkupId(true);
+
+        emptyFragment = new Fragment("panelPreview", "emptyFragment", container);
+        emptyFragment.setOutputMarkupId(true);
+        container.add(emptyFragment);
+        uploadForm.add(container);
+
+        field = new TextField<String>("textField", model);
+        add(field.setLabel(new Model<String>(name)).setOutputMarkupId(true));
+
+        uploadForm.add(new Label("preview", StringUtils.isBlank(mimeType) ? StringUtils.EMPTY : "(" + mimeType + ")"));
+
+        downloadLink = new Link<Void>("downloadLink") {
+
+            private static final long serialVersionUID = -4331619903296515985L;
+
+            @Override
+            public void onClick() {
+                try {
+                    HttpResourceStream stream = new HttpResourceStream(buildResponse());
+
+                    ResourceStreamRequestHandler rsrh = new ResourceStreamRequestHandler(stream);
+                    rsrh.setFileName(stream.getFilename() == null ? name : stream.getFilename());
+                    rsrh.setContentDisposition(ContentDisposition.ATTACHMENT);
+
+                    getRequestCycle().scheduleRequestHandlerAfterCurrent(rsrh);
+                } catch (Exception e) {
+                    error(getString(Constants.ERROR) + ": " + e.getMessage());
+                }
+            }
+        };
+        downloadLink.setOutputMarkupId(true);
+        uploadForm.add(downloadLink);
+
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final FileUploadField fileUpload = new FileUploadField("fileUpload", new Model());
+        fileUpload.setOutputMarkupId(true);
+        fileUpload.add(new AjaxFormSubmitBehavior(Constants.ON_CHANGE) {
+
+            private static final long serialVersionUID = -1107858522700306810L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target) {
+                final FileUpload uploadedFile = fileUpload.getFileUpload();
+                if (uploadedFile != null) {
+                    try {
+                        final byte[] uploadedBytes = uploadedFile.getBytes();
+                        final String uploaded = new String(
+                                Base64.encodeBase64(uploadedBytes),
+                                SyncopeConstants.DEFAULT_ENCODING);
+                        field.setModelObject(uploaded);
+                        target.add(field);
+
+                        final Component panelPreview = previewUtil.getPreviewer(mimeType, uploadedBytes);
+
+                        if (panelPreview != null) {
+                            changePreviewer(panelPreview);
+                        }
+
+                        fileUpload.setModelObject(null);
+                        uploadForm.addOrReplace(fileUpload);
+                        downloadLink.setEnabled(StringUtils.isNotBlank(uploaded));
+                        target.add(uploadForm);
+                    } catch (Exception e) {
+                        error(getString(Constants.ERROR) + ": " + e.getMessage());
+                        ((BaseModalPage) getPage()).getFeedbackPanel().refresh(target);
+                        LOG.error("While saving uploaded file", e);
+                    }
+                }
+            }
+        });
+
+        uploadForm.add(fileUpload);
+
+        IndicatingAjaxLink<Void> uploadLink = new IndicatingAjaxLink<Void>("uploadLink") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+            }
+        };
+        uploadForm.add(uploadLink);
+
+        IndicatingAjaxLink<Void> resetLink = new IndicatingAjaxLink<Void>("resetLink") {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            public void onClick(final AjaxRequestTarget target) {
+                field.setModelObject(null);
+                target.add(field);
+                downloadLink.setEnabled(false);
+                container.addOrReplace(emptyFragment);
+                uploadForm.addOrReplace(container);
+                target.add(uploadForm);
+            }
+        };
+        uploadForm.add(resetLink);
+    }
+
+    private Response buildResponse() {
+        return Response.ok(new ByteArrayInputStream(Base64.decodeBase64(getModelObject()))).
+                type(StringUtils.isBlank(mimeType) ? MediaType.APPLICATION_OCTET_STREAM : mimeType).build();
+    }
+
+    private void changePreviewer(final Component panelPreview) {
+        final Fragment fragment = new Fragment("panelPreview", "previewFragment", container);
+        fragment.add(panelPreview);
+        container.addOrReplace(fragment);
+        uploadForm.addOrReplace(container);
+    }
+
+    @Override
+    public BinaryFieldPanel clone() {
+        return (BinaryFieldPanel) super.clone();
+    }
+
+    @Override
+    public FieldPanel<String> setNewModel(final IModel<String> model) {
+        field.setModel(model);
+        try {
+            final Component panelPreview = previewUtil.getPreviewer(mimeType, model.getObject());
+            if (panelPreview != null) {
+                changePreviewer(panelPreview);
+            }
+        } catch (Exception e) {
+            LOG.error("While loading saved file", e);
+        }
+        downloadLink.setEnabled(StringUtils.isNotBlank(model.getObject()));
+        uploadForm.addOrReplace(downloadLink);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/CheckBoxMultipleChoiceFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/CheckBoxMultipleChoiceFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/CheckBoxMultipleChoiceFieldPanel.java
new file mode 100644
index 0000000..3c5119b
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/CheckBoxMultipleChoiceFieldPanel.java
@@ -0,0 +1,46 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.util.List;
+
+import org.apache.wicket.markup.html.form.CheckBoxMultipleChoice;
+import org.apache.wicket.model.IModel;
+
+public class CheckBoxMultipleChoiceFieldPanel<E> extends AbstractFieldPanel<List<E>> {
+
+    private static final long serialVersionUID = 4124935025837737298L;
+
+    private final CheckBoxMultipleChoice<E> field;
+
+    public CheckBoxMultipleChoiceFieldPanel(
+            final String id, final IModel<List<E>> model, final IModel<List<E>> choices) {
+
+        super(id, model);
+
+        field = new CheckBoxMultipleChoice<E>("checkBoxMultipleChoice", model, choices);
+        add(field);
+    }
+
+    @Override
+    public AbstractFieldPanel<List<E>> setModelObject(final List<E> object) {
+        field.setModelObject(object);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateFieldPanel.java
new file mode 100644
index 0000000..1f5aaf6
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateFieldPanel.java
@@ -0,0 +1,132 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.wicket.markup.html.list.ListItem;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.springframework.util.StringUtils;
+
+public class DateFieldPanel extends FieldPanel<Date> {
+
+    private static final long serialVersionUID = -428975732068281726L;
+
+    protected final String name;
+
+    protected final String datePattern;
+
+    protected DateFieldPanel(final String id, final String name, final IModel<Date> model, final String datePattern) {
+        super(id, model);
+        this.name = name;
+        this.datePattern = datePattern;
+    }
+
+    @Override
+    public FieldPanel<Date> setNewModel(final List<Serializable> list) {
+        final SimpleDateFormat formatter = datePattern == null
+                ? new SimpleDateFormat(SyncopeConstants.DEFAULT_DATE_PATTERN, Locale.getDefault())
+                : new SimpleDateFormat(datePattern, Locale.getDefault());
+
+        setNewModel(new Model<Date>() {
+
+            private static final long serialVersionUID = 527651414610325237L;
+
+            @Override
+            public Date getObject() {
+                Date date = null;
+
+                if (list != null && !list.isEmpty() && StringUtils.hasText(list.get(0).toString())) {
+                    try {
+                        // Parse string using datePattern
+                        date = formatter.parse(list.get(0).toString());
+                    } catch (ParseException e) {
+                        LOG.error("invalid parse exception", e);
+                    }
+                }
+
+                return date;
+            }
+
+            @Override
+            public void setObject(final Date object) {
+                list.clear();
+                if (object != null) {
+                    list.add(formatter.format(object));
+                }
+            }
+        });
+
+        return this;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public FieldPanel<Date> setNewModel(final ListItem item) {
+        final SimpleDateFormat formatter = datePattern == null
+                ? new SimpleDateFormat(SyncopeConstants.DEFAULT_DATE_PATTERN, Locale.getDefault())
+                : new SimpleDateFormat(datePattern, Locale.getDefault());
+
+        IModel<Date> model = new Model<Date>() {
+
+            private static final long serialVersionUID = 6799404673615637845L;
+
+            @Override
+            public Date getObject() {
+                Date date = null;
+
+                final Object obj = item.getModelObject();
+
+                if (obj != null && !obj.toString().isEmpty()) {
+                    if (obj instanceof String) {
+                        // Parse string using datePattern
+                        try {
+                            date = formatter.parse(obj.toString());
+                        } catch (ParseException e) {
+                            LOG.error("While parsing date", e);
+                        }
+                    } else if (obj instanceof Date) {
+                        // Don't parse anything
+                        date = (Date) obj;
+                    } else {
+                        // consider Long
+                        date = new Date((Long) obj);
+                    }
+                }
+
+                return date;
+            }
+
+            @Override
+            @SuppressWarnings("unchecked")
+            public void setObject(final Date object) {
+                item.setModelObject(object != null ? formatter.format(object) : null);
+            }
+        };
+
+        field.setModel(model);
+        return this;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2d194636/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateTextFieldPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateTextFieldPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateTextFieldPanel.java
new file mode 100644
index 0000000..add3de6
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/DateTextFieldPanel.java
@@ -0,0 +1,88 @@
+/*
+ * 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.wicket.markup.html.form;
+
+import java.util.Date;
+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.datetime.markup.html.form.DateTextField;
+import org.apache.wicket.extensions.yui.calendar.DatePicker;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+public class DateTextFieldPanel extends DateFieldPanel {
+
+    private static final long serialVersionUID = 1919852712185883648L;
+
+    public DateTextFieldPanel(final String id, final String name, final IModel<Date> model, final String datePattern) {
+        super(id, name, model, datePattern);
+
+        field = DateTextField.forDatePattern("field", model, datePattern);
+
+        if (!isReadOnly()) {
+            field.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                private static final long serialVersionUID = -1107858522700306810L;
+
+                @Override
+                protected void onUpdate(final AjaxRequestTarget target) {
+                    // nothing to do
+                }
+            });
+        }
+
+        field.add(getDatePicker());
+
+        add(field.setLabel(new Model<String>(name)).setOutputMarkupId(true));
+    }
+
+    /**
+     * Setup a DatePicker component.
+     */
+    private DatePicker getDatePicker() {
+        final DatePicker picker = new DatePicker() {
+
+            private static final long serialVersionUID = 4166072895162221956L;
+
+            @Override
+            protected boolean enableMonthYearSelection() {
+                return true;
+            }
+        };
+
+        picker.setShowOnFieldClick(true);
+
+        return picker;
+    }
+
+    @Override
+    public FieldPanel<Date> clone() {
+        final FieldPanel<Date> panel = new DateTextFieldPanel(getId(), name, new Model<Date>(), datePattern);
+        panel.setRequired(isRequired());
+        panel.setReadOnly(isReadOnly());
+        panel.setTitle(title);
+
+        if (isRequiredLabelAdded) {
+            panel.addRequiredLabel();
+        }
+
+        return panel;
+    }
+}