[SYNCOPE-1041] SAML 2.0 SP extension: console management

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

Branch: refs/heads/2_0_X
Commit: 9bbd1500bb160a83caa6d063675914f5923edeb1
Parents: 0ce5b4c
Author: Francesco Chicchiriccò <[email protected]>
Authored: Wed Mar 22 16:17:29 2017 +0100
Committer: Francesco Chicchiriccò <[email protected]>
Committed: Fri Mar 31 15:25:11 2017 +0200

----------------------------------------------------------------------
 .../commons/ConnIdSpecialAttributeName.java     |  34 --
 .../console/commons/ConnIdSpecialName.java      |  38 ++
 .../console/commons/status/StatusUtils.java     |   6 +-
 .../syncope/client/console/pages/BasePage.java  |   5 +-
 .../console/panels/ConnObjectListViewPanel.java |  14 +-
 .../syncope/client/console/panels/Realm.java    |   9 +-
 .../console/panels/RoleDirectoryPanel.java      |   2 +-
 .../policies/AccountPolicyDirectoryPanel.java   |   3 +-
 .../policies/PolicyModalPanelBuilder.java       |  21 +-
 .../markup/html/form/JsonEditorPanel.java       |  10 +-
 .../markup/html/form/MappingPurposePanel.java   |  32 +-
 .../wicket/markup/html/form/XMLEditorPanel.java |  74 +++
 .../console/wizards/AbstractMappingPanel.java   | 464 +++++++++++++++++++
 .../console/wizards/any/ConnObjectPanel.java    |   4 +-
 .../resources/ProvisionWizardBuilder.java       |  53 ++-
 .../wizards/resources/ResourceMappingPanel.java | 422 +----------------
 .../resources/ResourceProvisionPanel.java       |   4 +-
 .../wicket/markup/html/form/XMLEditorPanel.html |  54 +++
 .../console/wizards/AbstractMappingPanel.html   |  96 ++++
 .../wizards/AbstractMappingPanel.properties     |  24 +
 .../wizards/AbstractMappingPanel_it.properties  |  24 +
 .../AbstractMappingPanel_pt_BR.properties       |  24 +
 .../wizards/AbstractMappingPanel_ru.properties  |  24 +
 .../ProvisionWizardBuilder$Mapping.properties   |  20 -
 ...ProvisionWizardBuilder$Mapping_it.properties |  19 -
 ...visionWizardBuilder$Mapping_pt_BR.properties |  20 -
 .../wizards/resources/ResourceMappingPanel.html |  96 ----
 .../resources/ResourceProvisionPanel.properties |  13 -
 .../ResourceProvisionPanel_it.properties        |  13 -
 .../ResourceProvisionPanel_pt_BR.properties     |  13 -
 .../ResourceProvisionPanel_ru.properties        |  14 -
 ext/camel/client-console/pom.xml                |   4 +-
 .../console/rest/CamelRoutesRestClient.java     |   2 -
 ext/camel/common-lib/pom.xml                    |   4 +-
 ext/camel/logic/pom.xml                         |   4 +-
 ext/camel/persistence-api/pom.xml               |   4 +-
 ext/camel/persistence-jpa/pom.xml               |   4 +-
 ext/camel/pom.xml                               |   4 +-
 ext/camel/provisioning-api/pom.xml              |   4 +-
 ext/camel/provisioning-camel/pom.xml            |   4 +-
 ext/camel/rest-api/pom.xml                      |   4 +-
 ext/camel/rest-cxf/pom.xml                      |   4 +-
 ext/pom.xml                                     |   4 +-
 ext/saml2sp/agent/pom.xml                       |   4 +-
 ext/saml2sp/client-console/pom.xml              |   4 +-
 .../syncope/client/console/pages/SAML2SP.java   |  77 +++
 .../client/console/panels/ImportMetadata.java   | 112 +++++
 .../console/panels/SAML2IdPsDirectoryPanel.java | 258 +++++++++++
 .../client/console/panels/SAML2SPPanel.java     |  71 +++
 .../console/rest/SAML2IdPsRestClient.java       |  53 +++
 .../console/wizards/SAML2IdPMappingPanel.java   |  87 ++++
 .../console/wizards/SAML2IdPWizardBuilder.java  | 143 ++++++
 .../syncope/client/console/pages/SAML2SP.html   |  37 ++
 .../client/console/pages/SAML2SP.properties     |  18 +
 .../client/console/pages/SAML2SP_it.properties  |  18 +
 .../console/pages/SAML2SP_pt_BR.properties      |  18 +
 .../client/console/pages/SAML2SP_ru.properties  |  18 +
 .../client/console/panels/ImportMetadata.html   |  32 ++
 .../console/panels/SAML2IdPsDirectoryPanel.html |  23 +
 .../panels/SAML2IdPsDirectoryPanel.properties   |  21 +
 .../SAML2IdPsDirectoryPanel_it.properties       |  21 +
 .../SAML2IdPsDirectoryPanel_pt_BR.properties    |  21 +
 .../SAML2IdPsDirectoryPanel_ru.properties       |  21 +
 .../client/console/panels/SAML2SPPanel.html     |  27 ++
 .../wizards/SAML2IdPWizardBuilder$IdP.html      |  27 ++
 .../wizards/SAML2IdPWizardBuilder$Mapping.html  |  23 +
 ext/saml2sp/client-enduser/pom.xml              |  83 ++++
 ext/saml2sp/common-lib/pom.xml                  |   4 +-
 ext/saml2sp/logic/pom.xml                       |   4 +-
 ext/saml2sp/persistence-api/pom.xml             |   4 +-
 ext/saml2sp/persistence-jpa/pom.xml             |   4 +-
 ext/saml2sp/pom.xml                             |   5 +-
 ext/saml2sp/provisioning-api/pom.xml            |   4 +-
 ext/saml2sp/provisioning-java/pom.xml           |   4 +-
 ext/saml2sp/rest-api/pom.xml                    |   4 +-
 ext/saml2sp/rest-cxf/pom.xml                    |   4 +-
 ext/swagger-ui/pom.xml                          |   4 +-
 77 files changed, 2186 insertions(+), 767 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
