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 2017/07/18 10:22:47 UTC

[04/12] syncope git commit: [SYNCOPE-1164] Realm provisioning now features complete mapping, as Anys

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemContainerTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemContainerTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemContainerTO.java
new file mode 100644
index 0000000..6975b2c
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemContainerTO.java
@@ -0,0 +1,32 @@
+/*
+ * 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.common.lib.to;
+
+import java.util.List;
+
+public interface ItemContainerTO {
+
+    void setConnObjectLink(String connObjectLink);
+
+    boolean setConnObjectKeyItem(ItemTO connObjectKeyItem);
+
+    boolean add(ItemTO item);
+
+    List<ItemTO> getItems();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
new file mode 100644
index 0000000..603b4d3
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ItemTO.java
@@ -0,0 +1,163 @@
+/*
+ * 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.common.lib.to;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+
+@XmlRootElement(name = "item")
+@XmlType
+public class ItemTO extends AbstractBaseBean implements EntityTO {
+
+    private static final long serialVersionUID = 2983498836767176862L;
+
+    private String key;
+
+    /**
+     * Attribute schema to be mapped. Consider that we can associate tha same attribute schema more than once, with
+     * different aliases, to different resource attributes.
+     */
+    private String intAttrName;
+
+    /**
+     * External resource's field to be mapped.
+     */
+    private String extAttrName;
+
+    /**
+     * Specify if the mapped target resource's field is the key.
+     */
+    private boolean connObjectKey;
+
+    /**
+     * Specify if the mapped target resource's field is the password.
+     */
+    private boolean password;
+
+    /**
+     * Specify if the mapped target resource's field is nullable.
+     */
+    private String mandatoryCondition = "false";
+
+    /**
+     * Mapping purposes.
+     */
+    private MappingPurpose purpose;
+
+    /**
+     * (Optional) JEXL expression to apply to values before propagation.
+     */
+    private String propagationJEXLTransformer;
+
+    /**
+     * (Optional) JEXL expression to apply to values before pull.
+     */
+    private String pullJEXLTransformer;
+
+    private final List<String> transformerClassNames = new ArrayList<>();
+
+    public boolean isConnObjectKey() {
+        return connObjectKey;
+    }
+
+    public void setConnObjectKey(final boolean connObjectKey) {
+        this.connObjectKey = connObjectKey;
+    }
+
+    public String getExtAttrName() {
+        return extAttrName;
+    }
+
+    public void setExtAttrName(final String extAttrName) {
+        this.extAttrName = extAttrName;
+    }
+
+    @Override
+    public String getKey() {
+        return key;
+    }
+
+    @Override
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    public String getMandatoryCondition() {
+        return mandatoryCondition;
+    }
+
+    public void setMandatoryCondition(final String mandatoryCondition) {
+        this.mandatoryCondition = mandatoryCondition;
+    }
+
+    public boolean isPassword() {
+        return password;
+    }
+
+    public void setPassword(final boolean password) {
+        this.password = password;
+    }
+
+    public String getIntAttrName() {
+        return intAttrName;
+    }
+
+    public void setIntAttrName(final String intAttrName) {
+        this.intAttrName = intAttrName;
+    }
+
+    public MappingPurpose getPurpose() {
+        return purpose;
+    }
+
+    public void setPurpose(final MappingPurpose purpose) {
+        this.purpose = purpose;
+    }
+
+    public String getPropagationJEXLTransformer() {
+        return propagationJEXLTransformer;
+    }
+
+    public void setPropagationJEXLTransformer(final String propagationJEXLTransformer) {
+        this.propagationJEXLTransformer = propagationJEXLTransformer;
+    }
+
+    public String getPullJEXLTransformer() {
+        return pullJEXLTransformer;
+    }
+
+    public void setPullJEXLTransformer(final String pullJEXLTransformer) {
+        this.pullJEXLTransformer = pullJEXLTransformer;
+    }
+
+    @XmlElementWrapper(name = "transformerClassNames")
+    @XmlElement(name = "transformerClassName")
+    @JsonProperty("transformerClassNames")
+    public List<String> getTransformerClassNames() {
+        return transformerClassNames;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
deleted file mode 100644
index c078950..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
+++ /dev/null
@@ -1,163 +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.common.lib.to;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.types.MappingPurpose;
-
-@XmlRootElement(name = "mappingItem")
-@XmlType
-public class MappingItemTO extends AbstractBaseBean implements EntityTO {
-
-    private static final long serialVersionUID = 2983498836767176862L;
-
-    private String key;
-
-    /**
-     * Attribute schema to be mapped. Consider that we can associate tha same attribute schema more than once, with
-     * different aliases, to different resource attributes.
-     */
-    private String intAttrName;
-
-    /**
-     * External resource's field to be mapped.
-     */
-    private String extAttrName;
-
-    /**
-     * Specify if the mapped target resource's field is the key.
-     */
-    private boolean connObjectKey;
-
-    /**
-     * Specify if the mapped target resource's field is the password.
-     */
-    private boolean password;
-
-    /**
-     * Specify if the mapped target resource's field is nullable.
-     */
-    private String mandatoryCondition = "false";
-
-    /**
-     * Mapping purposes.
-     */
-    private MappingPurpose purpose;
-
-    /**
-     * (Optional) JEXL expression to apply to values before propagation.
-     */
-    private String propagationJEXLTransformer;
-
-    /**
-     * (Optional) JEXL expression to apply to values before pull.
-     */
-    private String pullJEXLTransformer;
-
-    private final List<String> mappingItemTransformerClassNames = new ArrayList<>();
-
-    public boolean isConnObjectKey() {
-        return connObjectKey;
-    }
-
-    public void setConnObjectKey(final boolean connObjectKey) {
-        this.connObjectKey = connObjectKey;
-    }
-
-    public String getExtAttrName() {
-        return extAttrName;
-    }
-
-    public void setExtAttrName(final String extAttrName) {
-        this.extAttrName = extAttrName;
-    }
-
-    @Override
-    public String getKey() {
-        return key;
-    }
-
-    @Override
-    public void setKey(final String key) {
-        this.key = key;
-    }
-
-    public String getMandatoryCondition() {
-        return mandatoryCondition;
-    }
-
-    public void setMandatoryCondition(final String mandatoryCondition) {
-        this.mandatoryCondition = mandatoryCondition;
-    }
-
-    public boolean isPassword() {
-        return password;
-    }
-
-    public void setPassword(final boolean password) {
-        this.password = password;
-    }
-
-    public String getIntAttrName() {
-        return intAttrName;
-    }
-
-    public void setIntAttrName(final String intAttrName) {
-        this.intAttrName = intAttrName;
-    }
-
-    public MappingPurpose getPurpose() {
-        return purpose;
-    }
-
-    public void setPurpose(final MappingPurpose purpose) {
-        this.purpose = purpose;
-    }
-
-    public String getPropagationJEXLTransformer() {
-        return propagationJEXLTransformer;
-    }
-
-    public void setPropagationJEXLTransformer(final String propagationJEXLTransformer) {
-        this.propagationJEXLTransformer = propagationJEXLTransformer;
-    }
-
-    public String getPullJEXLTransformer() {
-        return pullJEXLTransformer;
-    }
-
-    public void setPullJEXLTransformer(final String pullJEXLTransformer) {
-        this.pullJEXLTransformer = pullJEXLTransformer;
-    }
-
-    @XmlElementWrapper(name = "mappingItemTransformerClassNames")
-    @XmlElement(name = "className")
-    @JsonProperty("mappingItemTransformerClassNames")
-    public List<String> getMappingItemTransformerClassNames() {
-        return mappingItemTransformerClassNames;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
index a9048c7..8fe6224 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
@@ -31,42 +31,44 @@ import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlRootElement(name = "mapping")
 @XmlType
-public class MappingTO extends AbstractBaseBean {
+public class MappingTO extends AbstractBaseBean implements ItemContainerTO {
 
     private static final long serialVersionUID = 8447688036282611118L;
 
     private String connObjectLink;
 
-    private final List<MappingItemTO> items = new ArrayList<>();
+    private final List<ItemTO> items = new ArrayList<>();
 
-    private final List<MappingItemTO> linkingItems = new ArrayList<>();
+    private final List<ItemTO> linkingItems = new ArrayList<>();
 
     public String getConnObjectLink() {
         return connObjectLink;
     }
 
+    @Override
     public void setConnObjectLink(final String connObjectLink) {
         this.connObjectLink = connObjectLink;
     }
 
-    public MappingItemTO getConnObjectKeyItem() {
-        return IterableUtils.find(getItems(), new Predicate<MappingItemTO>() {
+    public ItemTO getConnObjectKeyItem() {
+        return IterableUtils.find(getItems(), new Predicate<ItemTO>() {
 
             @Override
-            public boolean evaluate(final MappingItemTO item) {
+            public boolean evaluate(final ItemTO item) {
                 return item.isConnObjectKey();
             }
         });
     }
 
-    protected boolean addConnObjectKeyItem(final MappingItemTO connObjectItem) {
+    protected boolean addConnObjectKeyItem(final ItemTO connObjectItem) {
         connObjectItem.setMandatoryCondition("true");
         connObjectItem.setConnObjectKey(true);
 
         return this.add(connObjectItem);
     }
 
-    public boolean setConnObjectKeyItem(final MappingItemTO connObjectKeyItem) {
+    @Override
+    public boolean setConnObjectKeyItem(final ItemTO connObjectKeyItem) {
         return connObjectKeyItem == null
                 ? remove(getConnObjectKeyItem())
                 : addConnObjectKeyItem(connObjectKeyItem);
@@ -75,22 +77,24 @@ public class MappingTO extends AbstractBaseBean {
     @XmlElementWrapper(name = "items")
     @XmlElement(name = "item")
     @JsonProperty("items")
-    public List<MappingItemTO> getItems() {
+    @Override
+    public List<ItemTO> getItems() {
         return items;
     }
 
-    public boolean add(final MappingItemTO item) {
+    @Override
+    public boolean add(final ItemTO item) {
         return item == null ? false : this.items.contains(item) || this.items.add(item);
     }
 
-    public boolean remove(final MappingItemTO item) {
+    public boolean remove(final ItemTO item) {
         return this.items.remove(item);
     }
 
     @XmlElementWrapper(name = "linkingItems")
     @XmlElement(name = "item")
     @JsonProperty("linkingItems")
-    public List<MappingItemTO> getLinkingItems() {
+    public List<ItemTO> getLinkingItems() {
         return linkingItems;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/common/lib/src/main/java/org/apache/syncope/common/lib/to/OrgUnitTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/OrgUnitTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/OrgUnitTO.java
index 80743c0..1290c0c 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/OrgUnitTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/OrgUnitTO.java
@@ -18,13 +18,20 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlRootElement(name = "orgUnit")
 @XmlType
-public class OrgUnitTO extends AbstractBaseBean implements EntityTO {
+public class OrgUnitTO extends AbstractBaseBean implements EntityTO, ItemContainerTO {
 
     private static final long serialVersionUID = -1868877794174953177L;
 
@@ -34,10 +41,10 @@ public class OrgUnitTO extends AbstractBaseBean implements EntityTO {
 
     private String syncToken;
 
-    private String extAttrName;
-
     private String connObjectLink;
 
+    private final List<ItemTO> items = new ArrayList<>();
+
     @Override
     public String getKey() {
         return key;
@@ -64,20 +71,53 @@ public class OrgUnitTO extends AbstractBaseBean implements EntityTO {
         this.syncToken = syncToken;
     }
 
-    public String getExtAttrName() {
-        return extAttrName;
-    }
-
-    public void setExtAttrName(final String extAttrName) {
-        this.extAttrName = extAttrName;
-    }
-
     public String getConnObjectLink() {
         return connObjectLink;
     }
 
+    @Override
     public void setConnObjectLink(final String connObjectLink) {
         this.connObjectLink = connObjectLink;
     }
 
+    public ItemTO getConnObjectKeyItem() {
+        return IterableUtils.find(getItems(), new Predicate<ItemTO>() {
+
+            @Override
+            public boolean evaluate(final ItemTO item) {
+                return item.isConnObjectKey();
+            }
+        });
+    }
+
+    protected boolean addConnObjectKeyItem(final ItemTO connObjectItem) {
+        connObjectItem.setMandatoryCondition("true");
+        connObjectItem.setConnObjectKey(true);
+
+        return this.add(connObjectItem);
+    }
+
+    @Override
+    public boolean setConnObjectKeyItem(final ItemTO connObjectKeyItem) {
+        return connObjectKeyItem == null
+                ? remove(getConnObjectKeyItem())
+                : addConnObjectKeyItem(connObjectKeyItem);
+    }
+
+    @XmlElementWrapper(name = "items")
+    @XmlElement(name = "item")
+    @JsonProperty("items")
+    @Override
+    public List<ItemTO> getItems() {
+        return items;
+    }
+
+    @Override
+    public boolean add(final ItemTO item) {
+        return item == null ? false : this.items.contains(item) || this.items.add(item);
+    }
+
+    public boolean remove(final ItemTO item) {
+        return this.items.remove(item);
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index 760b812..4593b77 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -179,19 +179,6 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
         if (resource == null) {
             throw new NotFoundException("Resource '" + key + "'");
         }
-        AnyType anyType = anyTypeDAO.find(anyTypeKey);
-        if (anyType == null) {
-            throw new NotFoundException("AnyType '" + anyTypeKey + "'");
-        }
-        Provision provision = resource.getProvision(anyType);
-        if (provision == null) {
-            throw new NotFoundException("Provision for AnyType '" + anyTypeKey + "' in Resource '" + key + "'");
-        }
-
-        Set<String> effectiveRealms = RealmUtils.getEffective(
-                AuthContextUtils.getAuthorizations().get(StandardEntitlement.RESOURCE_UPDATE),
-                resource.getConnector().getAdminRealm().getFullPath());
-        securityChecks(effectiveRealms, resource.getConnector().getAdminRealm().getFullPath(), resource.getKey());
 
         Connector connector;
         try {
@@ -202,7 +189,30 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
             throw sce;
         }
 
-        provision.setSyncToken(connector.getLatestSyncToken(provision.getObjectClass()));
+        if (SyncopeConstants.REALM_ANYTYPE.equals(anyTypeKey)) {
+            if (resource.getOrgUnit() == null) {
+                throw new NotFoundException("Realm provision not enabled for Resource '" + key + "'");
+            }
+
+            resource.getOrgUnit().setSyncToken(connector.getLatestSyncToken(resource.getOrgUnit().getObjectClass()));
+        } else {
+            AnyType anyType = anyTypeDAO.find(anyTypeKey);
+            if (anyType == null) {
+                throw new NotFoundException("AnyType '" + anyTypeKey + "'");
+            }
+            Provision provision = resource.getProvision(anyType);
+            if (provision == null) {
+                throw new NotFoundException("Provision for AnyType '" + anyTypeKey + "' in Resource '" + key + "'");
+            }
+
+            provision.setSyncToken(connector.getLatestSyncToken(provision.getObjectClass()));
+        }
+
+        Set<String> effectiveRealms = RealmUtils.getEffective(
+                AuthContextUtils.getAuthorizations().get(StandardEntitlement.RESOURCE_UPDATE),
+                resource.getConnector().getAdminRealm().getFullPath());
+        securityChecks(effectiveRealms, resource.getConnector().getAdminRealm().getFullPath(), resource.getKey());
+
         resourceDAO.save(resource);
     }
 
@@ -212,13 +222,23 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
         if (resource == null) {
             throw new NotFoundException("Resource '" + key + "'");
         }
-        AnyType anyType = anyTypeDAO.find(anyTypeKey);
-        if (anyType == null) {
-            throw new NotFoundException("AnyType '" + anyTypeKey + "'");
-        }
-        Provision provision = resource.getProvision(anyType);
-        if (provision == null) {
-            throw new NotFoundException("Provision for AnyType '" + anyTypeKey + "' in Resource '" + key + "'");
+        if (SyncopeConstants.REALM_ANYTYPE.equals(anyTypeKey)) {
+            if (resource.getOrgUnit() == null) {
+                throw new NotFoundException("Realm provision not enabled for Resource '" + key + "'");
+            }
+
+            resource.getOrgUnit().setSyncToken(null);
+        } else {
+            AnyType anyType = anyTypeDAO.find(anyTypeKey);
+            if (anyType == null) {
+                throw new NotFoundException("AnyType '" + anyTypeKey + "'");
+            }
+            Provision provision = resource.getProvision(anyType);
+            if (provision == null) {
+                throw new NotFoundException("Provision for AnyType '" + anyTypeKey + "' in Resource '" + key + "'");
+            }
+
+            provision.setSyncToken(null);
         }
 
         Set<String> effectiveRealms = RealmUtils.getEffective(
@@ -226,7 +246,6 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
                 resource.getConnector().getAdminRealm().getFullPath());
         securityChecks(effectiveRealms, resource.getConnector().getAdminRealm().getFullPath(), resource.getKey());
 
-        provision.setSyncToken(null);
         resourceDAO.save(resource);
     }
 
@@ -364,7 +383,8 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
             }
 
             objectClass = resource.getOrgUnit().getObjectClass();
-            options = MappingUtils.buildOperationOptions(resource.getOrgUnit());
+            options = MappingUtils.buildOperationOptions(
+                    MappingUtils.getPropagationItems(resource.getOrgUnit()).iterator());
         } else {
             Triple<ExternalResource, AnyType, Provision> init = connObjectInit(key, anyTypeKey);
             resource = init.getLeft();

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index c562de9..03635bb 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -223,8 +223,8 @@ public class SyncopeLogic extends AbstractLogic<AbstractBaseBean> {
                 PLATFORM_INFO.getReportletConfs().addAll(implLookup.getClassNames(Type.REPORTLET_CONF));
                 PLATFORM_INFO.getAccountRules().addAll(implLookup.getClassNames(Type.ACCOUNT_RULE_CONF));
                 PLATFORM_INFO.getPasswordRules().addAll(implLookup.getClassNames(Type.PASSWORD_RULE_CONF));
-                PLATFORM_INFO.getMappingItemTransformers().addAll(
-                        implLookup.getClassNames(Type.MAPPING_ITEM_TRANSFORMER));
+                PLATFORM_INFO.getItemTransformers().addAll(
+                        implLookup.getClassNames(Type.ITEM_TRANSFORMER));
                 PLATFORM_INFO.getTaskJobs().addAll(implLookup.getClassNames(Type.TASKJOBDELEGATE));
                 PLATFORM_INFO.getReconciliationFilterBuilders().
                         addAll(implLookup.getClassNames(Type.RECONCILIATION_FILTER_BUILDER));

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
index 8af1d44..2bc1eca 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
@@ -38,7 +38,7 @@ import org.apache.syncope.core.persistence.api.dao.PasswordRuleConfClass;
 import org.apache.syncope.core.persistence.api.dao.Reportlet;
 import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
 import org.apache.syncope.core.provisioning.api.LogicActions;
-import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
 import org.apache.syncope.core.provisioning.api.notification.NotificationRecipientsProvider;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
@@ -46,7 +46,7 @@ import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
 import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
 import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
 import org.apache.syncope.core.provisioning.api.pushpull.ReconciliationFilterBuilder;
-import org.apache.syncope.core.provisioning.java.data.JEXLMappingItemTransformerImpl;
+import org.apache.syncope.core.provisioning.java.data.JEXLItemTransformerImpl;
 import org.apache.syncope.core.provisioning.java.job.GroupMemberProvisionTaskJobDelegate;
 import org.apache.syncope.core.provisioning.java.pushpull.PlainAttrsPullCorrelationRule;
 import org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate;
@@ -113,7 +113,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
         scanner.addIncludeFilter(new AssignableTypeFilter(Reportlet.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(AccountRule.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(PasswordRule.class));
-        scanner.addIncludeFilter(new AssignableTypeFilter(MappingItemTransformer.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(ItemTransformer.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(SchedTaskJobDelegate.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(ReconciliationFilterBuilder.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(LogicActions.class));
@@ -166,10 +166,10 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     }
                 }
 
-                if (MappingItemTransformer.class.isAssignableFrom(clazz) && !isAbstractClazz
-                        && !clazz.equals(JEXLMappingItemTransformerImpl.class)) {
+                if (ItemTransformer.class.isAssignableFrom(clazz) && !isAbstractClazz
+                        && !clazz.equals(JEXLItemTransformerImpl.class)) {
 
-                    classNames.get(Type.MAPPING_ITEM_TRANSFORMER).add(clazz.getName());
+                    classNames.get(Type.ITEM_TRANSFORMER).add(clazz.getName());
                 }
 
                 if (SchedTaskJobDelegate.class.isAssignableFrom(clazz) && !isAbstractClazz

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
index c510677..a81a2d6 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
@@ -34,7 +34,7 @@ public interface ImplementationLookup extends SyncopeLoader {
         REPORTLET_CONF,
         ACCOUNT_RULE_CONF,
         PASSWORD_RULE_CONF,
-        MAPPING_ITEM_TRANSFORMER,
+        ITEM_TRANSFORMER,
         TASKJOBDELEGATE,
         RECONCILIATION_FILTER_BUILDER,
         LOGIC_ACTIONS,

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
index 5cefafb..de23601 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
@@ -34,6 +34,8 @@ public interface RealmDAO extends DAO<Realm> {
 
     Realm findByFullPath(String fullPath);
 
+    List<Realm> findByName(String name);
+
     List<Realm> findByResource(ExternalResource resource);
 
     <T extends Policy> List<Realm> findByPolicy(T policy);

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
index 8b2cc2d..48ce512 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
@@ -133,7 +133,7 @@ public class LinkingMappingItem implements MappingItem {
     }
 
     @Override
-    public List<String> getMappingItemTransformerClassNames() {
+    public List<String> getTransformerClassNames() {
         return Collections.emptyList();
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.java
new file mode 100644
index 0000000..e8bf037
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Item.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.core.persistence.api.entity.resource;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+
+public interface Item extends Entity {
+
+    String getExtAttrName();
+
+    void setExtAttrName(String extAttrName);
+
+    String getIntAttrName();
+
+    void setIntAttrName(String intAttrName);
+
+    String getMandatoryCondition();
+
+    void setMandatoryCondition(String condition);
+
+    MappingPurpose getPurpose();
+
+    void setPurpose(MappingPurpose purpose);
+
+    boolean isConnObjectKey();
+
+    void setConnObjectKey(boolean connObjectKey);
+
+    boolean isPassword();
+
+    void setPassword(boolean password);
+
+    String getPropagationJEXLTransformer();
+
+    void setPropagationJEXLTransformer(String propagationJEXLTransformer);
+
+    String getPullJEXLTransformer();
+
+    void setPullJEXLTransformer(String pullJEXLTransformer);
+
+    List<String> getTransformerClassNames();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Mapping.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Mapping.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Mapping.java
index 5c14f18..92940a0 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Mapping.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/Mapping.java
@@ -27,15 +27,15 @@ public interface Mapping extends Entity {
 
     void setProvision(Provision provision);
 
+    String getConnObjectLink();
+
+    void setConnObjectLink(String connObjectLink);
+
     boolean add(MappingItem item);
 
     MappingItem getConnObjectKeyItem();
 
     void setConnObjectKeyItem(MappingItem item);
 
-    String getConnObjectLink();
-
-    void setConnObjectLink(String connObjectLink);
-
     List<? extends MappingItem> getItems();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
index 461eaa1..24dc15d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
@@ -18,48 +18,10 @@
  */
 package org.apache.syncope.core.persistence.api.entity.resource;
 
-import java.util.List;
-import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.core.persistence.api.entity.Entity;
-
-public interface MappingItem extends Entity {
+public interface MappingItem extends Item {
 
     Mapping getMapping();
 
     void setMapping(Mapping mapping);
 
-    String getExtAttrName();
-
-    void setExtAttrName(String extAttrName);
-
-    String getIntAttrName();
-
-    void setIntAttrName(String intAttrName);
-
-    String getMandatoryCondition();
-
-    void setMandatoryCondition(String condition);
-
-    MappingPurpose getPurpose();
-
-    void setPurpose(MappingPurpose purpose);
-
-    boolean isConnObjectKey();
-
-    void setConnObjectKey(boolean connObjectKey);
-
-    boolean isPassword();
-
-    void setPassword(boolean password);
-
-    String getPropagationJEXLTransformer();
-
-    void setPropagationJEXLTransformer(String propagationJEXLTransformer);
-
-    String getPullJEXLTransformer();
-
-    void setPullJEXLTransformer(String pullJEXLTransformer);
-
-    List<String> getMappingItemTransformerClassNames();
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnit.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnit.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnit.java
index da8bee1..cdb0504 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnit.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnit.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity.resource;
 
+import java.util.List;
 import org.apache.syncope.core.persistence.api.entity.Entity;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.identityconnectors.framework.common.objects.SyncToken;
@@ -38,12 +39,15 @@ public interface OrgUnit extends Entity {
 
     void setSyncToken(SyncToken syncToken);
 
-    String getExtAttrName();
-
-    void setExtAttrName(String extAttrName);
-
     String getConnObjectLink();
 
     void setConnObjectLink(String connObjectLink);
 
+    boolean add(OrgUnitItem item);
+
+    OrgUnitItem getConnObjectKeyItem();
+
+    void setConnObjectKeyItem(OrgUnitItem item);
+
+    List<? extends OrgUnitItem> getItems();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnitItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnitItem.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnitItem.java
new file mode 100644
index 0000000..d25e0bc
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/OrgUnitItem.java
@@ -0,0 +1,26 @@
+/*
+ * 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.core.persistence.api.entity.resource;
+
+public interface OrgUnitItem extends Item {
+
+    OrgUnit getOrgUnit();
+
+    void setOrgUnit(OrgUnit orgUnit);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
index 87cd26f..0f4cb62 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
@@ -63,6 +63,7 @@ public class JPARealmDAO extends AbstractDAO<Realm> implements RealmDAO {
         return result;
     }
 
+    @Transactional(readOnly = true)
     @Override
     public Realm find(final String key) {
         return entityManager().find(JPARealm.class, key);
@@ -118,6 +119,15 @@ public class JPARealmDAO extends AbstractDAO<Realm> implements RealmDAO {
     }
 
     @Override
+    public List<Realm> findByName(final String name) {
+        TypedQuery<Realm> query = entityManager().createQuery("SELECT e FROM " + JPARealm.class.getSimpleName() + " e "
+                + "WHERE e.name=:name", Realm.class);
+        query.setParameter("name", name);
+
+        return query.getResultList();
+    }
+
+    @Override
     public List<Realm> findByResource(final ExternalResource resource) {
         TypedQuery<Realm> query = entityManager().createQuery("SELECT e FROM " + JPARealm.class.getSimpleName() + " e "
                 + "WHERE :resource MEMBER OF e.resources", Realm.class);
@@ -186,6 +196,7 @@ public class JPARealmDAO extends AbstractDAO<Realm> implements RealmDAO {
         return result;
     }
 
+    @Transactional(readOnly = true)
     @Override
     public List<Realm> findAll() {
         return findDescendants(getRoot());

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index 88f4e5a..66894e5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -127,7 +127,9 @@ import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAOrgUnit;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResourceHistoryConf;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAOrgUnitItem;
 
 @Component
 public class JPAEntityFactory implements EntityFactory {
@@ -219,6 +221,8 @@ public class JPAEntityFactory implements EntityFactory {
             result = (E) new JPAMapping();
         } else if (reference.equals(MappingItem.class)) {
             result = (E) new JPAMappingItem();
+        } else if (reference.equals(OrgUnitItem.class)) {
+            result = (E) new JPAOrgUnitItem();
         } else if (reference.equals(GPlainAttr.class)) {
             result = (E) new JPAGPlainAttr();
         } else if (reference.equals(GPlainAttrValue.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/AbstractItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/AbstractItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/AbstractItem.java
new file mode 100644
index 0000000..5bb91b9
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/AbstractItem.java
@@ -0,0 +1,176 @@
+/*
+ * 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.core.persistence.jpa.entity.resource;
+
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.MappedSuperclass;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractGeneratedKeyEntity;
+
+@MappedSuperclass
+public abstract class AbstractItem extends AbstractGeneratedKeyEntity implements Item {
+
+    private static final long serialVersionUID = 5552380143129988272L;
+
+    @NotNull
+    private String intAttrName;
+
+    /**
+     * Target resource's field to be mapped.
+     */
+    @NotNull
+    private String extAttrName;
+
+    /**
+     * Specify if the mapped target resource's field is nullable.
+     */
+    @NotNull
+    private String mandatoryCondition;
+
+    /**
+     * Specify if the mapped target resource's field is the id.
+     */
+    @NotNull
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer connObjectKey;
+
+    /**
+     * Specify if the mapped target resource's field is the password.
+     */
+    @NotNull
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer password;
+
+    @NotNull
+    @Enumerated(EnumType.STRING)
+    private MappingPurpose purpose;
+
+    /**
+     * (Optional) JEXL expression to apply to values before propagation.
+     */
+    @Column(name = "propJEXL")
+    private String propagationJEXLTransformer;
+
+    /**
+     * (Optional) JEXL expression to apply to values before pull.
+     */
+    @Column(name = "pullJEXL")
+    private String pullJEXLTransformer;
+
+    public AbstractItem() {
+        super();
+
+        mandatoryCondition = Boolean.FALSE.toString();
+
+        connObjectKey = getBooleanAsInteger(false);
+        password = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public String getExtAttrName() {
+        return extAttrName;
+    }
+
+    @Override
+    public void setExtAttrName(final String extAttrName) {
+        this.extAttrName = extAttrName;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return mandatoryCondition;
+    }
+
+    @Override
+    public void setMandatoryCondition(final String mandatoryCondition) {
+        this.mandatoryCondition = mandatoryCondition;
+    }
+
+    @Override
+    public String getIntAttrName() {
+        return intAttrName;
+    }
+
+    @Override
+    public void setIntAttrName(final String intAttrName) {
+        this.intAttrName = intAttrName;
+    }
+
+    @Override
+    public boolean isConnObjectKey() {
+        return isBooleanAsInteger(connObjectKey);
+    }
+
+    @Override
+    public void setConnObjectKey(final boolean connObjectKey) {
+        this.connObjectKey = getBooleanAsInteger(connObjectKey);
+    }
+
+    @Override
+    public boolean isPassword() {
+        return isBooleanAsInteger(password);
+    }
+
+    @Override
+    public void setPassword(final boolean password) {
+        this.password = getBooleanAsInteger(password);
+    }
+
+    @Override
+    public MappingPurpose getPurpose() {
+        return purpose;
+    }
+
+    @Override
+    public void setPurpose(final MappingPurpose purpose) {
+        this.purpose = purpose;
+    }
+
+    @Override
+    public String getPropagationJEXLTransformer() {
+        return propagationJEXLTransformer;
+    }
+
+    @Override
+    public void setPropagationJEXLTransformer(final String propagationJEXLTransformer) {
+        this.propagationJEXLTransformer = propagationJEXLTransformer;
+    }
+
+    @Override
+    public String getPullJEXLTransformer() {
+        return pullJEXLTransformer;
+    }
+
+    @Override
+    public void setPullJEXLTransformer(final String pullJEXLTransformer) {
+        this.pullJEXLTransformer = pullJEXLTransformer;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
index 3894994..bac3955 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
@@ -27,7 +27,6 @@ import javax.persistence.FetchType;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
-import javax.validation.constraints.NotNull;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
@@ -44,8 +43,7 @@ public class JPAMapping extends AbstractGeneratedKeyEntity implements Mapping {
 
     public static final String TABLE = "Mapping";
 
-    @NotNull
-    @OneToOne
+    @OneToOne(optional = false)
     private JPAProvision provision;
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "mapping")

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 47dac59..8624a70 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -20,30 +20,22 @@ package org.apache.syncope.core.persistence.jpa.entity.resource;
 
 import java.util.ArrayList;
 import java.util.List;
-import javax.persistence.Basic;
 import javax.persistence.Cacheable;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
 import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
 import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractGeneratedKeyEntity;
 
 @Entity
 @Table(name = JPAMappingItem.TABLE)
 @Cacheable
-public class JPAMappingItem extends AbstractGeneratedKeyEntity implements MappingItem {
+public class JPAMappingItem extends AbstractItem implements MappingItem {
 
     private static final long serialVersionUID = 7383601853619332424L;
 
@@ -52,73 +44,15 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
     @ManyToOne
     private JPAMapping mapping;
 
-    @NotNull
-    private String intAttrName;
-
-    /**
-     * Target resource's field to be mapped.
-     */
-    @NotNull
-    private String extAttrName;
-
-    /**
-     * Specify if the mapped target resource's field is nullable.
-     */
-    @NotNull
-    private String mandatoryCondition;
-
-    /**
-     * Specify if the mapped target resource's field is the id.
-     */
-    @NotNull
-    @Basic
-    @Min(0)
-    @Max(1)
-    private Integer connObjectKey;
-
-    /**
-     * Specify if the mapped target resource's field is the password.
-     */
-    @NotNull
-    @Basic
-    @Min(0)
-    @Max(1)
-    private Integer password;
-
-    @NotNull
-    @Enumerated(EnumType.STRING)
-    private MappingPurpose purpose;
-
-    /**
-     * (Optional) JEXL expression to apply to values before propagation.
-     */
-    @Column(name = "propJEXL")
-    private String propagationJEXLTransformer;
-
-    /**
-     * (Optional) JEXL expression to apply to values before pull.
-     */
-    @Column(name = "pullJEXL")
-    private String pullJEXLTransformer;
-
     /**
      * (Optional) classes for MappingItem transformation.
      */
     @ElementCollection(fetch = FetchType.EAGER)
     @Column(name = "transformerClassName")
-    @CollectionTable(name = "MappingItem_Transformer",
+    @CollectionTable(name = TABLE + "_Transformer",
             joinColumns =
             @JoinColumn(name = "mappingItem_id", referencedColumnName = "id"))
-    private List<String> mappingItemTransformerClassNames = new ArrayList<>();
-
-    public JPAMappingItem() {
-        super();
-
-        mandatoryCondition = Boolean.FALSE.toString();
-
-        connObjectKey = getBooleanAsInteger(false);
-        password = getBooleanAsInteger(false);
-    }
+    private List<String> transformerClassNames = new ArrayList<>();
 
     @Override
     public Mapping getMapping() {
@@ -132,88 +66,7 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
     }
 
     @Override
-    public String getExtAttrName() {
-        return extAttrName;
-    }
-
-    @Override
-    public void setExtAttrName(final String extAttrName) {
-        this.extAttrName = extAttrName;
-    }
-
-    @Override
-    public String getMandatoryCondition() {
-        return mandatoryCondition;
-    }
-
-    @Override
-    public void setMandatoryCondition(final String mandatoryCondition) {
-        this.mandatoryCondition = mandatoryCondition;
+    public List<String> getTransformerClassNames() {
+        return transformerClassNames;
     }
-
-    @Override
-    public String getIntAttrName() {
-        return intAttrName;
-    }
-
-    @Override
-    public void setIntAttrName(final String intAttrName) {
-        this.intAttrName = intAttrName;
-    }
-
-    @Override
-    public boolean isConnObjectKey() {
-        return isBooleanAsInteger(connObjectKey);
-    }
-
-    @Override
-    public void setConnObjectKey(final boolean connObjectKey) {
-        this.connObjectKey = getBooleanAsInteger(connObjectKey);
-    }
-
-    @Override
-    public boolean isPassword() {
-        return isBooleanAsInteger(password);
-    }
-
-    @Override
-    public void setPassword(final boolean password) {
-        this.password = getBooleanAsInteger(password);
-    }
-
-    @Override
-    public MappingPurpose getPurpose() {
-        return purpose;
-    }
-
-    @Override
-    public void setPurpose(final MappingPurpose purpose) {
-        this.purpose = purpose;
-    }
-
-    @Override
-    public String getPropagationJEXLTransformer() {
-        return propagationJEXLTransformer;
-    }
-
-    @Override
-    public void setPropagationJEXLTransformer(final String propagationJEXLTransformer) {
-        this.propagationJEXLTransformer = propagationJEXLTransformer;
-    }
-
-    @Override
-    public String getPullJEXLTransformer() {
-        return pullJEXLTransformer;
-    }
-
-    @Override
-    public void setPullJEXLTransformer(final String pullJEXLTransformer) {
-        this.pullJEXLTransformer = pullJEXLTransformer;
-    }
-
-    @Override
-    public List<String> getMappingItemTransformerClassNames() {
-        return mappingItemTransformerClassNames;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnit.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnit.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnit.java
index 7324bfc..ab4398d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnit.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnit.java
@@ -18,13 +18,21 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.resource;
 
+import java.util.ArrayList;
+import java.util.List;
 import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.Lob;
+import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractGeneratedKeyEntity;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
@@ -50,11 +58,11 @@ public class JPAOrgUnit extends AbstractGeneratedKeyEntity implements OrgUnit {
     private String serializedSyncToken;
 
     @NotNull
-    private String extAttrName;
-
-    @NotNull
     private String connObjectLink;
 
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "orgUnit")
+    private List<JPAOrgUnitItem> items = new ArrayList<>();
+
     @Override
     public ExternalResource getResource() {
         return resource;
@@ -96,23 +104,40 @@ public class JPAOrgUnit extends AbstractGeneratedKeyEntity implements OrgUnit {
     }
 
     @Override
-    public String getExtAttrName() {
-        return extAttrName;
+    public String getConnObjectLink() {
+        return connObjectLink;
     }
 
     @Override
-    public void setExtAttrName(final String extAttrName) {
-        this.extAttrName = extAttrName;
+    public void setConnObjectLink(final String connObjectLink) {
+        this.connObjectLink = connObjectLink;
     }
 
     @Override
-    public String getConnObjectLink() {
-        return connObjectLink;
+    public boolean add(final OrgUnitItem item) {
+        checkType(item, JPAOrgUnitItem.class);
+        return items.contains((JPAOrgUnitItem) item) || items.add((JPAOrgUnitItem) item);
     }
 
     @Override
-    public void setConnObjectLink(final String connObjectLink) {
-        this.connObjectLink = connObjectLink;
+    public List<? extends OrgUnitItem> getItems() {
+        return items;
+    }
+
+    @Override
+    public OrgUnitItem getConnObjectKeyItem() {
+        return IterableUtils.find(getItems(), new Predicate<OrgUnitItem>() {
+
+            @Override
+            public boolean evaluate(final OrgUnitItem item) {
+                return item.isConnObjectKey();
+            }
+        });
     }
 
+    @Override
+    public void setConnObjectKeyItem(final OrgUnitItem item) {
+        item.setConnObjectKey(true);
+        this.add(item);
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
new file mode 100644
index 0000000..e356ff2
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
@@ -0,0 +1,72 @@
+/*
+ * 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.core.persistence.jpa.entity.resource;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Cacheable;
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
+
+@Entity
+@Table(name = JPAOrgUnitItem.TABLE)
+@Cacheable
+public class JPAOrgUnitItem extends AbstractItem implements OrgUnitItem {
+
+    private static final long serialVersionUID = 7872073846646341777L;
+
+    public static final String TABLE = "OrgUnitItem";
+
+    @ManyToOne
+    private JPAOrgUnit orgUnit;
+
+    /**
+     * (Optional) classes for MappingItem transformation.
+     */
+    @ElementCollection(fetch = FetchType.EAGER)
+    @Column(name = "transformerClassName")
+    @CollectionTable(name = TABLE + "_Transformer",
+            joinColumns =
+            @JoinColumn(name = "orgUnitItem_id", referencedColumnName = "id"))
+    private List<String> transformerClassNames = new ArrayList<>();
+
+    @Override
+    public OrgUnit getOrgUnit() {
+        return orgUnit;
+    }
+
+    @Override
+    public void setOrgUnit(final OrgUnit mapping) {
+        checkType(mapping, JPAOrgUnit.class);
+        this.orgUnit = (JPAOrgUnit) mapping;
+    }
+
+    @Override
+    public List<String> getTransformerClassNames() {
+        return transformerClassNames;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
index 80f4d6e..719a240 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.validation.entity;
 
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import javax.validation.ConstraintValidatorContext;
 import org.apache.commons.collections4.IterableUtils;
@@ -26,24 +27,22 @@ import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.types.EntityViolationType;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
-import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
 import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 
 public class ExternalResourceValidator extends AbstractValidator<ExternalResourceCheck, ExternalResource> {
 
-    private boolean isValid(final Mapping mapping, final ConstraintValidatorContext context) {
-        if (mapping == null) {
-            return true;
-        }
-
-        long connObjectKeys = IterableUtils.countMatches(mapping.getItems(), new Predicate<MappingItem>() {
+    private boolean isValid(final List<? extends Item> items, final ConstraintValidatorContext context) {
+        long connObjectKeys = IterableUtils.countMatches(items, new Predicate<Item>() {
 
             @Override
-            public boolean evaluate(final MappingItem item) {
+            public boolean evaluate(final Item item) {
                 return item.isConnObjectKey();
             }
         });
@@ -56,36 +55,22 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
 
         boolean isValid = true;
 
-        long passwords = IterableUtils.countMatches(mapping.getItems(), new Predicate<MappingItem>() {
-
-            @Override
-            public boolean evaluate(final MappingItem item) {
-                return item.isPassword();
-            }
-        });
-        if (passwords > 1) {
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, "One password mapping is allowed at most")).
-                    addPropertyNode("password.size").addConstraintViolation();
-            isValid = false;
-        }
-
-        for (MappingItem item : mapping.getItems()) {
-            for (String className : item.getMappingItemTransformerClassNames()) {
+        for (Item item : items) {
+            for (String className : item.getTransformerClassNames()) {
                 Class<?> actionsClass = null;
                 boolean isAssignable = false;
                 try {
                     actionsClass = Class.forName(className);
-                    isAssignable = MappingItemTransformer.class.isAssignableFrom(actionsClass);
+                    isAssignable = ItemTransformer.class.isAssignableFrom(actionsClass);
                 } catch (Exception e) {
-                    LOG.error("Invalid MappingItemTransformer specified: {}", className, e);
+                    LOG.error("Invalid ItemTransformer specified: {}", className, e);
                 }
 
                 if (actionsClass == null || !isAssignable) {
                     context.buildConstraintViolationWithTemplate(
                             getTemplate(EntityViolationType.InvalidMapping,
-                                    "Invalid mapping item trasformer class name")).
-                            addPropertyNode("mappingItemTransformerClassName").addConstraintViolation();
+                                    "Invalid item trasformer class name")).
+                            addPropertyNode("itemTransformerClassName").addConstraintViolation();
                     isValid = false;
                 }
             }
@@ -94,6 +79,38 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
         return isValid;
     }
 
+    private boolean isValid(final OrgUnit orgUnit, final ConstraintValidatorContext context) {
+        if (orgUnit == null) {
+            return true;
+        }
+
+        return isValid(orgUnit.getItems(), context);
+    }
+
+    private boolean isValid(final Mapping mapping, final ConstraintValidatorContext context) {
+        if (mapping == null) {
+            return true;
+        }
+
+        boolean isValid = true;
+
+        long passwords = IterableUtils.countMatches(mapping.getItems(), new Predicate<MappingItem>() {
+
+            @Override
+            public boolean evaluate(final MappingItem item) {
+                return item.isPassword();
+            }
+        });
+        if (passwords > 1) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, "One password mapping is allowed at most")).
+                    addPropertyNode("password.size").addConstraintViolation();
+            isValid = false;
+        }
+
+        return isValid && isValid(mapping.getItems(), context);
+    }
+
     @Override
     public boolean isValid(final ExternalResource resource, final ConstraintValidatorContext context) {
         context.disableDefaultConstraintViolation();
@@ -138,6 +155,7 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
                 return isValid(provision.getMapping(), context);
             }
         });
+        validMappings &= isValid(resource.getOrgUnit(), context);
 
         if (anyTypes.size() < resource.getProvisions().size()) {
             context.buildConstraintViolationWithTemplate(getTemplate(EntityViolationType.InvalidResource,

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index b88aee1..0e1598e 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -799,10 +799,16 @@ under the License.
                     randomPwdIfNotProvided="1" enforceMandatoryCondition="1" overrideCapabilities="0"
                     propagationPriority="1"
                     createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"
-                    jsonConf='[{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute. Default is \"entryUUID\".","type":"java.lang.String","required":false,"order":21,"confidential":false,"defaultValues":["entryUUID"]},"overridable":true,"values":["entryUUID"]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member.","type":"[Ljava.lang.String;","required":true,"order":7,"confidential":false,"defaultValues":[]},"overridable":true,"values":["o=isp"]}]'/>
+                    jsonConf='[{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute. Default is \"entryUUID\".","type":"java.lang.String","required":false,"order":21,"confidential":false,"defaultValues":["entryUUID"]},"overridable":true,"values":["l"]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when searching the tree. Searches are performed when discovering users from the LDAP server or when looking for the groups of which a user is a member.","type":"[Ljava.lang.String;","required":true,"order":7,"confidential":false,"defaultValues":[]},"overridable":true,"values":["o=isp"]}]'/>
   <OrgUnit id="599a59cf-9a23-4447-9a59-cf9a2334473a" connObjectLink="syncope:fullPath2Dn(fullPath, 'ou') + ',o=isp'"
-           extAttrName="ou" objectClass="organizationalUnit" resource_id="resource-ldap-orgunit"/>
-
+           objectClass="organizationalUnit" resource_id="resource-ldap-orgunit"/>
+  <OrgUnitItem id="5d0e7ad0-9026-42ad-be8a-32539389e7bd" connObjectKey="1" extAttrName="l"
+               intAttrName="fullpath" mandatoryCondition="true" purpose="BOTH"
+               orgUnit_id="599a59cf-9a23-4447-9a59-cf9a2334473a"/>
+  <OrgUnitItem id="1df556d3-bc23-48b7-a09b-fc3794a00019" connObjectKey="0" extAttrName="ou"
+               intAttrName="name" mandatoryCondition="true" purpose="BOTH"
+               orgUnit_id="599a59cf-9a23-4447-9a59-cf9a2334473a"/>
+  
   <ExternalResource id="ws-target-resource-nopropagation" connector_id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b"
                     randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
                     createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
index 8d0be03..daa09e2 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
@@ -22,10 +22,14 @@ import java.util.List;
 import java.util.Set;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.identityconnectors.framework.common.objects.Attribute;
 
@@ -41,6 +45,15 @@ public interface MappingManager {
     String getConnObjectKeyValue(Any<?> any, Provision provision);
 
     /**
+     * Get connObjectKey internal value.
+     *
+     * @param realm realm
+     * @param orgUnit orgUnit information
+     * @return connObjectKey internal value
+     */
+    String getConnObjectKeyValue(Realm realm, OrgUnit orgUnit);
+
+    /**
      * Get attribute values for the given {@link MappingItem} and any object.
      *
      * @param provision provision information
@@ -65,6 +78,15 @@ public interface MappingManager {
             Any<?> any, String password, boolean changePwd, Boolean enable, Provision provision);
 
     /**
+     * Prepare attributes for sending to a connector instance.
+     *
+     * @param realm Realm
+     * @param orgUnit provision information
+     * @return connObjectLink + prepared attributes
+     */
+    Pair<String, Set<Attribute>> prepareAttrs(Realm realm, OrgUnit orgUnit);
+
+    /**
      * Set attribute values, according to the given {@link MappingItem}, to any object from attribute received from
      * connector.
      *
@@ -76,4 +98,14 @@ public interface MappingManager {
      */
     <T extends AnyTO> void setIntValues(MappingItem mapItem, Attribute attr, T anyTO, AnyUtils anyUtils);
 
+    /**
+     * Set attribute values, according to the given {@link OrgUnitItem}, to realm from attribute received from
+     * connector.
+     *
+     * @param orgUnitItem mapping item
+     * @param attr attribute received from connector
+     * @param realmTO realm
+     */
+    void setIntValues(OrgUnitItem orgUnitItem, Attribute attr, RealmTO realmTO);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ItemTransformer.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ItemTransformer.java
new file mode 100644
index 0000000..1ec16c3
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/ItemTransformer.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.core.provisioning.api.data;
+
+import java.util.List;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
+
+/**
+ * Transforms values to be propagated to (or pulling from) external resources right before they leave (or enter)
+ * the Syncope internal storage.
+ *
+ * These transformations are not applied to virtual attribute values.
+ */
+public interface ItemTransformer {
+
+    /**
+     * Invoked while preparing attribute values to be sent out to external resource during propagation.
+     *
+     * @param item mapping item
+     * @param entity entity
+     * @param values original values
+     * @return transformed values
+     */
+    List<PlainAttrValue> beforePropagation(
+            Item item,
+            Entity entity,
+            List<PlainAttrValue> values);
+
+    /**
+     * Invoked while reading attribute values from external resource during pull.
+     *
+     * @param item mapping item
+     * @param entityTO entity
+     * @param values original values
+     * @return transformed values
+     */
+    List<Object> beforePull(
+            Item item,
+            EntityTO entityTO,
+            List<Object> values);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLItemTransformer.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLItemTransformer.java
new file mode 100644
index 0000000..3194454
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLItemTransformer.java
@@ -0,0 +1,30 @@
+/*
+ * 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.core.provisioning.api.data;
+
+/**
+ * {@link ItemTransformer} implementing evaluation of JEXL expression defined for a given
+ * {@link org.apache.syncope.core.persistence.api.entity.resource.MappingItem}.
+ */
+public interface JEXLItemTransformer extends ItemTransformer {
+
+    void setPropagationJEXL(String propagationJEXL);
+
+    void setPullJEXL(String pullJEXL);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLMappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLMappingItemTransformer.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLMappingItemTransformer.java
deleted file mode 100644
index 8717e3d..0000000
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/JEXLMappingItemTransformer.java
+++ /dev/null
@@ -1,30 +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.core.provisioning.api.data;
-
-/**
- * {@link MappingItemTransformer} implementing evaluation of JEXL expression defined for a given
- * {@link org.apache.syncope.core.persistence.api.entity.resource.MappingItem}.
- */
-public interface JEXLMappingItemTransformer extends MappingItemTransformer {
-
-    void setPropagationJEXL(String propagationJEXL);
-
-    void setPullJEXL(String pullJEXL);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/e21971bf/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
deleted file mode 100644
index d8cb012..0000000
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
+++ /dev/null
@@ -1,60 +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.core.provisioning.api.data;
-
-import java.util.List;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-
-/**
- * Transforms values to be propagated to (or pulling from) external resources right before they leave (or enter)
- * the Syncope internal storage.
- *
- * These transformations are not applied to virtual attribute values.
- */
-public interface MappingItemTransformer {
-
-    /**
-     * Invoked while preparing attribute values to be sent out to external resource during propagation.
-     *
-     * @param mappingItem mapping item
-     * @param any any object
-     * @param values original values
-     * @return transformed values
-     */
-    List<PlainAttrValue> beforePropagation(
-            MappingItem mappingItem,
-            Any<?> any,
-            List<PlainAttrValue> values);
-
-    /**
-     * Invoked while reading attribute values from external resource during pull.
-     *
-     * @param mappingItem mapping item
-     * @param anyTO any object
-     * @param values original values
-     * @return transformed values
-     */
-    List<Object> beforePull(
-            MappingItem mappingItem,
-            AnyTO anyTO,
-            List<Object> values);
-}