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:52 UTC

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
index 9666804..b2907c4 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.provisioning.api.pushpull;
 
 import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.identityconnectors.framework.common.objects.SyncDelta;
 import org.quartz.JobExecutionException;
@@ -132,19 +131,18 @@ public interface PullActions extends ProvisioningActions {
      * The entity is updated upon pull in case of the matching rule
      * {@link org.apache.syncope.common.lib.types.MatchingRule#UPDATE} (default matching rule) is applied.
      *
-     * @param <M> concrete any object
      * @param <P> any object modifications
      * @param profile profile of the pull being executed.
      * @param delta retrieved pull information
-     * @param any any object
+     * @param entityTO entity
      * @param anyPatch modification
      * @return pull information used for logging and to be passed to the 'after' method.
      * @throws JobExecutionException in case of generic failure.
      */
-    <M extends AnyTO, P extends AnyPatch> SyncDelta beforeUpdate(
+    <P extends AnyPatch> SyncDelta beforeUpdate(
             ProvisioningProfile<?, ?> profile,
             SyncDelta delta,
-            M any,
+            EntityTO entityTO,
             P anyPatch)
             throws JobExecutionException;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index 38c895e..54ada98 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -23,55 +23,60 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
-import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.core.provisioning.api.utils.policy.InvalidPasswordRuleConf;
-import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
-import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.EntityFactory;
-import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
-import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
-import org.apache.syncope.core.spring.security.Encryptor;
-import org.apache.syncope.core.spring.security.PasswordGenerator;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 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.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 import org.apache.syncope.core.persistence.api.entity.Membership;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Schema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
 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.OrgUnitItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
-import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
+import org.apache.syncope.core.provisioning.api.utils.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.apache.syncope.core.spring.security.Encryptor;
+import org.apache.syncope.core.spring.security.PasswordGenerator;
 import org.identityconnectors.framework.common.FrameworkUtil;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
@@ -82,7 +87,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
-import org.apache.syncope.common.lib.to.GroupableRelatableTO;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 
 @Component
 public class MappingManagerImpl implements MappingManager {
@@ -110,6 +115,9 @@ public class MappingManagerImpl implements MappingManager {
     private GroupDAO groupDAO;
 
     @Autowired
+    private RealmDAO realmDAO;
+
+    @Autowired
     private DerAttrHandler derAttrHandler;
 
     @Autowired
@@ -145,7 +153,7 @@ public class MappingManagerImpl implements MappingManager {
         Set<Attribute> attributes = new HashSet<>();
         String connObjectKey = null;
 
-        for (MappingItem mapItem : MappingUtils.getPropagationMappingItems(provision)) {
+        for (MappingItem mapItem : MappingUtils.getPropagationItems(provision)) {
             LOG.debug("Processing expression '{}'", mapItem.getIntAttrName());
 
             try {
@@ -164,7 +172,7 @@ public class MappingManagerImpl implements MappingManager {
                             attributes.remove(alreadyAdded);
 
                             Set<Object> values = new HashSet<>();
-                            if (alreadyAdded.getValue() != null && !alreadyAdded.getValue().isEmpty()) {
+                            if (CollectionUtils.isNotEmpty(alreadyAdded.getValue())) {
                                 values.addAll(alreadyAdded.getValue());
                             }
 
@@ -198,7 +206,75 @@ public class MappingManagerImpl implements MappingManager {
             }
         }
 
-        return new ImmutablePair<>(connObjectKey, attributes);
+        return Pair.of(connObjectKey, attributes);
+    }
+
+    private String getIntValue(final Realm realm, final OrgUnitItem orgUnitItem) {
+        String value = null;
+        switch (orgUnitItem.getIntAttrName()) {
+            case "key":
+                value = realm.getKey();
+                break;
+
+            case "name":
+                value = realm.getName();
+                break;
+
+            case "fullpath":
+                value = realm.getFullPath();
+                break;
+
+            default:
+        }
+
+        return value;
+    }
+
+    @Override
+    public Pair<String, Set<Attribute>> prepareAttrs(final Realm realm, final OrgUnit orgUnit) {
+        LOG.debug("Preparing resource attributes for {} with orgUnit {}", realm, orgUnit);
+
+        Set<Attribute> attributes = new HashSet<>();
+        String connObjectKey = null;
+
+        for (OrgUnitItem orgUnitItem : MappingUtils.getPropagationItems(orgUnit)) {
+            LOG.debug("Processing expression '{}'", orgUnitItem.getIntAttrName());
+
+            String value = getIntValue(realm, orgUnitItem);
+
+            if (orgUnitItem.isConnObjectKey()) {
+                connObjectKey = value;
+            }
+
+            Attribute alreadyAdded = AttributeUtil.find(orgUnitItem.getExtAttrName(), attributes);
+            if (alreadyAdded == null) {
+                if (value == null) {
+                    attributes.add(AttributeBuilder.build(orgUnitItem.getExtAttrName()));
+                } else {
+                    attributes.add(AttributeBuilder.build(orgUnitItem.getExtAttrName(), value));
+                }
+            } else if (value != null) {
+                attributes.remove(alreadyAdded);
+
+                Set<Object> values = new HashSet<>();
+                if (CollectionUtils.isNotEmpty(alreadyAdded.getValue())) {
+                    values.addAll(alreadyAdded.getValue());
+                }
+                values.add(value);
+
+                attributes.add(AttributeBuilder.build(orgUnitItem.getExtAttrName(), values));
+            }
+        }
+
+        Attribute connObjectKeyExtAttr =
+                AttributeUtil.find(orgUnit.getConnObjectKeyItem().getExtAttrName(), attributes);
+        if (connObjectKeyExtAttr != null) {
+            attributes.remove(connObjectKeyExtAttr);
+            attributes.add(AttributeBuilder.build(orgUnit.getConnObjectKeyItem().getExtAttrName(), connObjectKey));
+        }
+        attributes.add(MappingUtils.evaluateNAME(realm, orgUnit, connObjectKey));
+
+        return Pair.of(connObjectKey, attributes);
     }
 
     /**
@@ -263,7 +339,7 @@ public class MappingManagerImpl implements MappingManager {
             }
 
             if (mapItem.isConnObjectKey()) {
-                result = new ImmutablePair<>(objValues.isEmpty() ? null : objValues.iterator().next().toString(), null);
+                result = Pair.of(objValues.isEmpty() ? null : objValues.iterator().next().toString(), null);
             } else if (mapItem.isPassword() && any instanceof User) {
                 String passwordAttrValue = password;
                 if (StringUtils.isBlank(passwordAttrValue)) {
@@ -286,15 +362,12 @@ public class MappingManagerImpl implements MappingManager {
                 if (passwordAttrValue == null) {
                     result = null;
                 } else {
-                    result = new ImmutablePair<>(
-                            null, AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
+                    result = Pair.of(null, AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
                 }
             } else if (schema != null && schema.isMultivalue()) {
-                result = new ImmutablePair<>(
-                        null, AttributeBuilder.build(mapItem.getExtAttrName(), objValues));
+                result = Pair.of(null, AttributeBuilder.build(mapItem.getExtAttrName(), objValues));
             } else {
-                result = new ImmutablePair<>(
-                        null, objValues.isEmpty()
+                result = Pair.of(null, objValues.isEmpty()
                         ? AttributeBuilder.build(mapItem.getExtAttrName())
                         : AttributeBuilder.build(mapItem.getExtAttrName(), objValues.iterator().next()));
             }
@@ -484,7 +557,7 @@ public class MappingManagerImpl implements MappingManager {
 
         List<PlainAttrValue> transformed = values;
         if (transform) {
-            for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(mapItem)) {
+            for (ItemTransformer transformer : MappingUtils.getItemTransformers(mapItem)) {
                 transformed = transformer.beforePropagation(mapItem, any, transformed);
             }
             LOG.debug("Transformed values: {}", values);
@@ -519,13 +592,21 @@ public class MappingManagerImpl implements MappingManager {
 
     @Transactional(readOnly = true)
     @Override
+    public String getConnObjectKeyValue(final Realm realm, final OrgUnit orgUnit) {
+        OrgUnitItem orgUnitItem = orgUnit.getConnObjectKeyItem();
+
+        return getIntValue(realm, orgUnitItem);
+    }
+
+    @Transactional(readOnly = true)
+    @Override
     public void setIntValues(
             final MappingItem mapItem, final Attribute attr, final AnyTO anyTO, final AnyUtils anyUtils) {
 
         List<Object> values = null;
         if (attr != null) {
             values = attr.getValue();
-            for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(mapItem)) {
+            for (ItemTransformer transformer : MappingUtils.getItemTransformers(mapItem)) {
                 values = transformer.beforePull(mapItem, anyTO, values);
             }
         }
@@ -679,4 +760,36 @@ public class MappingManagerImpl implements MappingManager {
             }
         }
     }
+
+    @Override
+    public void setIntValues(final OrgUnitItem orgUnitItem, final Attribute attr, final RealmTO realmTO) {
+        List<Object> values = null;
+        if (attr != null) {
+            values = attr.getValue();
+            for (ItemTransformer transformer : MappingUtils.getItemTransformers(orgUnitItem)) {
+                values = transformer.beforePull(orgUnitItem, realmTO, values);
+            }
+        }
+
+        if (values != null && !values.isEmpty() && values.get(0) != null) {
+            switch (orgUnitItem.getIntAttrName()) {
+                case "name":
+                    realmTO.setName(values.get(0).toString());
+                    break;
+
+                case "fullpath":
+                    String parentFullPath = StringUtils.substringBeforeLast(values.get(0).toString(), "/");
+                    Realm parent = realmDAO.findByFullPath(parentFullPath);
+                    if (parent == null) {
+                        LOG.warn("Could not find Realm with path {}, ignoring", parentFullPath);
+                    } else {
+                        realmTO.setParent(parent.getFullPath());
+                    }
+                    break;
+
+                default:
+            }
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index b25712b..108b530 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -226,7 +226,7 @@ abstract class AbstractAnyDataBinder {
     private List<String> evaluateMandatoryCondition(final Provision provision, final Any<?> any) {
         List<String> missingAttrNames = new ArrayList<>();
 
-        for (MappingItem mapItem : MappingUtils.getPropagationMappingItems(provision)) {
+        for (MappingItem mapItem : MappingUtils.getPropagationItems(provision)) {
             IntAttrName intAttrName =
                     intAttrNameParser.parse(mapItem.getIntAttrName(), provision.getAnyType().getKind());
             if (intAttrName.getSchemaType() != null) {
@@ -346,7 +346,7 @@ abstract class AbstractAnyDataBinder {
         }
 
         for (ExternalResource resource : resources) {
-            for (MappingItem item : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+            for (MappingItem item : MappingUtils.getPropagationItems(resource.getProvision(any.getType()))) {
                 if (schema.getKey().equals(item.getIntAttrName())) {
                     propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultItemTransformer.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultItemTransformer.java
new file mode 100644
index 0000000..230962a
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultItemTransformer.java
@@ -0,0 +1,47 @@
+/*
+ * 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.java.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;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Default (empty) implementation of {@link ItemTransformer}.
+ */
+@Transactional(readOnly = true)
+public class DefaultItemTransformer implements ItemTransformer {
+
+    @Override
+    public List<PlainAttrValue> beforePropagation(
+            final Item item, final Entity entity, final List<PlainAttrValue> values) {
+
+        return values;
+    }
+
+    @Override
+    public List<Object> beforePull(final Item item, final EntityTO entityTO, final List<Object> values) {
+        return values;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
deleted file mode 100644
index 37a471c..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
+++ /dev/null
@@ -1,54 +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.java.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;
-import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
-import org.springframework.transaction.annotation.Transactional;
-
-/**
- * Default (empty) implementation of {@link MappingItemTransformer}.
- */
-public class DefaultMappingItemTransformer implements MappingItemTransformer {
-
-    @Transactional(readOnly = true)
-    @Override
-    public List<PlainAttrValue> beforePropagation(
-            final MappingItem mappingItem,
-            final Any<?> any,
-            final List<PlainAttrValue> values) {
-
-        return values;
-    }
-
-    @Transactional(readOnly = true)
-    @Override
-    public List<Object> beforePull(
-            final MappingItem mappingItem,
-            final AnyTO anyTO,
-            final List<Object> values) {
-
-        return values;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLItemTransformerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLItemTransformerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLItemTransformerImpl.java
new file mode 100644
index 0000000..ae31618
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLItemTransformerImpl.java
@@ -0,0 +1,102 @@
+/*
+ * 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.java.data;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.MapContext;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+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;
+import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
+import org.apache.syncope.core.provisioning.api.data.JEXLItemTransformer;
+
+public class JEXLItemTransformerImpl extends DefaultItemTransformer implements JEXLItemTransformer {
+
+    private String propagationJEXL;
+
+    private String pullJEXL;
+
+    @Override
+    public void setPropagationJEXL(final String propagationJEXL) {
+        this.propagationJEXL = propagationJEXL;
+    }
+
+    @Override
+    public void setPullJEXL(final String pullJEXL) {
+        this.pullJEXL = pullJEXL;
+    }
+
+    @Override
+    public List<PlainAttrValue> beforePropagation(
+            final Item item,
+            final Entity entity,
+            final List<PlainAttrValue> values) {
+
+        if (StringUtils.isNotBlank(propagationJEXL) && values != null) {
+            for (PlainAttrValue value : values) {
+                JexlContext jexlContext = new MapContext();
+                if (entity != null) {
+                    JexlUtils.addFieldsToContext(entity, jexlContext);
+                    if (entity instanceof Any) {
+                        JexlUtils.addPlainAttrsToContext(((Any<?>) entity).getPlainAttrs(), jexlContext);
+                        JexlUtils.addDerAttrsToContext(((Any<?>) entity), jexlContext);
+                    }
+                }
+                jexlContext.set("value", value.getValueAsString());
+
+                value.setStringValue(JexlUtils.evaluate(propagationJEXL, jexlContext));
+            }
+
+            return values;
+        }
+
+        return super.beforePropagation(item, entity, values);
+    }
+
+    @Override
+    public List<Object> beforePull(
+            final Item item,
+            final EntityTO entityTO,
+            final List<Object> values) {
+
+        if (StringUtils.isNotBlank(pullJEXL) && values != null) {
+            List<Object> newValues = new ArrayList<>(values.size());
+            for (Object value : values) {
+                JexlContext jexlContext = new MapContext();
+                jexlContext.set("value", value);
+                if (entityTO instanceof AnyTO) {
+                    newValues.add(JexlUtils.evaluate(pullJEXL, (AnyTO) entityTO, jexlContext));
+                } else {
+                    newValues.add(JexlUtils.evaluate(pullJEXL, jexlContext));
+                }
+            }
+
+            return newValues;
+        }
+
+        return super.beforePull(item, entityTO, values);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformerImpl.java
deleted file mode 100644
index 07618aa..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformerImpl.java
+++ /dev/null
@@ -1,99 +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.java.data;
-
-import java.util.ArrayList;
-import java.util.List;
-import org.apache.commons.jexl3.JexlContext;
-import org.apache.commons.jexl3.MapContext;
-import org.apache.commons.lang3.StringUtils;
-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;
-import org.apache.syncope.core.provisioning.api.data.JEXLMappingItemTransformer;
-import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
-
-public class JEXLMappingItemTransformerImpl
-        extends DefaultMappingItemTransformer implements JEXLMappingItemTransformer {
-
-    private String propagationJEXL;
-
-    private String pullJEXL;
-
-    @Override
-    public void setPropagationJEXL(final String propagationJEXL) {
-        this.propagationJEXL = propagationJEXL;
-    }
-
-    @Override
-    public void setPullJEXL(final String pullJEXL) {
-        this.pullJEXL = pullJEXL;
-    }
-
-    @Override
-    public List<PlainAttrValue> beforePropagation(
-            final MappingItem mappingItem,
-            final Any<?> any,
-            final List<PlainAttrValue> values) {
-
-        if (StringUtils.isNotBlank(propagationJEXL) && values != null) {
-            for (PlainAttrValue value : values) {
-                JexlContext jexlContext = new MapContext();
-                if (any != null) {
-                    JexlUtils.addFieldsToContext(any, jexlContext);
-                    JexlUtils.addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
-                    JexlUtils.addDerAttrsToContext(any, jexlContext);
-                }
-                jexlContext.set("value", value.getValueAsString());
-
-                value.setStringValue(JexlUtils.evaluate(propagationJEXL, jexlContext));
-            }
-
-            return values;
-        }
-
-        return super.beforePropagation(mappingItem, any, values);
-    }
-
-    @Override
-    public List<Object> beforePull(
-            final MappingItem mappingItem,
-            final AnyTO anyTO,
-            final List<Object> values) {
-
-        if (StringUtils.isNotBlank(pullJEXL) && values != null) {
-            List<Object> newValues = new ArrayList<>(values.size());
-            for (Object value : values) {
-                JexlContext jexlContext = new MapContext();
-                jexlContext.set("value", value);
-                if (anyTO == null) {
-                    newValues.add(JexlUtils.evaluate(pullJEXL, jexlContext));
-                } else {
-                    newValues.add(JexlUtils.evaluate(pullJEXL, anyTO, jexlContext));
-                }
-            }
-
-            return newValues;
-        }
-
-        return super.beforePull(mappingItem, anyTO, values);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index e6293cf..ba6da63 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -27,7 +27,8 @@ import org.apache.commons.collections4.IteratorUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
-import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.ItemContainerTO;
+import org.apache.syncope.common.lib.to.ItemTO;
 import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.OrgUnitTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
@@ -58,7 +59,9 @@ import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
+import org.apache.syncope.core.persistence.api.entity.resource.Item;
 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.apache.syncope.core.provisioning.java.IntAttrNameParser;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
@@ -76,7 +79,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
     private static final Logger LOG = LoggerFactory.getLogger(ResourceDataBinder.class);
 
-    private static final String[] MAPPINGITEM_IGNORE_PROPERTIES = { "key", "mapping" };
+    private static final String[] ITEM_IGNORE_PROPERTIES = { "key", "mapping" };
 
     @Autowired
     private AnyTypeDAO anyTypeDAO;
@@ -126,7 +129,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             List<ExternalResourceHistoryConf> history = resourceHistoryConfDAO.findByEntity(resource);
             long maxHistorySize = confDAO.find("resource.conf.history.size", "10").getValues().get(0).getLongValue();
             if (maxHistorySize < history.size()) {
-            // always remove the last item since history was obtained  by a query with ORDER BY creation DESC
+                // always remove the last item since history was obtained  by a query with ORDER BY creation DESC
                 for (int i = 0; i < history.size() - maxHistorySize; i++) {
                     resourceHistoryConfDAO.delete(history.get(history.size() - 1).getKey());
                 }
@@ -275,19 +278,60 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             }
             orgUnit.setObjectClass(new ObjectClass(orgUnitTO.getObjectClass()));
 
-            if (orgUnitTO.getExtAttrName() == null) {
-                SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidOrgUnit);
-                sce.getElements().add("Null extAttrName");
-                throw sce;
-            }
-            orgUnit.setExtAttrName(orgUnitTO.getExtAttrName());
-
             if (orgUnitTO.getConnObjectLink() == null) {
                 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidOrgUnit);
                 sce.getElements().add("Null connObjectLink");
                 throw sce;
             }
             orgUnit.setConnObjectLink(orgUnitTO.getConnObjectLink());
+
+            SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
+            SyncopeClientException invalidMapping = SyncopeClientException.build(
+                    ClientExceptionType.InvalidMapping);
+            SyncopeClientException requiredValuesMissing = SyncopeClientException.build(
+                    ClientExceptionType.RequiredValuesMissing);
+
+            orgUnit.getItems().clear();
+            for (ItemTO itemTO : orgUnitTO.getItems()) {
+                if (itemTO == null) {
+                    LOG.error("Null {}", ItemTO.class.getSimpleName());
+                    invalidMapping.getElements().add("Null " + ItemTO.class.getSimpleName());
+                } else if (itemTO.getIntAttrName() == null) {
+                    requiredValuesMissing.getElements().add("intAttrName");
+                    scce.addException(requiredValuesMissing);
+                } else {
+                    if (!"name".equals(itemTO.getIntAttrName()) && !"fullpath".equals(itemTO.getIntAttrName())) {
+                        LOG.error("Only 'name' and 'fullpath' are supported for Realms");
+                        invalidMapping.getElements().add("Only 'name' and 'fullpath' are supported for Realms");
+                    } else {
+                        // no mandatory condition implies mandatory condition false
+                        if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null
+                                ? "false" : itemTO.getMandatoryCondition())) {
+
+                            SyncopeClientException invalidMandatoryCondition = SyncopeClientException.build(
+                                    ClientExceptionType.InvalidValues);
+                            invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition());
+                            scce.addException(invalidMandatoryCondition);
+                        }
+
+                        OrgUnitItem item = entityFactory.newEntity(OrgUnitItem.class);
+                        BeanUtils.copyProperties(itemTO, item, ITEM_IGNORE_PROPERTIES);
+                        item.setOrgUnit(orgUnit);
+                        if (item.isConnObjectKey()) {
+                            orgUnit.setConnObjectKeyItem(item);
+                        } else {
+                            orgUnit.add(item);
+                        }
+
+                    }
+                }
+            }
+            if (!invalidMapping.getElements().isEmpty()) {
+                scce.addException(invalidMapping);
+            }
+            if (scce.hasExceptions()) {
+                throw scce;
+            }
         }
 
         resource.setCreateTraceLevel(resourceTO.getCreateTraceLevel());
@@ -328,10 +372,10 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
         SyncopeClientException requiredValuesMissing = SyncopeClientException.build(
                 ClientExceptionType.RequiredValuesMissing);
 
-        for (MappingItemTO itemTO : mappingTO.getItems()) {
+        for (ItemTO itemTO : mappingTO.getItems()) {
             if (itemTO == null) {
-                LOG.error("Null {}", MappingItemTO.class.getSimpleName());
-                invalidMapping.getElements().add("Null " + MappingItemTO.class.getSimpleName());
+                LOG.error("Null {}", ItemTO.class.getSimpleName());
+                invalidMapping.getElements().add("Null " + ItemTO.class.getSimpleName());
             } else if (itemTO.getIntAttrName() == null) {
                 requiredValuesMissing.getElements().add("intAttrName");
                 scce.addException(requiredValuesMissing);
@@ -377,7 +421,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                         }
 
                         MappingItem item = entityFactory.newEntity(MappingItem.class);
-                        BeanUtils.copyProperties(itemTO, item, MAPPINGITEM_IGNORE_PROPERTIES);
+                        BeanUtils.copyProperties(itemTO, item, ITEM_IGNORE_PROPERTIES);
                         item.setMapping(mapping);
                         if (item.isConnObjectKey()) {
                             if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
@@ -442,18 +486,16 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
         }
     }
 
-    private void populateMappingTO(final Mapping mapping, final MappingTO mappingTO) {
-        mappingTO.setConnObjectLink(mapping.getConnObjectLink());
-
-        for (MappingItem item : mapping.getItems()) {
-            MappingItemTO itemTO = new MappingItemTO();
+    private void populateItems(final List<? extends Item> items, final ItemContainerTO containerTO) {
+        for (Item item : items) {
+            ItemTO itemTO = new ItemTO();
             itemTO.setKey(item.getKey());
-            BeanUtils.copyProperties(item, itemTO, MAPPINGITEM_IGNORE_PROPERTIES);
+            BeanUtils.copyProperties(item, itemTO, ITEM_IGNORE_PROPERTIES);
 
             if (itemTO.isConnObjectKey()) {
-                mappingTO.setConnObjectKeyItem(itemTO);
+                containerTO.setConnObjectKeyItem(itemTO);
             } else {
-                mappingTO.add(itemTO);
+                containerTO.add(itemTO);
             }
         }
     }
@@ -484,7 +526,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             if (provision.getMapping() != null) {
                 MappingTO mappingTO = new MappingTO();
                 provisionTO.setMapping(mappingTO);
-                populateMappingTO(provision.getMapping(), mappingTO);
+                mappingTO.setConnObjectLink(provision.getMapping().getConnObjectLink());
+                populateItems(provision.getMapping().getItems(), mappingTO);
             }
 
             for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
@@ -492,9 +535,9 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
                 MappingItem linkingMappingItem = virSchema.asLinkingMappingItem();
 
-                MappingItemTO itemTO = new MappingItemTO();
+                ItemTO itemTO = new ItemTO();
                 itemTO.setKey(linkingMappingItem.getKey());
-                BeanUtils.copyProperties(linkingMappingItem, itemTO, MAPPINGITEM_IGNORE_PROPERTIES);
+                BeanUtils.copyProperties(linkingMappingItem, itemTO, ITEM_IGNORE_PROPERTIES);
 
                 provisionTO.getMapping().getLinkingItems().add(itemTO);
             }
@@ -509,8 +552,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             orgUnitTO.setKey(orgUnit.getKey());
             orgUnitTO.setObjectClass(orgUnit.getObjectClass().getObjectClassValue());
             orgUnitTO.setSyncToken(orgUnit.getSerializedSyncToken());
-            orgUnitTO.setExtAttrName(orgUnit.getExtAttrName());
             orgUnitTO.setConnObjectLink(orgUnit.getConnObjectLink());
+            populateItems(orgUnit.getItems(), orgUnitTO);
 
             resourceTO.setOrgUnit(orgUnitTO);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
index a14ba2f..b24c85c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
@@ -51,9 +51,7 @@ import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
 import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
-import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
-import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -69,15 +67,12 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationException
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.exceptions.ConnectorException;
 import org.identityconnectors.framework.common.objects.Attribute;
-import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
 import org.identityconnectors.framework.common.objects.Name;
 import org.identityconnectors.framework.common.objects.ObjectClass;
-import org.identityconnectors.framework.common.objects.ResultsHandler;
 import org.identityconnectors.framework.common.objects.Uid;
-import org.identityconnectors.framework.common.objects.filter.EqualsFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -120,12 +115,6 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
     protected GroupDAO groupDAO;
 
     /**
-     * Realm DAO.
-     */
-    @Autowired
-    protected RealmDAO realmDAO;
-
-    /**
      * Task DAO.
      */
     @Autowired
@@ -396,7 +385,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
                     ? null
                     : orgUnit == null
                             ? getRemoteObject(task, connector, provision, false)
-                            : getRemoteObject(task, connector, orgUnit);
+                            : getRemoteObject(task, connector, orgUnit, false);
 
             for (PropagationActions action : actions) {
                 action.before(task, beforeObj);
@@ -463,7 +452,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
                             ? null
                             : orgUnit == null
                                     ? getRemoteObject(task, connector, provision, true)
-                                    : getRemoteObject(task, connector, orgUnit);
+                                    : getRemoteObject(task, connector, orgUnit, true);
                 } catch (Exception ignore) {
                     // ignore exception
                     LOG.error("Error retrieving after object", ignore);
@@ -621,7 +610,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
             obj = connector.getObject(new ObjectClass(task.getObjectClassName()),
                     new Uid(connObjectKey),
                     MappingUtils.buildOperationOptions(IteratorUtils.chainedIterator(
-                            MappingUtils.getPropagationMappingItems(provision).iterator(),
+                            MappingUtils.getPropagationItems(provision).iterator(),
                             linkingMappingItems.iterator())));
 
             for (MappingItem item : linkingMappingItems) {
@@ -650,37 +639,31 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
      * @param connector connector facade proxy.
      * @param task current propagation task.
      * @param orgUnit orgUnit
+     * @param latest 'FALSE' to retrieve object using old connObjectKey if not null.
      * @return remote connector object.
      */
     protected ConnectorObject getRemoteObject(
             final PropagationTask task,
             final Connector connector,
-            final OrgUnit orgUnit) {
+            final OrgUnit orgUnit,
+            final boolean latest) {
 
-        Realm realm = realmDAO.find(task.getEntityKey());
-        if (realm == null) {
-            return null;
-        }
+        String connObjectKey = latest || task.getOldConnObjectKey() == null
+                ? task.getConnObjectKey()
+                : task.getOldConnObjectKey();
 
-        final ConnectorObject[] obj = new ConnectorObject[1];
+        ConnectorObject obj = null;
         try {
-            connector.search(new ObjectClass(task.getObjectClassName()),
-                    new EqualsFilter(AttributeBuilder.build(orgUnit.getExtAttrName(), realm.getName())),
-                    new ResultsHandler() {
-
-                @Override
-                public boolean handle(final ConnectorObject connectorObject) {
-                    obj[0] = connectorObject;
-                    return false;
-                }
-            }, MappingUtils.buildOperationOptions(orgUnit));
+            obj = connector.getObject(new ObjectClass(task.getObjectClassName()),
+                    new Uid(connObjectKey),
+                    MappingUtils.buildOperationOptions(MappingUtils.getPropagationItems(orgUnit).iterator()));
         } catch (TimeoutException toe) {
             LOG.debug("Request timeout", toe);
             throw toe;
         } catch (RuntimeException ignore) {
-            LOG.debug("While resolving {}", task.getConnObjectKey(), ignore);
+            LOG.debug("While resolving {}", connObjectKey, ignore);
         }
 
-        return obj[0];
+        return obj;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
index f1ec799..c826f6b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
@@ -28,8 +28,6 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
-import org.apache.commons.jexl3.JexlContext;
-import org.apache.commons.jexl3.MapContext;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
@@ -68,7 +66,6 @@ import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
-import org.identityconnectors.framework.common.objects.Name;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -204,8 +201,8 @@ public class PropagationManagerImpl implements PropagationManager {
         return getUpdateTasks(
                 userDAO.authFind(wfResult.getResult().getKey().getKey()),
                 wfResult.getResult().getKey().getPassword() == null
-                        ? null
-                        : wfResult.getResult().getKey().getPassword().getValue(),
+                ? null
+                : wfResult.getResult().getKey().getPassword().getValue(),
                 changePwd,
                 wfResult.getResult().getValue(),
                 wfResult.getPropByRes(),
@@ -381,9 +378,9 @@ public class PropagationManagerImpl implements PropagationManager {
         for (Map.Entry<String, ResourceOperation> entry : propByRes.asMap().entrySet()) {
             ExternalResource resource = resourceDAO.find(entry.getKey());
             Provision provision = resource == null ? null : resource.getProvision(any.getType());
-            List<MappingItem> mappingItems = provision == null
+            List<? extends MappingItem> mappingItems = provision == null
                     ? Collections.<MappingItem>emptyList()
-                    : MappingUtils.getPropagationMappingItems(provision);
+                    : MappingUtils.getPropagationItems(provision);
 
             if (resource == null) {
                 LOG.error("Invalid resource name specified: {}, ignoring...", entry.getKey());
@@ -484,28 +481,11 @@ public class PropagationManagerImpl implements PropagationManager {
                 task.setObjectClassName(orgUnit.getObjectClass().getObjectClassValue());
                 task.setEntityKey(realm.getKey());
                 task.setOperation(entry.getValue());
+                task.setOldConnObjectKey(propByRes.getOldConnObjectKey(resource.getKey()));
 
-                Set<Attribute> preparedAttrs = new HashSet<>();
-                preparedAttrs.add(AttributeBuilder.build(orgUnit.getExtAttrName(), realm.getName()));
-
-                JexlContext jexlContext = new MapContext();
-                JexlUtils.addFieldsToContext(realm, jexlContext);
-                String evalConnObjectLink = JexlUtils.evaluate(orgUnit.getConnObjectLink(), jexlContext);
-                if (StringUtils.isBlank(evalConnObjectLink)) {
-                    // add connObjectKey as __NAME__ attribute ...
-                    LOG.debug("Add connObjectKey [{}] as __NAME__", realm.getName());
-                    preparedAttrs.add(new Name(realm.getName()));
-                } else {
-                    LOG.debug("Add connObjectLink [{}] as __NAME__", evalConnObjectLink);
-                    preparedAttrs.add(new Name(evalConnObjectLink));
-
-                    // connObjectKey not propagated: it will be used to set the value for __UID__ attribute
-                    LOG.debug("connObjectKey will be used just as __UID__ attribute");
-                }
-
-                task.setConnObjectKey(realm.getName());
-
-                task.setAttributes(preparedAttrs);
+                Pair<String, Set<Attribute>> preparedAttrs = mappingManager.prepareAttrs(realm, orgUnit);
+                task.setConnObjectKey(preparedAttrs.getKey());
+                task.setAttributes(preparedAttrs.getValue());
 
                 tasks.add(task);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
index af8466c..1e93b92 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPullResultHandler.java
@@ -178,7 +178,6 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
         }
 
         AnyTO anyTO = connObjectUtils.getAnyTO(delta.getObject(), profile.getTask(), provision, anyUtils);
-
         anyTO.getResources().add(profile.getTask().getResource().getKey());
 
         ProvisioningReport result = new ProvisioningReport();
@@ -324,9 +323,10 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                 result.setName(getName(before));
             }
 
-            Result resultStatus;
-            Object output;
             if (!profile.isDryRun()) {
+                Result resultStatus;
+                Object output;
+
                 if (before == null) {
                     resultStatus = Result.FAILURE;
                     output = null;
@@ -395,16 +395,13 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             return Collections.<ProvisioningReport>emptyList();
         }
 
-        LOG.debug("About to update {}", anys);
+        LOG.debug("About to deprovision {}", anys);
 
-        final List<ProvisioningReport> updResults = new ArrayList<>();
+        final List<ProvisioningReport> results = new ArrayList<>();
 
         for (String key : anys) {
             LOG.debug("About to unassign resource {}", key);
 
-            Object output;
-            Result resultStatus;
-
             ProvisioningReport result = new ProvisioningReport();
             result.setOperation(ResourceOperation.DELETE);
             result.setAnyType(provision.getAnyType().getKey());
@@ -419,6 +416,9 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             }
 
             if (!profile.isDryRun()) {
+                Object output;
+                Result resultStatus;
+
                 if (before == null) {
                     resultStatus = Result.FAILURE;
                     output = null;
@@ -487,10 +487,10 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         ? MatchingRule.toEventName(MatchingRule.UNASSIGN)
                         : MatchingRule.toEventName(MatchingRule.DEPROVISION), resultStatus, before, output, delta);
             }
-            updResults.add(result);
+            results.add(result);
         }
 
-        return updResults;
+        return results;
     }
 
     protected List<ProvisioningReport> link(
@@ -510,14 +510,11 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         LOG.debug("About to update {}", anys);
 
-        final List<ProvisioningReport> updResults = new ArrayList<>();
+        final List<ProvisioningReport> results = new ArrayList<>();
 
         for (String key : anys) {
             LOG.debug("About to unassign resource {}", key);
 
-            Object output;
-            Result resultStatus;
-
             ProvisioningReport result = new ProvisioningReport();
             result.setOperation(ResourceOperation.NONE);
             result.setAnyType(provision.getAnyType().getKey());
@@ -532,6 +529,9 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             }
 
             if (!profile.isDryRun()) {
+                Object output;
+                Result resultStatus;
+
                 if (before == null) {
                     resultStatus = Result.FAILURE;
                     output = null;
@@ -585,10 +585,10 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                         ? MatchingRule.toEventName(MatchingRule.UNLINK)
                         : MatchingRule.toEventName(MatchingRule.LINK), resultStatus, before, output, delta);
             }
-            updResults.add(result);
+            results.add(result);
         }
 
-        return updResults;
+        return results;
     }
 
     protected List<ProvisioningReport> delete(
@@ -605,7 +605,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
 
         LOG.debug("About to delete {}", anys);
 
-        List<ProvisioningReport> delResults = new ArrayList<>();
+        List<ProvisioningReport> results = new ArrayList<>();
 
         SyncDelta workingDelta = delta;
         for (String key : anys) {
@@ -648,7 +648,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
                     finalize(ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, workingDelta);
                 }
 
-                delResults.add(result);
+                results.add(result);
             } catch (NotFoundException e) {
                 LOG.error("Could not find {} {}", provision.getAnyType().getKey(), key, e);
             } catch (DelegatedAdministrationException e) {
@@ -658,7 +658,7 @@ public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHan
             }
         }
 
-        return delResults;
+        return results;
     }
 
     protected ProvisioningReport ignore(

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
index cd2aaf3..d5b2093 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DBPasswordPullActions.java
@@ -23,7 +23,6 @@ import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.patch.PasswordPatch;
 import org.apache.syncope.common.lib.patch.UserPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -76,10 +75,10 @@ public class DBPasswordPullActions extends DefaultPullActions {
 
     @Transactional(readOnly = true)
     @Override
-    public <A extends AnyTO, M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> SyncDelta beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
-            final A any,
+            final EntityTO entityTO,
             final M anyPatch) throws JobExecutionException {
 
         if (anyPatch instanceof UserPatch) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
index a75ff8b..9344835 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPullActions.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.provisioning.java.pushpull;
 
 import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException;
 import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningProfile;
@@ -38,10 +37,10 @@ public abstract class DefaultPullActions implements PullActions {
     }
 
     @Override
-    public <A extends AnyTO, P extends AnyPatch> SyncDelta beforeUpdate(
+    public <P extends AnyPatch> SyncDelta beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
-            final A any,
+            final EntityTO entityTO,
             final P anyMod) throws JobExecutionException {
 
         return delta;

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
index 967b27c..f11a20e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/LDAPPasswordPullActions.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.provisioning.java.pushpull;
 import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.patch.PasswordPatch;
 import org.apache.syncope.common.lib.patch.UserPatch;
-import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -70,10 +69,10 @@ public class LDAPPasswordPullActions extends DefaultPullActions {
 
     @Transactional(readOnly = true)
     @Override
-    public <A extends AnyTO, M extends AnyPatch> SyncDelta beforeUpdate(
+    public <M extends AnyPatch> SyncDelta beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
-            final A any,
+            final EntityTO entityTO,
             final M anyPatch) throws JobExecutionException {
 
         if (anyPatch instanceof UserPatch) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
index 33a9634..81bfd70 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
@@ -27,11 +27,11 @@ import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
-import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 
 public class PlainAttrsPullCorrelationRule implements PullCorrelationRule {
 
@@ -47,7 +47,7 @@ public class PlainAttrsPullCorrelationRule implements PullCorrelationRule {
     @Override
     public SearchCond getSearchCond(final ConnectorObject connObj) {
         Map<String, MappingItem> mappingItems = new HashMap<>();
-        for (MappingItem item : MappingUtils.getPullMappingItems(provision)) {
+        for (MappingItem item : MappingUtils.getPullItems(provision)) {
             mappingItems.put(item.getIntAttrName(), item);
         }
 
@@ -65,7 +65,7 @@ public class PlainAttrsPullCorrelationRule implements PullCorrelationRule {
             }
 
             List<Object> values = attr.getValue();
-            for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(mappingItem)) {
+            for (ItemTransformer transformer : MappingUtils.getItemTransformers(mappingItem)) {
                 values = transformer.beforePull(mappingItem, null, values);
             }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
index fa7807e..3520db0 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -151,10 +151,10 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
         // First OrgUnits...
         if (pullTask.getResource().getOrgUnit() != null) {
             OrgUnit orgUnit = pullTask.getResource().getOrgUnit();
-            OperationOptions options = MappingUtils.buildOperationOptions(orgUnit);
+            OperationOptions options = MappingUtils.buildOperationOptions(
+                    MappingUtils.getPullItems(orgUnit).iterator());
 
-            SyncopePullResultHandler rhandler =
-                    (SyncopePullResultHandler) ApplicationContextProvider.getBeanFactory().
+            SyncopePullResultHandler rhandler = (SyncopePullResultHandler) ApplicationContextProvider.getBeanFactory().
                     createBean(RealmPullResultHandlerImpl.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
             rhandler.setProfile(profile);
             rhandler.setPullExecutor(this);
@@ -181,8 +181,8 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
                     case FILTERED_RECONCILIATION:
                         ReconciliationFilterBuilder filterBuilder =
                                 (ReconciliationFilterBuilder) ApplicationContextProvider.getBeanFactory().
-                                createBean(Class.forName(pullTask.getReconciliationFilterBuilderClassName()),
-                                        AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+                                        createBean(Class.forName(pullTask.getReconciliationFilterBuilderClassName()),
+                                                AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
                         connector.filteredReconciliation(orgUnit.getObjectClass(),
                                 filterBuilder,
                                 rhandler,
@@ -265,8 +265,9 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
                         case FILTERED_RECONCILIATION:
                             ReconciliationFilterBuilder filterBuilder =
                                     (ReconciliationFilterBuilder) ApplicationContextProvider.getBeanFactory().
-                                    createBean(Class.forName(pullTask.getReconciliationFilterBuilderClassName()),
-                                            AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+                                            createBean(
+                                                    Class.forName(pullTask.getReconciliationFilterBuilderClassName()),
+                                                    AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
                             connector.filteredReconciliation(provision.getObjectClass(),
                                     filterBuilder,
                                     handler,

http://git-wip-us.apache.org/repos/asf/syncope/blob/eebca673/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
index e73517c..819c5f3 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.provisioning.java.pushpull;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.policy.PullPolicySpec;
@@ -31,6 +32,7 @@ import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
@@ -38,17 +40,19 @@ import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 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.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.Connector;
 import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
-import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
@@ -62,7 +66,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
+import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.apache.syncope.core.provisioning.api.data.ItemTransformer;
 
 @Transactional(readOnly = true)
 @Component
@@ -101,6 +107,9 @@ public class PullUtils {
     private AnySearchDAO searchDAO;
 
     @Autowired
+    private RealmDAO realmDAO;
+
+    @Autowired
     private AnyUtilsFactory anyUtilsFactory;
 
     @Autowired
@@ -130,7 +139,7 @@ public class PullUtils {
             public boolean handle(final ConnectorObject obj) {
                 return found.add(obj);
             }
-        }, MappingUtils.buildOperationOptions(MappingUtils.getPullMappingItems(provision).iterator()));
+        }, MappingUtils.buildOperationOptions(MappingUtils.getPullItems(provision).iterator()));
 
         if (found.isEmpty()) {
             LOG.debug("No {} found on {} with __NAME__ {}", provision.getObjectClass(), resource, name);
@@ -171,12 +180,10 @@ public class PullUtils {
     private List<String> findByConnObjectKeyItem(
             final String uid, final Provision provision, final AnyUtils anyUtils) {
 
-        List<String> result = new ArrayList<>();
-
         MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
 
         String transfUid = uid;
-        for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(connObjectKeyItem)) {
+        for (ItemTransformer transformer : MappingUtils.getItemTransformers(connObjectKeyItem)) {
             List<Object> output = transformer.beforePull(
                     connObjectKeyItem,
                     null,
@@ -186,6 +193,8 @@ public class PullUtils {
             }
         }
 
+        List<String> result = new ArrayList<>();
+
         IntAttrName intAttrName = intAttrNameParser.parse(
                 connObjectKeyItem.getIntAttrName(),
                 provision.getAnyType().getKind());
@@ -323,6 +332,52 @@ public class PullUtils {
         }
     }
 
+    public List<String> findExisting(
+            final String uid,
+            final ConnectorObject connObj,
+            final OrgUnit orgUnit) {
+
+        OrgUnitItem connObjectKeyItem = orgUnit.getConnObjectKeyItem();
+
+        String transfUid = uid;
+        for (ItemTransformer transformer : MappingUtils.getItemTransformers(connObjectKeyItem)) {
+            List<Object> output = transformer.beforePull(
+                    connObjectKeyItem,
+                    null,
+                    Collections.<Object>singletonList(transfUid));
+            if (output != null && !output.isEmpty()) {
+                transfUid = output.get(0).toString();
+            }
+        }
+
+        List<String> result = new ArrayList<>();
+
+        Realm realm;
+        switch (connObjectKeyItem.getIntAttrName()) {
+            case "key":
+                realm = realmDAO.find(transfUid);
+                if (realm != null) {
+                    result.add(realm.getKey());
+                }
+                break;
+
+            case "name":
+                CollectionUtils.collect(realmDAO.findByName(transfUid), EntityUtils.keyTransformer(), result);
+                break;
+
+            case "fullpath":
+                realm = realmDAO.findByFullPath(transfUid);
+                if (realm != null) {
+                    result.add(realm.getKey());
+                }
+                break;
+
+            default:
+        }
+
+        return result;
+    }
+
     public Boolean readEnabled(final ConnectorObject connectorObject, final ProvisioningTask task) {
         Boolean enabled = null;
         if (task.isSyncStatus()) {