deleted file mode 100644
index 3533172..0000000
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialAttributeName.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.client.console.commons;
-
-public final class ConnIdSpecialAttributeName {
-
-    public static final String ENABLE = "__ENABLE__";
-
-    public static final String NAME = "__NAME__";
-
-    public static final String UID = "__UID__";
-
-    public static final String PASSWORD = "__PASSWORD__";
-
-    private ConnIdSpecialAttributeName() {
-        // private constructor for static utility class
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialName.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialName.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialName.java
new file mode 100644
index 0000000..e93489b
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/ConnIdSpecialName.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.console.commons;
+
+public final class ConnIdSpecialName {
+
+    public static final String ENABLE = "__ENABLE__";
+
+    public static final String NAME = "__NAME__";
+
+    public static final String UID = "__UID__";
+
+    public static final String PASSWORD = "__PASSWORD__";
+
+    public static final String ACCOUNT = "__ACCOUNT__";
+
+    public static final String GROUP = "__GROUP__";
+
+    private ConnIdSpecialName() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
index a1d3fe2..baf5b9b 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/commons/status/StatusUtils.java
@@ -25,7 +25,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName;
+import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.LabelPanel;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
@@ -115,7 +115,7 @@ public class StatusUtils implements Serializable {
     private Boolean isEnabled(final ConnObjectTO objectTO) {
         final Map<String, AttrTO> attributeTOs = objectTO.getAttrMap();
 
-        final AttrTO status = 
attributeTOs.get(ConnIdSpecialAttributeName.ENABLE);
+        final AttrTO status = attributeTOs.get(ConnIdSpecialName.ENABLE);
 
         return status != null && status.getValues() != null && 
!status.getValues().isEmpty()
                 ? Boolean.valueOf(status.getValues().get(0))
@@ -127,7 +127,7 @@ public class StatusUtils implements Serializable {
                 ? Collections.<String, AttrTO>emptyMap()
                 : objectTO.getAttrMap();
 
-        final AttrTO name = attributeTOs.get(ConnIdSpecialAttributeName.NAME);
+        final AttrTO name = attributeTOs.get(ConnIdSpecialName.NAME);
 
         return name != null && name.getValues() != null && 
!name.getValues().isEmpty()
                 ? name.getValues().get(0)

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
index ac74c77..4b62c8b 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/pages/BasePage.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.pages;
 
 import java.io.Serializable;
 import java.util.List;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
@@ -347,7 +348,9 @@ public class BasePage extends WebPage implements 
IAjaxIndicatorAware {
 
                 BookmarkablePageLink<Page> link = new 
BookmarkablePageLink<>("extPage", item.getModelObject());
                 link.add(new Label("extPageLabel", ann.label()));
-                MetaDataRoleAuthorizationStrategy.authorize(link, 
WebPage.ENABLE, ann.listEntitlement());
+                if (StringUtils.isNotBlank(ann.listEntitlement())) {
+                    MetaDataRoleAuthorizationStrategy.authorize(link, 
WebPage.ENABLE, ann.listEntitlement());
+                }
                 containingLI.add(link);
 
                 Label extPageIcon = new Label("extPageIcon");

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
index 327c007..60daaf7 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
@@ -25,7 +25,7 @@ import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName;
+import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.panels.ListViewPanel.ListViewReload;
 import org.apache.syncope.client.console.rest.ResourceRestClient;
 import 
org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.CollectionPanel;
@@ -94,10 +94,9 @@ public abstract class ConnObjectListViewPanel extends Panel {
             }
         }, ActionLink.ActionType.VIEW, 
StandardEntitlement.RESOURCE_GET_CONNOBJECT).
                 setItems(listOfItems).
-                includes(
-                        ConnIdSpecialAttributeName.UID,
-                        ConnIdSpecialAttributeName.NAME,
-                        ConnIdSpecialAttributeName.ENABLE).
+                includes(ConnIdSpecialName.UID,
+                        ConnIdSpecialName.NAME,
+                        ConnIdSpecialName.ENABLE).
                 withChecks(ListViewPanel.CheckAvailability.NONE).
                 setReuseItem(false);
 
@@ -132,12 +131,11 @@ public abstract class ConnObjectListViewPanel extends 
Panel {
             final String anyType,
             final String cookie) {
 
-        final Pair<String, List<ConnObjectTO>> items = new 
ResourceRestClient().listConnObjects(
-                resource,
+        final Pair<String, List<ConnObjectTO>> items = new 
ResourceRestClient().listConnObjects(resource,
                 anyType,
                 SIZE,
                 cookie,
-                new SortParam<String>(ConnIdSpecialAttributeName.UID, true));
+                new SortParam<String>(ConnIdSpecialName.UID, true));
 
         nextPageCookie = items.getLeft();
         return items.getRight();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
index 7837f12..4422b51 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/Realm.java
@@ -32,7 +32,7 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.commons.lang3.tuple.Triple;
 import org.apache.syncope.client.console.SyncopeConsoleApplication;
 import org.apache.syncope.client.console.commons.AnyTypeComparator;
-import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName;
+import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.ITabComponent;
 import org.apache.syncope.client.console.commons.status.StatusUtils;
@@ -215,11 +215,10 @@ public abstract class Realm extends 
WizardMgtPanel<RealmTO> {
                     ConnObjectTO afterObj = bean.getAfterObj();
                     String remoteId = afterObj == null
                             || MapUtils.isEmpty(afterObj.getAttrMap())
-                            || 
!afterObj.getAttrMap().containsKey(ConnIdSpecialAttributeName.NAME)
-                            || CollectionUtils.isEmpty(
-                                    
afterObj.getAttrMap().get(ConnIdSpecialAttributeName.NAME).getValues())
+                            || 
!afterObj.getAttrMap().containsKey(ConnIdSpecialName.NAME)
+                            || 
CollectionUtils.isEmpty(afterObj.getAttrMap().get(ConnIdSpecialName.NAME).getValues())
                             ? StringUtils.EMPTY
-                            : 
afterObj.getAttrMap().get(ConnIdSpecialAttributeName.NAME).getValues().
+                            : 
afterObj.getAttrMap().get(ConnIdSpecialName.NAME).getValues().
                             iterator().next();
 
                     return new Label("field", remoteId);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index c7bd44b..403938e 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -142,7 +142,7 @@ public class RoleDirectoryPanel extends 
DirectoryPanel<RoleTO, RoleWrapper, Role
 
                         ModalPanel panel = new AnyPanel(BaseModal.CONTENT_ID, 
anyTypeTO, null, null, false, pageRef) {
 
-                            private static final long serialVersionUID = 1L;
+                            private static final long serialVersionUID = 
-7514498203393023415L;
 
                             @Override
                             protected Panel getDirectoryPanel(final String id) 
{

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java
index b5f7afa..9e7d7a0 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/policies/AccountPolicyDirectoryPanel.java
@@ -45,8 +45,7 @@ public class AccountPolicyDirectoryPanel extends 
PolicyDirectoryPanel<AccountPol
     public AccountPolicyDirectoryPanel(final String id, final PageReference 
pageRef) {
         super(id, PolicyType.ACCOUNT, pageRef);
 
-        this.addNewItemPanelBuilder(new PolicyModalPanelBuilder<>(
-                new AccountPolicyTO(), modal, pageRef), true);
+        this.addNewItemPanelBuilder(new PolicyModalPanelBuilder<>(new 
AccountPolicyTO(), modal, pageRef), true);
         MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, RENDER, 
StandardEntitlement.POLICY_CREATE);
 
         initResultTable();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
index 93c9f8d..05f123f 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
@@ -100,48 +100,47 @@ public class PolicyModalPanelBuilder<T extends 
AbstractPolicyTO> extends Abstrac
 
             this.policyTO = policyTO;
 
-            final List<Component> components = new ArrayList<>();
+            final List<Component> fields = new ArrayList<>();
 
-            FieldPanel<String> description = 
-                new AjaxTextFieldPanel("field", "description", 
-                                       new PropertyModel<String>(policyTO, 
"description"), false);
+            FieldPanel<String> description = new AjaxTextFieldPanel("field", 
"description",
+                    new PropertyModel<String>(policyTO, "description"), false);
             description.setRequired(true);
-            components.add(description);
+            fields.add(description);
 
             if (policyTO instanceof AccountPolicyTO) {
-                components.add(new 
AjaxSpinnerFieldPanel.Builder<Integer>().build(
+                fields.add(new AjaxSpinnerFieldPanel.Builder<Integer>().build(
                         "field",
                         "maxAuthenticationAttempts",
                         Integer.class,
                         new PropertyModel<Integer>(policyTO, 
"maxAuthenticationAttempts")));
 
-                components.add(new AjaxCheckBoxPanel(
+                fields.add(new AjaxCheckBoxPanel(
                         "field",
                         "propagateSuspension",
                         new PropertyModel<Boolean>(policyTO, 
"propagateSuspension"),
                         false));
 
-                components.add(new 
AjaxPalettePanel.Builder<String>().setName("passthroughResources").build(
+                fields.add(new 
AjaxPalettePanel.Builder<String>().setName("passthroughResources").build(
                         "field",
                         new PropertyModel<List<String>>(policyTO, 
"passthroughResources"),
                         new ListModel<String>(resources.getObject())));
             }
 
             if (policyTO instanceof PasswordPolicyTO) {
-                components.add(new 
AjaxSpinnerFieldPanel.Builder<Integer>().build(
+                fields.add(new AjaxSpinnerFieldPanel.Builder<Integer>().build(
                         "field",
                         "historyLength",
                         Integer.class,
                         new PropertyModel<Integer>(policyTO, 
"historyLength")));
 
-                components.add(new AjaxCheckBoxPanel(
+                fields.add(new AjaxCheckBoxPanel(
                         "field",
                         "allowNullPassword",
                         new PropertyModel<Boolean>(policyTO, 
"allowNullPassword"),
                         false));
             }
 
-            add(new ListView<Component>("fields", components) {
+            add(new ListView<Component>("fields", fields) {
 
                 private static final long serialVersionUID = 
-9180479401817023838L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
index fb84c7e..7efb694 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/JsonEditorPanel.java
@@ -32,17 +32,22 @@ public class JsonEditorPanel extends 
AbstractModalPanel<String> {
 
     private final IModel<String> content;
 
+    private final boolean readOnly;
+
     public JsonEditorPanel(final IModel<String> content) {
-        this(null, content, null);
+        this(null, content, false, null);
     }
 
     public JsonEditorPanel(
             final BaseModal<String> modal,
             final IModel<String> content,
+            final boolean readOnly,
             final PageReference pageRef) {
+
         super(modal, pageRef);
         this.content = content;
-        final TextArea<String> jsonEditorInfoDefArea = new 
TextArea<>("jsonEditorInfo", this.content);
+        this.readOnly = readOnly;
+        TextArea<String> jsonEditorInfoDefArea = new 
TextArea<>("jsonEditorInfo", this.content);
         
jsonEditorInfoDefArea.setMarkupId("jsonEditorInfo").setOutputMarkupPlaceholderTag(true);
         add(jsonEditorInfoDefArea);
     }
@@ -52,6 +57,7 @@ public class JsonEditorPanel extends 
AbstractModalPanel<String> {
         super.renderHead(response);
         response.render(OnLoadHeaderItem.forScript(
                 
"CodeMirror.fromTextArea(document.getElementById('jsonEditorInfo'), {"
+                + "  readOnly: " + readOnly + ", "
                 + "  lineNumbers: true, "
                 + "  lineWrapping: true, "
                 + "  matchBrackets: true,"

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MappingPurposePanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MappingPurposePanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MappingPurposePanel.java
index f5d43a6..7a5e6ce 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MappingPurposePanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/MappingPurposePanel.java
@@ -103,31 +103,31 @@ public class MappingPurposePanel extends Panel {
     private void setOpacity(final MappingPurpose mappingPurpose) {
         switch (mappingPurpose) {
             case PROPAGATION:
-                propagation.add(new AttributeModifier("style", new 
Model<String>("opacity: 1;")));
-                pull.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                both.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                none.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
+                propagation.add(new AttributeModifier("style", new 
Model<>("opacity: 1;")));
+                pull.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
+                both.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
+                none.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
                 break;
 
             case PULL:
-                pull.add(new AttributeModifier("style", new 
Model<String>("opacity: 1;")));
-                propagation.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                both.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                none.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
+                pull.add(new AttributeModifier("style", new Model<>("opacity: 
1;")));
+                propagation.add(new AttributeModifier("style", new 
Model<>("opacity: 0.3;")));
+                both.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
+                none.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
                 break;
 
             case BOTH:
-                both.add(new AttributeModifier("style", new 
Model<String>("opacity: 1;")));
-                propagation.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                pull.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                none.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
+                both.add(new AttributeModifier("style", new Model<>("opacity: 
1;")));
+                propagation.add(new AttributeModifier("style", new 
Model<>("opacity: 0.3;")));
+                pull.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
+                none.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
                 break;
 
             case NONE:
-                none.add(new AttributeModifier("style", new 
Model<String>("opacity: 1;")));
-                pull.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                propagation.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
-                both.add(new AttributeModifier("style", new 
Model<String>("opacity: 0.3;")));
+                none.add(new AttributeModifier("style", new Model<>("opacity: 
1;")));
+                pull.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
+                propagation.add(new AttributeModifier("style", new 
Model<>("opacity: 0.3;")));
+                both.add(new AttributeModifier("style", new Model<>("opacity: 
0.3;")));
                 break;
 
             default:

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/XMLEditorPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/XMLEditorPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/XMLEditorPanel.java
new file mode 100644
index 0000000..4249641
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/XMLEditorPanel.java
@@ -0,0 +1,74 @@
+/*
+ * 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.syncope.client.console.panels.AbstractModalPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.OnLoadHeaderItem;
+import org.apache.wicket.markup.html.form.TextArea;
+import org.apache.wicket.model.IModel;
+
+public class XMLEditorPanel extends AbstractModalPanel<Serializable> {
+
+    private static final long serialVersionUID = -5110368813584745668L;
+
+    private final IModel<String> content;
+
+    private final boolean readOnly;
+
+    public XMLEditorPanel(final IModel<String> content) {
+        this(null, content, false, null);
+    }
+
+    public XMLEditorPanel(
+            final BaseModal<Serializable> modal,
+            final IModel<String> content,
+            final boolean readOnly,
+            final PageReference pageRef) {
+
+        super(modal, pageRef);
+        this.content = content;
+        this.readOnly = readOnly;
+        final TextArea<String> xmlEditorInfoDefArea = new 
TextArea<>("xmlEditorInfo", this.content);
+        
xmlEditorInfoDefArea.setMarkupId("xmlEditorInfo").setOutputMarkupPlaceholderTag(true);
+        add(xmlEditorInfoDefArea);
+    }
+
+    @Override
+    public void renderHead(final IHeaderResponse response) {
+        super.renderHead(response);
+        response.render(OnLoadHeaderItem.forScript(
+                
"CodeMirror.fromTextArea(document.getElementById('xmlEditorInfo'), {"
+                + "  readOnly: " + readOnly + ", "
+                + "  lineNumbers: true, "
+                + "  lineWrapping: true, "
+                + "  autoCloseTags: true, "
+                + "  mode: 'text/html', "
+                + "  autoRefresh: true"
+                + "}).on('change', updateTextArea);"));
+    }
+
+    @Override
+    public IModel<String> getItem() {
+        return content;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
new file mode 100644
index 0000000..382250d
--- /dev/null
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/AbstractMappingPanel.java
@@ -0,0 +1,464 @@
+/*
+ * 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.wizards;
+
+import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverBehavior;
+import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig;
+import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.syncope.client.console.commons.ConnIdSpecialName;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import 
org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
+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.console.wicket.markup.html.form.AjaxCheckBoxPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import 
org.apache.syncope.client.console.wicket.markup.html.form.MappingPurposePanel;
+import org.apache.syncope.client.console.widgets.JEXLTransformerWidget;
+import org.apache.syncope.client.console.widgets.MappingItemTransformerWidget;
+import 
org.apache.syncope.client.console.wizards.resources.JEXLTransformersTogglePanel;
+import 
org.apache.syncope.client.console.wizards.resources.MappingItemTransformersTogglePanel;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.StandardEntitlement;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxButton;
+import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
+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.list.ListItem;
+import org.apache.wicket.markup.html.list.ListView;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+import org.apache.wicket.model.PropertyModel;
+import org.apache.wicket.model.ResourceModel;
+
+public abstract class AbstractMappingPanel extends Panel {
+
+    private static final long serialVersionUID = -8295587900937040104L;
+
+    protected static final Set<String> USER_FIELD_NAMES = new HashSet<>();
+
+    protected static final Set<String> GROUP_FIELD_NAMES = new HashSet<>();
+
+    protected static final Set<String> ANY_OBJECT_FIELD_NAMES = new 
HashSet<>();
+
+    static {
+        initFieldNames(UserTO.class, USER_FIELD_NAMES);
+        initFieldNames(GroupTO.class, GROUP_FIELD_NAMES);
+        initFieldNames(AnyObjectTO.class, ANY_OBJECT_FIELD_NAMES);
+    }
+
+    private static void initFieldNames(final Class<?> entityClass, final 
Set<String> keys) {
+        List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
+        classes.add(entityClass);
+        for (Class<?> clazz : classes) {
+            for (Field field : clazz.getDeclaredFields()) {
+                if (!Modifier.isStatic(field.getModifiers())
+                        && !Collection.class.isAssignableFrom(field.getType())
+                        && !Map.class.isAssignableFrom(field.getType())) {
+
+                    keys.add(field.getName());
+                }
+            }
+        }
+    }
+
+    /**
+     * Any type rest client.
+     */
+    protected final AnyTypeRestClient anyTypeRestClient = new 
AnyTypeRestClient();
+
+    /**
+     * Any type class rest client.
+     */
+    protected final AnyTypeClassRestClient anyTypeClassRestClient = new 
AnyTypeClassRestClient();
+
+    protected final Label passwordLabel;
+
+    protected final Label purposeLabel;
+
+    /**
+     * Add mapping button.
+     */
+    protected final AjaxButton addMappingBtn;
+
+    /**
+     * All mappings.
+     */
+    protected final ListView<MappingItemTO> mappings;
+
+    /**
+     * Mapping container.
+     */
+    protected final WebMarkupContainer mappingContainer;
+
+    protected final IModel<List<MappingItemTO>> model;
+
+    public AbstractMappingPanel(
+            final String id,
+            final MappingItemTransformersTogglePanel mapItemTransformers,
+            final JEXLTransformersTogglePanel jexlTransformers,
+            final IModel<List<MappingItemTO>> model,
+            final boolean addMappingBtnVisible,
+            final boolean hidePurpose,
+            final MappingPurpose defaultPurpose) {
+
+        super(id);
+        setOutputMarkupId(true);
+
+        this.model = model;
+
+        mappingContainer = new WebMarkupContainer("mappingContainer");
+        mappingContainer.setOutputMarkupId(true);
+        add(mappingContainer);
+
+        passwordLabel = new Label("passwordLabel", new 
ResourceModel("password"));
+        mappingContainer.add(passwordLabel);
+
+        purposeLabel = new Label("purposeLabel", new ResourceModel("purpose"));
+        mappingContainer.add(purposeLabel);
+
+        mappingContainer.add(new Label("intAttrNameInfo", Model.of()).add(new 
PopoverBehavior(
+                Model.<String>of(),
+                Model.of(getString("intAttrNameInfo.help")
+                        + "<div style=\"font-size: 10px;\">"
+                        + "<code>groups[groupName].attribute</code>\n"
+                        + "<code>anyObjects[anyObjectName].attribute</code>\n"
+                        + "<code>memberships[groupName].attribute</code>\n"
+                        + "</div>"),
+                new 
PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.bottom)) {
+
+            private static final long serialVersionUID = -7867802555691605021L;
+
+            @Override
+            protected String createRelAttribute() {
+                return "intAttrNameInfo";
+            }
+        }));
+
+        mappingContainer.add(Constants.getJEXLPopover(this, 
TooltipConfig.Placement.bottom));
+
+        Collections.sort(model.getObject(), new Comparator<MappingItemTO>() {
+
+            @Override
+            public int compare(final MappingItemTO left, final MappingItemTO 
right) {
+                int compared;
+                if (left == null && right == null) {
+                    compared = 0;
+                } else if (left == null) {
+                    compared = 1;
+                } else if (right == null) {
+                    compared = -1;
+                } else if (left.isConnObjectKey()) {
+                    compared = -1;
+                } else if (right.isConnObjectKey()) {
+                    compared = 1;
+                } else if (left.isPassword()) {
+                    compared = -1;
+                } else if (right.isPassword()) {
+                    compared = 1;
+                } else if (left.getPurpose() == MappingPurpose.BOTH && 
right.getPurpose() != MappingPurpose.BOTH) {
+                    compared = -1;
+                } else if (left.getPurpose() != MappingPurpose.BOTH && 
right.getPurpose() == MappingPurpose.BOTH) {
+                    compared = 1;
+                } else if (left.getPurpose() == MappingPurpose.PROPAGATION
+                        && (right.getPurpose() == MappingPurpose.PULL
+                        || right.getPurpose() == MappingPurpose.NONE)) {
+                    compared = -1;
+                } else if (left.getPurpose() == MappingPurpose.PULL
+                        && right.getPurpose() == MappingPurpose.PROPAGATION) {
+                    compared = 1;
+                } else if (left.getPurpose() == MappingPurpose.PULL
+                        && right.getPurpose() == MappingPurpose.NONE) {
+                    compared = -1;
+                } else if (left.getPurpose() == MappingPurpose.NONE
+                        && right.getPurpose() != MappingPurpose.NONE) {
+                    compared = 1;
+                } else {
+                    compared = 
left.getIntAttrName().compareTo(right.getIntAttrName());
+                }
+                return compared;
+            }
+        });
+
+        mappings = new ListView<MappingItemTO>("mappings", model.getObject()) {
+
+            private static final long serialVersionUID = 4949588177564901031L;
+
+            @Override
+            protected void populateItem(final ListItem<MappingItemTO> item) {
+                final MappingItemTO mapItem = item.getModelObject();
+                if (mapItem.getPurpose() == null) {
+                    mapItem.setPurpose(defaultPurpose);
+                }
+
+                //--------------------------------
+                // Internal attribute
+                // -------------------------------
+                AjaxTextFieldPanel intAttrName = new AjaxTextFieldPanel(
+                        "intAttrName",
+                        getString("intAttrName"),
+                        new PropertyModel<String>(mapItem, "intAttrName"),
+                        false);
+                intAttrName.setChoices(Collections.<String>emptyList());
+                intAttrName.setRequired(true).hideLabel();
+                item.add(intAttrName);
+                // -------------------------------
+
+                //--------------------------------
+                // External attribute
+                // -------------------------------
+                final AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel(
+                        "extAttrName",
+                        getString("extAttrName"),
+                        new PropertyModel<String>(mapItem, "extAttrName"));
+                extAttrName.setChoices(getExtAttrNames().getObject());
+
+                boolean required = !mapItem.isPassword();
+                extAttrName.setRequired(required).hideLabel();
+                extAttrName.setEnabled(required);
+                item.add(extAttrName);
+                // -------------------------------
+
+                //--------------------------------
+                // JEXL transformers
+                // -------------------------------
+                item.add(new JEXLTransformerWidget(
+                        "jexlTransformers", mapItem, 
jexlTransformers).setRenderBodyOnly(true));
+                // -------------------------------
+
+                //--------------------------------
+                // Mapping item transformers
+                // -------------------------------
+                item.add(new MappingItemTransformerWidget(
+                        "mappingItemTransformers", mapItem, 
mapItemTransformers).setRenderBodyOnly(true));
+                // -------------------------------
+
+                //--------------------------------
+                // Mandatory
+                // -------------------------------
+                final AjaxTextFieldPanel mandatory = new AjaxTextFieldPanel(
+                        "mandatoryCondition",
+                        new ResourceModel("mandatoryCondition", 
"mandatoryCondition").getObject(),
+                        new PropertyModel<String>(mapItem, 
"mandatoryCondition"));
+                mandatory.hideLabel();
+                mandatory.setChoices(Arrays.asList(new String[] { "true", 
"false" }));
+                mandatory.setEnabled(!mapItem.isConnObjectKey());
+                item.add(mandatory);
+                // -------------------------------
+
+                //--------------------------------
+                // Connector object key
+                // -------------------------------
+                final AjaxCheckBoxPanel connObjectKey = new AjaxCheckBoxPanel(
+                        "connObjectKey",
+                        new ResourceModel("connObjectKey", 
"connObjectKey").getObject(),
+                        new PropertyModel<Boolean>(mapItem, "connObjectKey"), 
false);
+                connObjectKey.hideLabel();
+                item.add(connObjectKey);
+                // -------------------------------
+
+                //--------------------------------
+                // Password
+                // -------------------------------
+                final AjaxCheckBoxPanel password = new AjaxCheckBoxPanel(
+                        "password",
+                        new ResourceModel("password", "password").getObject(),
+                        new PropertyModel<Boolean>(mapItem, "password"), 
false);
+                item.add(password.hideLabel());
+                // -------------------------------
+
+                //--------------------------------
+                // Purpose
+                // -------------------------------
+                WebMarkupContainer purpose = new WebMarkupContainer("purpose");
+                purpose.setOutputMarkupId(Boolean.TRUE);
+
+                final MappingPurposePanel purposeActions = new 
MappingPurposePanel(
+                        "purposeActions", new 
PropertyModel<MappingPurpose>(mapItem, "purpose"), purpose);
+                purpose.add(purposeActions.setRenderBodyOnly(true));
+                item.add(purpose);
+                // -------------------------------
+
+                //--------------------------------
+                // Remove
+                // -------------------------------
+                final ActionLinksPanel.Builder<Serializable> actions = 
ActionLinksPanel.builder();
+                actions.add(new ActionLink<Serializable>() {
+
+                    private static final long serialVersionUID = 
-3722207913631435501L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final 
Serializable ignore) {
+                        int index = -1;
+                        for (int i = 0; i < model.getObject().size() && index 
== -1; i++) {
+                            if (mapItem.equals(model.getObject().get(i))) {
+                                index = i;
+                            }
+                        }
+
+                        if (index != -1) {
+                            model.getObject().remove(index);
+                            item.getParent().removeAll();
+                            target.add(AbstractMappingPanel.this);
+                        }
+                    }
+                }, ActionLink.ActionType.DELETE, 
StandardEntitlement.RESOURCE_UPDATE);
+                item.add(actions.build("toRemove"));
+                // -------------------------------
+
+                intAttrName.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                    private static final long serialVersionUID = 
-1107858522700306810L;
+
+                    @Override
+                    protected void onUpdate(final AjaxRequestTarget target) {
+                    }
+                });
+
+                connObjectKey.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                    private static final long serialVersionUID = 
-1107858522700306810L;
+
+                    @Override
+                    protected void onUpdate(final AjaxRequestTarget target) {
+                        if (connObjectKey.getModelObject()) {
+                            mapItem.setMandatoryCondition("true");
+                            mandatory.setModelObject("true");
+                            mandatory.setEnabled(false);
+                        } else {
+                            mapItem.setMandatoryCondition("false");
+                            mandatory.setModelObject("false");
+                            mandatory.setEnabled(true);
+                        }
+                        target.add(mandatory);
+                    }
+                });
+
+                password.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+
+                    private static final long serialVersionUID = 
-1107858522700306810L;
+
+                    @Override
+                    protected void onUpdate(final AjaxRequestTarget target) {
+                        extAttrName.setEnabled(!password.getModelObject());
+                        extAttrName.setModelObject(password.getModelObject()
+                                ? ConnIdSpecialName.PASSWORD : 
extAttrName.getModelObject());
+                        extAttrName.setRequired(!password.getModelObject());
+                        target.add(extAttrName);
+
+                        setConnObjectKey(connObjectKey, password);
+                        target.add(connObjectKey);
+                    }
+                });
+
+                setConnObjectKey(connObjectKey, password);
+                setAttrNames(intAttrName);
+
+                if (hidePassword()) {
+                    password.setVisible(false);
+
+                    // Changes required by clone ....
+                    extAttrName.setEnabled(true);
+                    if (mapItem.isPassword()) {
+                        // re-enable if and only if cloned object mapping item 
was a password
+                        intAttrName.setEnabled(true);
+                    }
+                    mapItem.setPassword(false);
+                }
+
+                if (hidePurpose) {
+                    purpose.setVisible(false);
+                }
+            }
+        };
+
+        mappings.setReuseItems(true);
+        mappingContainer.add(mappings);
+
+        addMappingBtn = new IndicatingAjaxButton("addMappingBtn", new 
ResourceModel("add")) {
+
+            private static final long serialVersionUID = -4804368561204623354L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final 
Form<?> form) {
+                model.getObject().add(new MappingItemTO());
+                target.add(AbstractMappingPanel.this);
+            }
+        };
+        addMappingBtn.setDefaultFormProcessing(false);
+        addMappingBtn.setEnabled(addMappingBtnVisible);
+        mappingContainer.add(addMappingBtn);
+
+    }
+
+    protected boolean hidePassword() {
+        return true;
+    }
+
+    protected abstract IModel<List<String>> getExtAttrNames();
+
+    /**
+     * Set attribute names for a drop down choice list.
+     *
+     * @param toBeUpdated drop down choice to be updated.
+     */
+    protected abstract void setAttrNames(AjaxTextFieldPanel toBeUpdated);
+
+    @Override
+    protected void onBeforeRender() {
+        super.onBeforeRender();
+        passwordLabel.setVisible(false);
+        purposeLabel.setVisible(true);
+    }
+
+    /**
+     * Enable/Disable connObjectKey checkbox.
+     *
+     * @param connObjectKey connObjectKey checkbox.
+     * @param password password checkbox.
+     */
+    private void setConnObjectKey(final AjaxCheckBoxPanel connObjectKey, final 
AjaxCheckBoxPanel password) {
+        if (password.getModelObject()) {
+            connObjectKey.setReadOnly(true);
+            connObjectKey.setModelObject(false);
+        } else {
+            connObjectKey.setReadOnly(false);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
index 4c234a4..7d3f612 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
@@ -26,7 +26,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName;
+import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
@@ -155,7 +155,7 @@ public class ConnObjectPanel extends Panel {
             field = new AjaxTextFieldPanel(id, schemaName, new 
Model<String>());
         } else if (CollectionUtils.isEmpty(attrTO.getValues())) {
             field = new AjaxTextFieldPanel(id, schemaName, new 
Model<String>());
-        } else if (ConnIdSpecialAttributeName.PASSWORD.equals(schemaName)) {
+        } else if (ConnIdSpecialName.PASSWORD.equals(schemaName)) {
             field = new AjaxTextFieldPanel(id, schemaName, new 
Model<>("********"));
         } else if (attrTO.getValues().size() == 1) {
             field = new AjaxTextFieldPanel(id, schemaName, new 
Model<>(attrTO.getValues().get(0)));

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
index 7e7f375..7045013 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ProvisionWizardBuilder.java
@@ -26,6 +26,7 @@ import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.commons.ConnIdSpecialName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.panels.ProvisionAuxClassesPanel;
 import org.apache.syncope.client.console.rest.AnyTypeRestClient;
@@ -37,6 +38,7 @@ import 
org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
 import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -53,7 +55,7 @@ import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.model.StringResourceModel;
 
-public class ProvisionWizardBuilder extends AjaxWizardBuilder<ProvisionTO> 
implements Serializable {
+public class ProvisionWizardBuilder extends AjaxWizardBuilder<ProvisionTO> {
 
     private static final long serialVersionUID = 3739399543837732640L;
 
@@ -98,10 +100,6 @@ public class ProvisionWizardBuilder extends 
AjaxWizardBuilder<ProvisionTO> imple
 
         private static final long serialVersionUID = -1657800545799468278L;
 
-        private static final String ACCOUNT = "__ACCOUNT__";
-
-        private static final String GROUP = "__GROUP__";
-
         ObjectType(final ProvisionTO item) {
             super(new ResourceModel("type.title", StringUtils.EMPTY),
                     new ResourceModel("type.summary", StringUtils.EMPTY), new 
Model<>(item));
@@ -128,10 +126,10 @@ public class ProvisionWizardBuilder extends 
AjaxWizardBuilder<ProvisionTO> imple
                 @Override
                 protected void onUpdate(final AjaxRequestTarget target) {
                     if (AnyTypeKind.USER.name().equals(type.getModelObject())) 
{
-                        clazz.setModelObject(ACCOUNT);
+                        clazz.setModelObject(ConnIdSpecialName.ACCOUNT);
                         target.add(container);
                     } else if 
(AnyTypeKind.GROUP.name().equals(type.getModelObject())) {
-                        clazz.setModelObject(GROUP);
+                        clazz.setModelObject(ConnIdSpecialName.GROUP);
                         target.add(container);
                     }
                 }
@@ -161,8 +159,8 @@ public class ProvisionWizardBuilder extends 
AjaxWizardBuilder<ProvisionTO> imple
         private static final long serialVersionUID = 3454904947720856253L;
 
         Mapping(final ProvisionTO item) {
-            setTitleModel(new ResourceModel("mapping.title"));
-            setSummaryModel(new StringResourceModel("mapping.summary", this, 
new Model<>(item)));
+            setTitleModel(Model.of("Mapping"));
+            setSummaryModel(Model.of(StringUtils.EMPTY));
         }
     }
 
@@ -242,11 +240,14 @@ public class ProvisionWizardBuilder extends 
AjaxWizardBuilder<ProvisionTO> imple
         Mapping mapping = new Mapping(modelObject);
         mapping.setOutputMarkupId(true);
 
-        MappingItemTransformersTogglePanel mapItemTransformers
-                = new MappingItemTransformersTogglePanel(mapping, pageRef);
+        MappingItemTransformersTogglePanel mapItemTransformers =
+                new MappingItemTransformersTogglePanel(mapping, pageRef);
         addOuterObject(mapItemTransformers);
         JEXLTransformersTogglePanel jexlTransformers = new 
JEXLTransformersTogglePanel(mapping, pageRef);
         addOuterObject(jexlTransformers);
+        if (modelObject.getMapping() == null) {
+            modelObject.setMapping(new MappingTO());
+        }
         mapping.add(new ResourceMappingPanel(
                 "mapping", resourceTO, modelObject, mapItemTransformers, 
jexlTransformers));
 
@@ -260,23 +261,21 @@ public class ProvisionWizardBuilder extends 
AjaxWizardBuilder<ProvisionTO> imple
     protected Serializable onApplyInternal(final ProvisionTO modelObject) {
         final List<ProvisionTO> provisions;
         if (modelObject.getKey() == null) {
-            provisions
-                    = ListUtils.select(this.resourceTO.getProvisions(), new 
Predicate<ProvisionTO>() {
-
-                        @Override
-                        public boolean evaluate(final ProvisionTO object) {
-                            return 
!modelObject.getAnyType().equals(object.getAnyType());
-                        }
-                    });
+            provisions = ListUtils.select(this.resourceTO.getProvisions(), new 
Predicate<ProvisionTO>() {
+
+                @Override
+                public boolean evaluate(final ProvisionTO object) {
+                    return 
!modelObject.getAnyType().equals(object.getAnyType());
+                }
+            });
         } else {
-            provisions
-                    = ListUtils.select(this.resourceTO.getProvisions(), new 
Predicate<ProvisionTO>() {
-
-                        @Override
-                        public boolean evaluate(final ProvisionTO object) {
-                            return 
!modelObject.getKey().equals(object.getKey());
-                        }
-                    });
+            provisions = ListUtils.select(this.resourceTO.getProvisions(), new 
Predicate<ProvisionTO>() {
+
+                @Override
+                public boolean evaluate(final ProvisionTO object) {
+                    return !modelObject.getKey().equals(object.getKey());
+                }
+            });
         }
         provisions.add(modelObject);
         this.resourceTO.getProvisions().clear();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
index 8c02c36..ee13453 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
@@ -18,126 +18,36 @@
  */
 package org.apache.syncope.client.console.wizards.resources;
 
-import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverBehavior;
-import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig;
-import 
de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
-import java.io.Serializable;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.apache.commons.lang3.ClassUtils;
-import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName;
-import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
-import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.ConnectorRestClient;
-import 
org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
-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.console.wicket.markup.html.form.AjaxCheckBoxPanel;
 import 
org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
-import 
org.apache.syncope.client.console.wicket.markup.html.form.MappingPurposePanel;
-import org.apache.syncope.client.console.widgets.JEXLTransformerWidget;
-import org.apache.syncope.client.console.widgets.MappingItemTransformerWidget;
-import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.client.console.wizards.AbstractMappingPanel;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
-import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.MappingItemTO;
-import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.common.lib.types.StandardEntitlement;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.markup.html.form.AjaxButton;
-import org.apache.wicket.extensions.ajax.markup.html.IndicatingAjaxButton;
-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.list.ListItem;
-import org.apache.wicket.markup.html.list.ListView;
-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.Model;
-import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.util.ListModel;
 
 /**
  * Resource mapping panel.
  */
-public class ResourceMappingPanel extends Panel {
+public class ResourceMappingPanel extends AbstractMappingPanel {
 
     private static final long serialVersionUID = -7982691107029848579L;
 
-    private static final Set<String> USER_FIELD_NAMES = new HashSet<>();
-
-    private static final Set<String> GROUP_FIELD_NAMES = new HashSet<>();
-
-    private static final Set<String> ANY_OBJECT_FIELD_NAMES = new HashSet<>();
-
-    static {
-        initFieldNames(UserTO.class, USER_FIELD_NAMES);
-        initFieldNames(GroupTO.class, GROUP_FIELD_NAMES);
-        initFieldNames(AnyObjectTO.class, ANY_OBJECT_FIELD_NAMES);
-    }
-
-    private static void initFieldNames(final Class<?> entityClass, final 
Set<String> keys) {
-        List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
-        classes.add(entityClass);
-        for (Class<?> clazz : classes) {
-            for (Field field : clazz.getDeclaredFields()) {
-                if (!Modifier.isStatic(field.getModifiers())
-                        && !Collection.class.isAssignableFrom(field.getType())
-                        && !Map.class.isAssignableFrom(field.getType())) {
-
-                    keys.add(field.getName());
-                }
-            }
-        }
-    }
-
-    /**
-     * Any type rest client.
-     */
-    private final AnyTypeRestClient anyTypeRestClient = new 
AnyTypeRestClient();
-
-    /**
-     * Any type class rest client.
-     */
-    private final AnyTypeClassRestClient anyTypeClassRestClient = new 
AnyTypeClassRestClient();
-
-    private final Label passwordLabel;
-
-    /**
-     * Add mapping button.
-     */
-    private final AjaxButton addMappingBtn;
-
-    /**
-     * All mappings.
-     */
-    private final ListView<MappingItemTO> mappings;
-
     /**
      * External resource provisioning configuration instance to be updated.
      */
     private final ProvisionTO provisionTO;
 
-    /**
-     * Mapping container.
-     */
-    private final WebMarkupContainer mappingContainer;
+    private final LoadableDetachableModel<List<String>> extAttrNames;
 
     /**
      * Attribute Mapping Panel.
@@ -155,15 +65,19 @@ public class ResourceMappingPanel extends Panel {
             final MappingItemTransformersTogglePanel mapItemTransformers,
             final JEXLTransformersTogglePanel jexlTransformers) {
 
-        super(id);
+        super(id,
+                mapItemTransformers,
+                jexlTransformers,
+                new 
ListModel<MappingItemTO>(provisionTO.getMapping().getItems()),
+                resourceTO.getConnector() != null,
+                false,
+                MappingPurpose.BOTH);
+
         setOutputMarkupId(true);
 
         this.provisionTO = provisionTO;
-        if (provisionTO.getMapping() == null) {
-            provisionTO.setMapping(new MappingTO());
-        }
 
-        final LoadableDetachableModel<List<String>> extAttrNames = new 
LoadableDetachableModel<List<String>>() {
+        extAttrNames = new LoadableDetachableModel<List<String>>() {
 
             private static final long serialVersionUID = 5275935387613157437L;
 
@@ -175,282 +89,16 @@ public class ResourceMappingPanel extends Panel {
                         resourceTO.getConfOverride());
             }
         };
+    }
 
-        this.mappingContainer = new WebMarkupContainer("mappingContainer");
-        this.mappingContainer.setOutputMarkupId(true);
-        add(this.mappingContainer);
-
-        mappingContainer.add(new Label("intAttrNameInfo", Model.of()).add(new 
PopoverBehavior(
-                Model.<String>of(),
-                Model.of(getString("intAttrNameInfo.help")
-                + "<div style=\"font-size: 10px;\">"
-                + "<code>groups[groupName].attribute</code>\n"
-                + "<code>anyObjects[anyObjectName].attribute</code>\n"
-                + "<code>memberships[groupName].attribute</code>\n"
-                + "</div>"),
-                new 
PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.bottom)) {
-
-            private static final long serialVersionUID = -7867802555691605021L;
-
-            @Override
-            protected String createRelAttribute() {
-                return "intAttrNameInfo";
-            }
-        }));
-
-        mappingContainer.add(Constants.getJEXLPopover(this, 
TooltipConfig.Placement.bottom));
-
-        passwordLabel = new Label("passwordLabel", new 
ResourceModel("password"));
-        mappingContainer.add(passwordLabel);
-
-        Collections.sort(provisionTO.getMapping().getItems(), new 
Comparator<MappingItemTO>() {
-
-            @Override
-            public int compare(final MappingItemTO left, final MappingItemTO 
right) {
-                int compared;
-                if (left == null && right == null) {
-                    compared = 0;
-                } else if (left == null) {
-                    compared = 1;
-                } else if (right == null) {
-                    compared = -1;
-                } else if (left.isConnObjectKey()) {
-                    compared = -1;
-                } else if (right.isConnObjectKey()) {
-                    compared = 1;
-                } else if (left.isPassword()) {
-                    compared = -1;
-                } else if (right.isPassword()) {
-                    compared = 1;
-                } else if (left.getPurpose() == MappingPurpose.BOTH && 
right.getPurpose() != MappingPurpose.BOTH) {
-                    compared = -1;
-                } else if (left.getPurpose() != MappingPurpose.BOTH && 
right.getPurpose() == MappingPurpose.BOTH) {
-                    compared = 1;
-                } else if (left.getPurpose() == MappingPurpose.PROPAGATION
-                        && (right.getPurpose() == MappingPurpose.PULL
-                        || right.getPurpose() == MappingPurpose.NONE)) {
-                    compared = -1;
-                } else if (left.getPurpose() == MappingPurpose.PULL
-                        && right.getPurpose() == MappingPurpose.PROPAGATION) {
-                    compared = 1;
-                } else if (left.getPurpose() == MappingPurpose.PULL
-                        && right.getPurpose() == MappingPurpose.NONE) {
-                    compared = -1;
-                } else if (left.getPurpose() == MappingPurpose.NONE
-                        && right.getPurpose() != MappingPurpose.NONE) {
-                    compared = 1;
-                } else {
-                    compared = 
left.getIntAttrName().compareTo(right.getIntAttrName());
-                }
-                return compared;
-            }
-        });
-
-        mappings = new ListView<MappingItemTO>("mappings", 
provisionTO.getMapping().getItems()) {
-
-            private static final long serialVersionUID = 4949588177564901031L;
-
-            @Override
-            protected void populateItem(final ListItem<MappingItemTO> item) {
-                final MappingItemTO mapItem = item.getModelObject();
-                if (mapItem.getPurpose() == null) {
-                    mapItem.setPurpose(MappingPurpose.BOTH);
-                }
-
-                //--------------------------------
-                // Internal attribute
-                // -------------------------------
-                AjaxTextFieldPanel intAttrName = new AjaxTextFieldPanel(
-                        "intAttrName",
-                        getString("intAttrName"),
-                        new PropertyModel<String>(mapItem, "intAttrName"),
-                        false);
-                intAttrName.setChoices(Collections.<String>emptyList());
-                intAttrName.setRequired(true).hideLabel();
-                item.add(intAttrName);
-                // -------------------------------
-
-                //--------------------------------
-                // External attribute
-                // -------------------------------
-                final AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel(
-                        "extAttrName",
-                        getString("extAttrName"),
-                        new PropertyModel<String>(mapItem, "extAttrName"));
-                extAttrName.setChoices(extAttrNames.getObject());
-
-                boolean required = !mapItem.isPassword();
-                extAttrName.setRequired(required).hideLabel();
-                extAttrName.setEnabled(required);
-                item.add(extAttrName);
-                // -------------------------------
-
-                //--------------------------------
-                // JEXL transformers
-                // -------------------------------
-                item.add(new JEXLTransformerWidget(
-                        "jexlTransformers", mapItem, 
jexlTransformers).setRenderBodyOnly(true));
-                // -------------------------------
-
-                //--------------------------------
-                // Mapping item transformers
-                // -------------------------------
-                item.add(new MappingItemTransformerWidget(
-                        "mappingItemTransformers", mapItem, 
mapItemTransformers).setRenderBodyOnly(true));
-                // -------------------------------
-
-                //--------------------------------
-                // Mandatory
-                // -------------------------------
-                final AjaxTextFieldPanel mandatory = new AjaxTextFieldPanel(
-                        "mandatoryCondition",
-                        new ResourceModel("mandatoryCondition", 
"mandatoryCondition").getObject(),
-                        new PropertyModel<String>(mapItem, 
"mandatoryCondition"));
-                mandatory.hideLabel();
-                mandatory.setChoices(Arrays.asList(new String[] { "true", 
"false" }));
-                mandatory.setEnabled(!mapItem.isConnObjectKey());
-                item.add(mandatory);
-                // -------------------------------
-
-                //--------------------------------
-                // Connector object key
-                // -------------------------------
-                final AjaxCheckBoxPanel connObjectKey = new AjaxCheckBoxPanel(
-                        "connObjectKey",
-                        new ResourceModel("connObjectKey", 
"connObjectKey").getObject(),
-                        new PropertyModel<Boolean>(mapItem, "connObjectKey"), 
false);
-                connObjectKey.hideLabel();
-                item.add(connObjectKey);
-                // -------------------------------
-
-                //--------------------------------
-                // Password
-                // -------------------------------
-                final AjaxCheckBoxPanel password = new AjaxCheckBoxPanel(
-                        "password",
-                        new ResourceModel("password", "password").getObject(),
-                        new PropertyModel<Boolean>(mapItem, "password"), 
false);
-                item.add(password.hideLabel());
-                // -------------------------------
-
-                //--------------------------------
-                // Purpose
-                // -------------------------------
-                WebMarkupContainer purpose = new WebMarkupContainer("purpose");
-                purpose.setOutputMarkupId(Boolean.TRUE);
-
-                final MappingPurposePanel panel = new MappingPurposePanel(
-                        "purposeActions", new 
PropertyModel<MappingPurpose>(mapItem, "purpose"), purpose);
-
-                purpose.add(panel.setRenderBodyOnly(true));
-                item.add(purpose);
-                // -------------------------------
-
-                //--------------------------------
-                // Remove
-                // -------------------------------
-                final ActionLinksPanel.Builder<Serializable> actions = 
ActionLinksPanel.builder();
-                actions.add(new ActionLink<Serializable>() {
-
-                    private static final long serialVersionUID = 
-3722207913631435501L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final 
Serializable ignore) {
-                        int index = -1;
-                        for (int i = 0; i < 
provisionTO.getMapping().getItems().size() && index == -1; i++) {
-                            if 
(mapItem.equals(provisionTO.getMapping().getItems().get(i))) {
-                                index = i;
-                            }
-                        }
-
-                        if (index != -1) {
-                            provisionTO.getMapping().getItems().remove(index);
-                            item.getParent().removeAll();
-                            target.add(ResourceMappingPanel.this);
-                        }
-                    }
-                }, ActionLink.ActionType.DELETE, 
StandardEntitlement.RESOURCE_UPDATE);
-                item.add(actions.build("toRemove"));
-                // -------------------------------
-
-                intAttrName.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                    private static final long serialVersionUID = 
-1107858522700306810L;
-
-                    @Override
-                    protected void onUpdate(final AjaxRequestTarget target) {
-                    }
-                });
-
-                connObjectKey.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                    private static final long serialVersionUID = 
-1107858522700306810L;
-
-                    @Override
-                    protected void onUpdate(final AjaxRequestTarget target) {
-                        if (connObjectKey.getModelObject()) {
-                            mapItem.setMandatoryCondition("true");
-                            mandatory.setModelObject("true");
-                            mandatory.setEnabled(false);
-                        } else {
-                            mapItem.setMandatoryCondition("false");
-                            mandatory.setModelObject("false");
-                            mandatory.setEnabled(true);
-                        }
-                        target.add(mandatory);
-                    }
-                });
-
-                password.getField().add(new 
IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                    private static final long serialVersionUID = 
-1107858522700306810L;
-
-                    @Override
-                    protected void onUpdate(final AjaxRequestTarget target) {
-                        extAttrName.setEnabled(!mapItem.isConnObjectKey() && 
!password.getModelObject());
-                        extAttrName.setModelObject(password.getModelObject()
-                                ? ConnIdSpecialAttributeName.PASSWORD : 
extAttrName.getModelObject());
-                        extAttrName.setRequired(!password.getModelObject());
-                        target.add(extAttrName);
-
-                        setConnObjectKey(connObjectKey, password);
-                        target.add(connObjectKey);
-                    }
-                });
-
-                setConnObjectKey(connObjectKey, password);
-                setAttrNames(intAttrName);
-
-                if (!AnyTypeKind.USER.name().equals(provisionTO.getAnyType())) 
{
-                    password.setVisible(false);
-
-                    // Changes required by clone ....
-                    extAttrName.setEnabled(!mapItem.isConnObjectKey());
-                    if (mapItem.isPassword()) {
-                        // re-enable if and only if cloned objec mapping item 
was a password
-                        intAttrName.setEnabled(true);
-                    }
-                    mapItem.setPassword(false);
-                }
-            }
-        };
-
-        mappings.setReuseItems(true);
-        mappingContainer.add(mappings);
-
-        addMappingBtn = new IndicatingAjaxButton("addMappingBtn", new 
ResourceModel("add")) {
-
-            private static final long serialVersionUID = -4804368561204623354L;
-
-            @Override
-            protected void onSubmit(final AjaxRequestTarget target, final 
Form<?> form) {
-                provisionTO.getMapping().getItems().add(new MappingItemTO());
-                target.add(ResourceMappingPanel.this);
-            }
-        };
-        addMappingBtn.setDefaultFormProcessing(false);
-        addMappingBtn.setEnabled(resourceTO.getConnector() != null);
-        mappingContainer.add(addMappingBtn);
+    @Override
+    protected boolean hidePassword() {
+        return !AnyTypeKind.USER.name().equals(provisionTO.getAnyType());
+    }
+    
+    @Override
+    protected IModel<List<String>> getExtAttrNames() {
+        return extAttrNames;
     }
 
     @Override
@@ -459,13 +107,8 @@ public class ResourceMappingPanel extends Panel {
         
passwordLabel.setVisible(AnyTypeKind.USER.name().equals(this.provisionTO.getAnyType()));
     }
 
-    /**
-     * Set attribute names for a drop down choice list.
-     *
-     * @param type attribute type.
-     * @param toBeUpdated drop down choice to be updated.
-     */
-    private void setAttrNames(final AjaxTextFieldPanel toBeUpdated) {
+    @Override
+    protected void setAttrNames(final AjaxTextFieldPanel toBeUpdated) {
         toBeUpdated.setRequired(true);
         toBeUpdated.setEnabled(true);
 
@@ -501,19 +144,4 @@ public class ResourceMappingPanel extends Panel {
         Collections.sort(choices);
         toBeUpdated.setChoices(choices);
     }
-
-    /**
-     * Enable/Disable connObjectKey checkbox.
-     *
-     * @param connObjectKey connObjectKey checkbox.
-     * @param password password checkbox.
-     */
-    private void setConnObjectKey(final AjaxCheckBoxPanel connObjectKey, final 
AjaxCheckBoxPanel password) {
-        if (password.getModelObject()) {
-            connObjectKey.setReadOnly(true);
-            connObjectKey.setModelObject(false);
-        } else {
-            connObjectKey.setReadOnly(false);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9bbd1500/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
index 207a2c7..6901480 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.java
@@ -323,9 +323,9 @@ public class ResourceProvisionPanel extends 
AbstractModalPanel<Serializable> {
                         });
 
                         if (connObjectKeyCount != 1) {
-                            throw new RuntimeException(provision.getAnyType() 
+ ": "
+                            throw new 
IllegalArgumentException(provision.getAnyType() + ": "
                                     + new 
StringResourceModel("connObjectKeyValidation", ResourceProvisionPanel.this).
-                                    getString());
+                                            getString());
                         }
                     }
                 }

Reply via email to