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 2019/01/29 17:00:26 UTC

[syncope] branch 2_0_X updated: [SYNCOPE-1430] Now ItemTransformer#beforePropagation requires (and returns) AttrSchemaType to avoid unwante attribute value type mess

This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch 2_0_X
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/2_0_X by this push:
     new 9352440  [SYNCOPE-1430] Now ItemTransformer#beforePropagation requires (and returns) AttrSchemaType to avoid unwante attribute value type mess
9352440 is described below

commit 93524408dc6c3933ef0f1d9508143e9a109dc180
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Tue Jan 29 15:18:21 2019 +0100

    [SYNCOPE-1430] Now ItemTransformer#beforePropagation requires (and returns) AttrSchemaType to avoid unwante attribute value type mess
---
 .../syncope/core/persistence/api/dao/AnyDAO.java   |  10 +-
 .../core/persistence/jpa/dao/AbstractAnyDAO.java   |  21 ++--
 .../jpa/entity/AbstractPlainAttrValue.java         |  45 ++++++-
 .../core/persistence/jpa/inner/UserTest.java       |  18 ++-
 .../core/persistence/jpa/outer/UserTest.java       |   4 +-
 .../syncope/core/provisioning/api/IntAttrName.java |  11 +-
 .../core/provisioning/api/MappingManager.java      |   7 +-
 .../provisioning/api/data/ItemTransformer.java     |   6 +-
 .../core/provisioning/java/IntAttrNameParser.java  |  16 ++-
 .../core/provisioning/java/MappingManagerImpl.java | 135 +++++++++------------
 .../java/data/AbstractAnyDataBinder.java           |  15 ++-
 .../java/data/DefaultItemTransformer.java          |  12 +-
 .../java/data/JEXLItemTransformerImpl.java         |  11 +-
 .../java/data/ResourceDataBinderImpl.java          |   6 +-
 .../core/provisioning/java/pushpull/PullUtils.java |  19 +--
 .../provisioning/java/IntAttrNameParserTest.java   |  33 +++--
 .../syncope/core/logic/oidc/OIDCUserManager.java   |  17 +--
 .../java/data/OIDCProviderDataBinderImpl.java      |   6 +-
 .../syncope/core/logic/saml2/SAML2UserManager.java |  17 +--
 .../java/data/SAML2IdPDataBinderImpl.java          |   6 +-
 ...sformer.java => DateToDateItemTransformer.java} |  42 ++-----
 ...sformer.java => DateToLongItemTransformer.java} |  45 +++----
 .../fit/core/reference/ITImplementationLookup.java |   2 +
 .../fit/core/reference/PrefixItemTransformer.java  |  10 +-
 .../syncope/fit/core/PropagationTaskITCase.java    | 124 +++++++++++++++++++
 .../org/apache/syncope/fit/core/VirAttrITCase.java |   1 -
 26 files changed, 403 insertions(+), 236 deletions(-)

diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
index 658a32b..41e81a9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
@@ -23,8 +23,10 @@ import java.util.Date;
 import java.util.List;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 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.Schema;
 
 public interface AnyDAO<A extends Any<?>> extends DAO<A> {
@@ -41,9 +43,9 @@ public interface AnyDAO<A extends Any<?>> extends DAO<A> {
 
     A findByWorkflowId(String workflowId);
 
-    List<A> findByPlainAttrValue(String schemaName, PlainAttrValue attrValue);
+    List<A> findByPlainAttrValue(PlainSchema schema, PlainAttrValue attrValue);
 
-    A findByPlainAttrUniqueValue(String schemaName, PlainAttrValue attrUniqueValue);
+    A findByPlainAttrUniqueValue(PlainSchema schema, PlainAttrValue attrUniqueValue);
 
     /**
      * Find any objects by derived attribute value. This method could fail if one or more string literals contained
@@ -51,11 +53,11 @@ public interface AnyDAO<A extends Any<?>> extends DAO<A> {
      * specify a derived attribute expression you must be quite sure that string literals used to build the expression
      * cannot be found into the attribute values used to replace attribute schema names used as identifiers.
      *
-     * @param schemaName derived schema name
+     * @param schema derived schema
      * @param value derived attribute value
      * @return list of any objects
      */
-    List<A> findByDerAttrValue(String schemaName, String value);
+    List<A> findByDerAttrValue(DerSchema schema, String value);
 
     List<A> findByResource(ExternalResource resource);
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 4588617..8fc2ebc 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -211,10 +211,9 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
 
     @Override
     @SuppressWarnings("unchecked")
-    public List<A> findByPlainAttrValue(final String schemaKey, final PlainAttrValue attrValue) {
-        PlainSchema schema = plainSchemaDAO().find(schemaKey);
+    public List<A> findByPlainAttrValue(final PlainSchema schema, final PlainAttrValue attrValue) {
         if (schema == null) {
-            LOG.error("Invalid schema name '{}'", schemaKey);
+            LOG.error("No PlainSchema");
             return Collections.<A>emptyList();
         }
 
@@ -222,7 +221,7 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
                 ? anyUtils().plainAttrUniqueValueClass().getName()
                 : anyUtils().plainAttrValueClass().getName();
         Query query = findByPlainAttrValueQuery(entityName);
-        query.setParameter("schemaKey", schemaKey);
+        query.setParameter("schemaKey", schema.getKey());
         query.setParameter("stringValue", attrValue.getStringValue());
         query.setParameter("booleanValue", attrValue.getBooleanValue() == null
                 ? null
@@ -247,18 +246,17 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
     }
 
     @Override
-    public A findByPlainAttrUniqueValue(final String schemaKey, final PlainAttrValue attrUniqueValue) {
-        PlainSchema schema = plainSchemaDAO().find(schemaKey);
+    public A findByPlainAttrUniqueValue(final PlainSchema schema, final PlainAttrValue attrUniqueValue) {
         if (schema == null) {
-            LOG.error("Invalid schema name '{}'", schemaKey);
+            LOG.error("No PlainSchema");
             return null;
         }
         if (!schema.isUniqueConstraint()) {
-            LOG.error("This schema has not unique constraint: '{}'", schemaKey);
+            LOG.error("This schema has not unique constraint: '{}'", schema.getKey());
             return null;
         }
 
-        List<A> result = findByPlainAttrValue(schemaKey, attrUniqueValue);
+        List<A> result = findByPlainAttrValue(schema, attrUniqueValue);
         return result.isEmpty()
                 ? null
                 : result.iterator().next();
@@ -412,10 +410,9 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
     }
 
     @Override
-    public List<A> findByDerAttrValue(final String schemaKey, final String value) {
-        DerSchema schema = derSchemaDAO().find(schemaKey);
+    public List<A> findByDerAttrValue(final DerSchema schema, final String value) {
         if (schema == null) {
-            LOG.error("Invalid schema name '{}'", schemaKey);
+            LOG.error("No DerSchema");
             return Collections.<A>emptyList();
         }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
index 03083e8..54285da 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
@@ -219,7 +219,51 @@ public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity
                                                 : getStringValue());
     }
 
+    private Object getValue(final AttrSchemaType type) {
+        Object value;
+        switch (type) {
+
+            case Boolean:
+                value = getBooleanValue();
+                break;
+
+            case Long:
+                value = getLongValue();
+                break;
+
+            case Double:
+                value = getDoubleValue();
+                break;
+
+            case Date:
+                value = getDateValue();
+                break;
+
+            case Binary:
+                value = getBinaryValue();
+                break;
+
+            case String:
+            case Enum:
+            case Encrypted:
+                value = getStringValue();
+                break;
+
+            default:
+                value = null;
+        }
+
+        return value;
+    }
+
     private String getValueAsString(final AttrSchemaType type, final PlainSchema schema) {
+        if (getValue(type) == null) {
+            LOG.warn("Could not find expected value for type {} in {}, reverting to getValue().toString()", type, this);
+
+            Object value = getValue();
+            return value == null ? null : value.toString();
+        }
+
         String result;
         switch (type) {
 
@@ -254,7 +298,6 @@ public abstract class AbstractPlainAttrValue extends AbstractGeneratedKeyEntity
             case Encrypted:
             default:
                 result = getStringValue();
-                break;
         }
 
         return result;
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
index eb48129..2be9203 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/UserTest.java
@@ -28,7 +28,9 @@ import java.util.Date;
 import java.util.List;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -55,6 +57,12 @@ public class UserTest extends AbstractTest {
     @Autowired
     private ExternalResourceDAO resourceDAO;
 
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
     @Test
     public void findAll() {
         List<User> list = userDAO.findAll(1, 100);
@@ -89,18 +97,18 @@ public class UserTest extends AbstractTest {
 
     @Test
     public void findByDerAttributeValue() {
-        final List<User> list = userDAO.findByDerAttrValue("cn", "Vivaldi, Antonio");
+        final List<User> list = userDAO.findByDerAttrValue(derSchemaDAO.find("cn"), "Vivaldi, Antonio");
         assertEquals("did not get expected number of users", 1, list.size());
     }
 
     @Test
     public void findByInvalidDerAttrValue() {
-        assertTrue(userDAO.findByDerAttrValue("cn", "Antonio, Maria, Rossi").isEmpty());
+        assertTrue(userDAO.findByDerAttrValue(derSchemaDAO.find("cn"), "Antonio, Maria, Rossi").isEmpty());
     }
 
     @Test
     public void findByInvalidDerAttrExpression() {
-        assertTrue(userDAO.findByDerAttrValue("noschema", "Antonio, Maria").isEmpty());
+        assertTrue(userDAO.findByDerAttrValue(derSchemaDAO.find("noschema"), "Antonio, Maria").isEmpty());
     }
 
     @Test
@@ -108,7 +116,7 @@ public class UserTest extends AbstractTest {
         final UPlainAttrValue fullnameValue = entityFactory.newEntity(UPlainAttrValue.class);
         fullnameValue.setStringValue("Gioacchino Rossini");
 
-        final List<User> list = userDAO.findByPlainAttrValue("fullname", fullnameValue);
+        final List<User> list = userDAO.findByPlainAttrValue(plainSchemaDAO.find("fullname"), fullnameValue);
         assertEquals("did not get expected number of users", 1, list.size());
     }
 
@@ -117,7 +125,7 @@ public class UserTest extends AbstractTest {
         final UPlainAttrValue coolValue = entityFactory.newEntity(UPlainAttrValue.class);
         coolValue.setBooleanValue(true);
 
-        final List<User> list = userDAO.findByPlainAttrValue("cool", coolValue);
+        final List<User> list = userDAO.findByPlainAttrValue(plainSchemaDAO.find("cool"), coolValue);
         assertEquals("did not get expected number of users", 1, list.size());
     }
 
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
index ede95f7..19c442c 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
@@ -255,11 +255,11 @@ public class UserTest extends AbstractTest {
         assertNotNull(firstname);
 
         // search by ksuffix derived attribute
-        List<User> list = userDAO.findByDerAttrValue("ksuffix", firstname + "k");
+        List<User> list = userDAO.findByDerAttrValue(derSchemaDAO.find("ksuffix"), firstname + "k");
         assertEquals("did not get expected number of users ", 1, list.size());
 
         // search by kprefix derived attribute
-        list = userDAO.findByDerAttrValue("kprefix", "k" + firstname);
+        list = userDAO.findByDerAttrValue(derSchemaDAO.find("kprefix"), "k" + firstname);
         assertEquals("did not get expected number of users ", 1, list.size());
     }
 
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
index a243bad..dee9859 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
@@ -22,6 +22,7 @@ import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.persistence.api.entity.Schema;
 
 public class IntAttrName {
 
@@ -31,7 +32,7 @@ public class IntAttrName {
 
     private SchemaType schemaType;
 
-    private String schemaName;
+    private Schema schema;
 
     private String enclosingGroup;
 
@@ -69,12 +70,12 @@ public class IntAttrName {
         this.schemaType = schemaType;
     }
 
-    public String getSchemaName() {
-        return schemaName;
+    public Schema getSchema() {
+        return schema;
     }
 
-    public void setSchemaName(final String schemaName) {
-        this.schemaName = schemaName;
+    public void setSchema(final Schema schemaName) {
+        this.schema = schemaName;
     }
 
     public String getEnclosingGroup() {
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 b030782..a9f7cf3 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
@@ -23,6 +23,7 @@ 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.common.lib.types.AttrSchemaType;
 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.Realm;
@@ -57,10 +58,12 @@ public interface MappingManager {
      * @param provision provision information
      * @param mapItem mapping item
      * @param intAttrName int attr name
+     * @param schemaType schema type
      * @param any any object
-     * @return attribute values.
+     * @return attribute values and their type
      */
-    List<PlainAttrValue> getIntValues(Provision provision, Item mapItem, IntAttrName intAttrName, Any<?> any);
+    Pair<AttrSchemaType, List<PlainAttrValue>> getIntValues(
+            Provision provision, Item mapItem, IntAttrName intAttrName, AttrSchemaType schemaType, Any<?> any);
 
     /**
      * Prepare attributes for sending to a connector instance.
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
index 1ec16c3..0177d58 100644
--- 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
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.provisioning.api.data;
 
 import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 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;
@@ -37,12 +39,14 @@ public interface ItemTransformer {
      *
      * @param item mapping item
      * @param entity entity
+     * @param schemaType schema type
      * @param values original values
      * @return transformed values
      */
-    List<PlainAttrValue> beforePropagation(
+    Pair<AttrSchemaType, List<PlainAttrValue>> beforePropagation(
             Item item,
             Entity entity,
+            AttrSchemaType schemaType,
             List<PlainAttrValue> values);
 
     /**
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
index 27dd988..16b3f06 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
@@ -22,6 +22,7 @@ import java.text.ParseException;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.SchemaType;
@@ -63,7 +64,7 @@ public class IntAttrNameParser {
     @Autowired
     private AnyUtilsFactory anyUtilsFactory;
 
-    private SchemaType find(final String key) {
+    private Pair<Schema, SchemaType> find(final String key) {
         Schema schema = plainSchemaDAO.find(key);
         if (schema == null) {
             schema = derSchemaDAO.find(key);
@@ -72,13 +73,13 @@ public class IntAttrNameParser {
                 if (schema == null) {
                     return null;
                 } else {
-                    return SchemaType.VIRTUAL;
+                    return Pair.of(schema, SchemaType.VIRTUAL);
                 }
             } else {
-                return SchemaType.DERIVED;
+                return Pair.of(schema, SchemaType.DERIVED);
             }
         } else {
-            return SchemaType.PLAIN;
+            return Pair.of(schema, SchemaType.PLAIN);
         }
     }
 
@@ -90,8 +91,11 @@ public class IntAttrNameParser {
         if (anyUtilsFactory.getInstance(anyTypeKind).isFieldName(fieldOrSchemaName)) {
             result.setField(fieldOrSchemaName);
         } else {
-            result.setSchemaType(find(fieldOrSchemaName));
-            result.setSchemaName(fieldOrSchemaName);
+            Pair<Schema, SchemaType> schemaInfo = find(fieldOrSchemaName);
+            if (schemaInfo != null) {
+                result.setSchemaType(schemaInfo.getRight());
+                result.setSchema(schemaInfo.getLeft());
+            }
         }
     }
 
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 ad34038..f3f7201 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
@@ -45,13 +45,10 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 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.RelationshipTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
-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.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
@@ -65,7 +62,6 @@ 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.Relationship;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
-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;
@@ -111,15 +107,6 @@ public class MappingManagerImpl implements MappingManager {
     private AnyTypeDAO anyTypeDAO;
 
     @Autowired
-    private PlainSchemaDAO plainSchemaDAO;
-
-    @Autowired
-    private DerSchemaDAO derSchemaDAO;
-
-    @Autowired
-    private VirSchemaDAO virSchemaDAO;
-
-    @Autowired
     private AnyObjectDAO anyObjectDAO;
 
     @Autowired
@@ -320,36 +307,26 @@ public class MappingManagerImpl implements MappingManager {
             return null;
         }
 
-        boolean readOnlyVirSchema = false;
-        Schema schema = null;
-        AttrSchemaType schemaType = AttrSchemaType.String;
-        if (intAttrName.getSchemaType() != null) {
-            switch (intAttrName.getSchemaType()) {
-                case PLAIN:
-                    schema = plainSchemaDAO.find(intAttrName.getSchemaName());
-                    if (schema != null) {
-                        schemaType = schema.getType();
-                    }
-                    break;
-
-                case VIRTUAL:
-                    schema = virSchemaDAO.find(intAttrName.getSchemaName());
-                    readOnlyVirSchema = (schema != null && schema.isReadonly());
-                    break;
-
-                default:
-            }
-        }
+        AttrSchemaType schemaType = intAttrName.getSchema() instanceof PlainSchema
+                ? ((PlainSchema) intAttrName.getSchema()).getType()
+                : AttrSchemaType.String;
+        boolean readOnlyVirSchema = intAttrName.getSchema() instanceof VirSchema
+                ? intAttrName.getSchema().isReadonly()
+                : false;
 
-        List<PlainAttrValue> values = getIntValues(provision, mapItem, intAttrName, any);
+        Pair<AttrSchemaType, List<PlainAttrValue>> intValues =
+                getIntValues(provision, mapItem, intAttrName, schemaType, any);
+        schemaType = intValues.getLeft();
+        List<PlainAttrValue> values = intValues.getRight();
 
         LOG.debug("Define mapping for: "
                 + "\n* ExtAttrName " + mapItem.getExtAttrName()
                 + "\n* is connObjectKey " + mapItem.isConnObjectKey()
                 + "\n* is password " + mapItem.isPassword()
                 + "\n* mandatory condition " + mapItem.getMandatoryCondition()
-                + "\n* Schema " + intAttrName.getSchemaName()
+                + "\n* Schema " + intAttrName.getSchema()
                 + "\n* ClassType " + schemaType.getType().getName()
+                + "\n* AttrSchemaType " + schemaType
                 + "\n* Values " + values);
 
         Pair<String, Attribute> result;
@@ -362,10 +339,13 @@ public class MappingManagerImpl implements MappingManager {
                 if (FrameworkUtil.isSupportedAttributeType(schemaType.getType())) {
                     objValues.add(value.getValue());
                 } else {
-                    if (schema instanceof PlainSchema) {
-                        objValues.add(value.getValueAsString((PlainSchema) schema));
-                    } else {
+                    PlainSchema plainSchema = intAttrName.getSchema() instanceof PlainSchema
+                            ? (PlainSchema) intAttrName.getSchema()
+                            : null;
+                    if (plainSchema == null || plainSchema.getType() != schemaType) {
                         objValues.add(value.getValueAsString(schemaType));
+                    } else {
+                        objValues.add(value.getValueAsString(plainSchema));
                     }
                 }
             }
@@ -408,10 +388,11 @@ public class MappingManagerImpl implements MappingManager {
 
     @Transactional(readOnly = true)
     @Override
-    public List<PlainAttrValue> getIntValues(
+    public Pair<AttrSchemaType, List<PlainAttrValue>> getIntValues(
             final Provision provision,
             final Item mapItem,
             final IntAttrName intAttrName,
+            final AttrSchemaType schemaType,
             final Any<?> any) {
 
         LOG.debug("Get internal values for {} as '{}' on {}", any, mapItem.getIntAttrName(), provision.getResource());
@@ -484,7 +465,7 @@ public class MappingManagerImpl implements MappingManager {
         }
         if (references.isEmpty()) {
             LOG.warn("Could not determine the reference instance for {}", mapItem.getIntAttrName());
-            return Collections.emptyList();
+            return Pair.of(schemaType, Collections.<PlainAttrValue>emptyList());
         }
 
         List<PlainAttrValue> values = new ArrayList<>();
@@ -576,10 +557,10 @@ public class MappingManagerImpl implements MappingManager {
                     case PLAIN:
                         PlainAttr<?> attr;
                         if (membership == null) {
-                            attr = reference.getPlainAttr(intAttrName.getSchemaName());
+                            attr = reference.getPlainAttr(intAttrName.getSchema().getKey());
                         } else {
-                            attr = ((GroupableRelatable<?, ?, ?, ?, ?>) reference).getPlainAttr(
-                                    intAttrName.getSchemaName(), membership);
+                            attr = ((GroupableRelatable<?, ?, ?, ?, ?>) reference).
+                                    getPlainAttr(intAttrName.getSchema().getKey(), membership);
                         }
                         if (attr != null) {
                             if (attr.getUniqueValue() != null) {
@@ -593,16 +574,14 @@ public class MappingManagerImpl implements MappingManager {
                         break;
 
                     case DERIVED:
-                        DerSchema derSchema = derSchemaDAO.find(intAttrName.getSchemaName());
-                        if (derSchema != null) {
-                            String value = membership == null
-                                    ? derAttrHandler.getValue(reference, derSchema)
-                                    : derAttrHandler.getValue(reference, membership, derSchema);
-                            if (value != null) {
-                                PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                                attrValue.setStringValue(value);
-                                values.add(attrValue);
-                            }
+                        DerSchema derSchema = (DerSchema) intAttrName.getSchema();
+                        String derValue = membership == null
+                                ? derAttrHandler.getValue(reference, derSchema)
+                                : derAttrHandler.getValue(reference, membership, derSchema);
+                        if (derValue != null) {
+                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                            attrValue.setStringValue(derValue);
+                            values.add(attrValue);
                         }
                         break;
 
@@ -610,20 +589,18 @@ public class MappingManagerImpl implements MappingManager {
                         // virtual attributes don't get transformed
                         transform = false;
 
-                        VirSchema virSchema = virSchemaDAO.find(intAttrName.getSchemaName());
-                        if (virSchema != null) {
-                            LOG.debug("Expire entry cache {}-{}", reference, intAttrName.getSchemaName());
-                            virAttrCache.expire(
-                                    reference.getType().getKey(), reference.getKey(), intAttrName.getSchemaName());
-
-                            List<String> virValues = membership == null
-                                    ? virAttrHandler.getValues(reference, virSchema)
-                                    : virAttrHandler.getValues(reference, membership, virSchema);
-                            for (String value : virValues) {
-                                PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                                attrValue.setStringValue(value);
-                                values.add(attrValue);
-                            }
+                        VirSchema virSchema = (VirSchema) intAttrName.getSchema();
+                        LOG.debug("Expire entry cache {}-{}", reference, intAttrName.getSchema());
+                        virAttrCache.expire(
+                                reference.getType().getKey(), reference.getKey(), intAttrName.getSchema().getKey());
+
+                        List<String> virValues = membership == null
+                                ? virAttrHandler.getValues(reference, virSchema)
+                                : virAttrHandler.getValues(reference, membership, virSchema);
+                        for (String virValue : virValues) {
+                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                            attrValue.setStringValue(virValue);
+                            values.add(attrValue);
                         }
                         break;
 
@@ -634,17 +611,17 @@ public class MappingManagerImpl implements MappingManager {
 
         LOG.debug("Internal values: {}", values);
 
-        List<PlainAttrValue> transformed = values;
+        Pair<AttrSchemaType, List<PlainAttrValue>> trans = Pair.of(schemaType, values);
         if (transform) {
             for (ItemTransformer transformer : MappingUtils.getItemTransformers(mapItem)) {
-                transformed = transformer.beforePropagation(mapItem, any, transformed);
+                trans = transformer.beforePropagation(mapItem, any, trans.getLeft(), trans.getRight());
             }
             LOG.debug("Transformed values: {}", values);
         } else {
             LOG.debug("No transformation occurred");
         }
 
-        return transformed;
+        return trans;
     }
 
     private String getGroupOwnerValue(final Provision provision, final Any<?> any) {
@@ -664,20 +641,21 @@ public class MappingManagerImpl implements MappingManager {
     @Override
     public String getConnObjectKeyValue(final Any<?> any, final Provision provision) {
         MappingItem mapItem = provision.getMapping().getConnObjectKeyItem();
-        List<PlainAttrValue> values;
+        Pair<AttrSchemaType, List<PlainAttrValue>> values;
         try {
             values = getIntValues(
                     provision,
                     mapItem,
                     intAttrNameParser.parse(mapItem.getIntAttrName(), provision.getAnyType().getKind()),
+                    AttrSchemaType.String,
                     any);
         } catch (ParseException e) {
             LOG.error("Invalid intAttrName '{}' specified, ignoring", mapItem.getIntAttrName(), e);
-            values = Collections.emptyList();
+            values = Pair.of(AttrSchemaType.String, Collections.<PlainAttrValue>emptyList());
         }
-        return values.isEmpty()
+        return values.getRight().isEmpty()
                 ? null
-                : values.get(0).getValueAsString();
+                : values.getRight().get(0).getValueAsString();
     }
 
     @Transactional(readOnly = true)
@@ -772,9 +750,9 @@ public class MappingManagerImpl implements MappingManager {
             switch (intAttrName.getSchemaType()) {
                 case PLAIN:
                     AttrTO attrTO = new AttrTO();
-                    attrTO.setSchema(intAttrName.getSchemaName());
+                    attrTO.setSchema(intAttrName.getSchema().getKey());
 
-                    PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
+                    PlainSchema schema = (PlainSchema) intAttrName.getSchema();
 
                     for (Object value : values) {
                         AttrSchemaType schemaType = schema == null ? AttrSchemaType.String : schema.getType();
@@ -801,7 +779,8 @@ public class MappingManagerImpl implements MappingManager {
 
                 case DERIVED:
                     attrTO = new AttrTO();
-                    attrTO.setSchema(intAttrName.getSchemaName());
+                    attrTO.setSchema(intAttrName.getSchema().getKey());
+
                     if (groupableTO == null || group == null) {
                         anyTO.getDerAttrs().add(attrTO);
                     } else {
@@ -816,7 +795,7 @@ public class MappingManagerImpl implements MappingManager {
 
                 case VIRTUAL:
                     attrTO = new AttrTO();
-                    attrTO.setSchema(intAttrName.getSchemaName());
+                    attrTO.setSchema(intAttrName.getSchema().getKey());
 
                     // virtual attributes don't get transformed, iterate over original attr.getValue()
                     for (Object value : attr.getValue() == null ? Collections.emptyList() : attr.getValue()) {
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 6057749..a169532 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
@@ -28,6 +28,7 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.patch.AnyPatch;
@@ -37,6 +38,7 @@ import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.ResourceOperation;
@@ -212,9 +214,16 @@ abstract class AbstractAnyDataBinder {
             } catch (ParseException e) {
                 LOG.error("Invalid intAttrName '{}', ignoring", mapItem.getIntAttrName(), e);
             }
-            if (intAttrName != null && intAttrName.getSchemaType() != null) {
-                List<PlainAttrValue> values = mappingManager.getIntValues(provision, mapItem, intAttrName, any);
-                if (values.isEmpty() && JexlUtils.evaluateMandatoryCondition(mapItem.getMandatoryCondition(), any)) {
+            if (intAttrName != null && intAttrName.getSchema() != null) {
+                AttrSchemaType schemaType = intAttrName.getSchema() instanceof PlainSchema
+                        ? ((PlainSchema) intAttrName.getSchema()).getType()
+                        : AttrSchemaType.String;
+
+                Pair<AttrSchemaType, List<PlainAttrValue>> intValues =
+                        mappingManager.getIntValues(provision, mapItem, intAttrName, schemaType, any);
+                if (intValues.getRight().isEmpty()
+                        && JexlUtils.evaluateMandatoryCondition(mapItem.getMandatoryCondition(), any)) {
+
                     missingAttrNames.add(mapItem.getIntAttrName());
                 }
             }
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
index 230962a..54c3fb7 100644
--- 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
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.provisioning.java.data;
 
 import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 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;
@@ -33,15 +35,17 @@ import org.springframework.transaction.annotation.Transactional;
 public class DefaultItemTransformer implements ItemTransformer {
 
     @Override
-    public List<PlainAttrValue> beforePropagation(
-            final Item item, final Entity entity, final List<PlainAttrValue> values) {
+    public Pair<AttrSchemaType, List<PlainAttrValue>> beforePropagation(
+            final Item item,
+            final Entity entity,
+            final AttrSchemaType schemaType,
+            final List<PlainAttrValue> values) {
 
-        return values;
+        return Pair.of(schemaType, values);
     }
 
     @Override
     public List<Object> beforePull(final Item item, final EntityTO entityTO, final List<Object> values) {
         return values;
     }
-
 }
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
index 1c67951..48ccc0e 100644
--- 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
@@ -23,9 +23,11 @@ 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.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 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;
@@ -50,9 +52,10 @@ public class JEXLItemTransformerImpl extends DefaultItemTransformer implements J
     }
 
     @Override
-    public List<PlainAttrValue> beforePropagation(
+    public Pair<AttrSchemaType, List<PlainAttrValue>> beforePropagation(
             final Item item,
             final Entity entity,
+            final AttrSchemaType schemaType,
             final List<PlainAttrValue> values) {
 
         if (StringUtils.isNotBlank(propagationJEXL) && values != null) {
@@ -67,7 +70,7 @@ public class JEXLItemTransformerImpl extends DefaultItemTransformer implements J
                             JexlUtils.addDerAttrsToContext(((Any<?>) entity), jexlContext);
                         }
                     }
-                    jexlContext.set("value", originalValue.toString());
+                    jexlContext.set("value", originalValue);
 
                     value.setBinaryValue(null);
                     value.setBooleanValue(null);
@@ -78,10 +81,10 @@ public class JEXLItemTransformerImpl extends DefaultItemTransformer implements J
                 }
             }
 
-            return values;
+            return Pair.of(AttrSchemaType.String, values);
         }
 
-        return super.beforePropagation(item, entity, values);
+        return super.beforePropagation(item, entity, schemaType, values);
     }
 
     @Override
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 294dbc1..0e5d78b 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
@@ -404,15 +404,15 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                             && intAttrName.getRelatedAnyObject() == null) {
                         switch (intAttrName.getSchemaType()) {
                             case PLAIN:
-                                allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             case DERIVED:
-                                allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             case VIRTUAL:
-                                allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             default:
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 7345fb7..742cecb 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
@@ -26,6 +26,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.policy.PullPolicySpec;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 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.AnySearchDAO;
@@ -37,6 +38,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 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.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
@@ -243,27 +245,26 @@ public class PullUtils {
                 case PLAIN:
                     PlainAttrValue value = anyUtils.newPlainAttrValue();
 
-                    PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
-                    if (schema == null) {
+                    if (intAttrName.getSchemaType() == SchemaType.PLAIN) {
                         value.setStringValue(connObjectKey);
                     } else {
                         try {
-                            value.parseValue(schema, connObjectKey);
+                            value.parseValue((PlainSchema) intAttrName.getSchema(), connObjectKey);
                         } catch (ParsingValidationException e) {
                             LOG.error("While parsing provided __UID__ {}", value, e);
                             value.setStringValue(connObjectKey);
                         }
                     }
 
-                    for (Any<?> any : anyUtils.dao().findByPlainAttrValue(intAttrName.getSchemaName(), value)) {
-                        result.add(any.getKey());
-                    }
+                    result.addAll(CollectionUtils.collect(
+                            anyUtils.dao().findByPlainAttrValue((PlainSchema) intAttrName.getSchema(), value),
+                            EntityUtils.keyTransformer()));
                     break;
 
                 case DERIVED:
-                    for (Any<?> any : anyUtils.dao().findByDerAttrValue(intAttrName.getSchemaName(), connObjectKey)) {
-                        result.add(any.getKey());
-                    }
+                    result.addAll(CollectionUtils.collect(
+                            anyUtils.dao().findByDerAttrValue((DerSchema) intAttrName.getSchema(), connObjectKey),
+                            EntityUtils.keyTransformer()));
                     break;
 
                 default:
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
index 334a162..1743537 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
@@ -21,11 +21,15 @@ package org.apache.syncope.core.provisioning.java;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.text.ParseException;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -44,7 +48,7 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
         assertNotNull(intAttrName.getField());
         assertEquals("key", intAttrName.getField());
-        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchema());
         assertNull(intAttrName.getSchemaType());
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
@@ -58,7 +62,7 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
         assertNotNull(intAttrName.getField());
         assertEquals("name", intAttrName.getField());
-        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchema());
         assertNull(intAttrName.getSchemaType());
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
@@ -72,7 +76,7 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
         assertNotNull(intAttrName.getField());
         assertEquals("userOwner", intAttrName.getField());
-        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchema());
         assertNull(intAttrName.getSchemaType());
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
@@ -93,8 +97,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("email", intAttrName.getSchemaName());
+        assertEquals("email", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof PlainSchema);
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
         assertNull(intAttrName.getRelatedAnyObject());
@@ -106,8 +111,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("cn", intAttrName.getSchemaName());
+        assertEquals("cn", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof DerSchema);
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
         assertNull(intAttrName.getRelatedAnyObject());
@@ -119,8 +125,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("rvirtualdata", intAttrName.getSchemaName());
+        assertEquals("rvirtualdata", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.VIRTUAL, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof VirSchema);
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
         assertNull(intAttrName.getRelatedAnyObject());
@@ -135,8 +142,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("cn", intAttrName.getSchemaName());
+        assertEquals("cn", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof DerSchema);
         assertEquals("readers", intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
         assertNull(intAttrName.getRelatedAnyObject());
@@ -151,8 +159,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("firstname", intAttrName.getSchemaName());
+        assertEquals("firstname", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof PlainSchema);
         assertEquals("bellini", intAttrName.getRelatedUser());
         assertNull(intAttrName.getEnclosingGroup());
         assertNull(intAttrName.getMembershipOfGroup());
@@ -167,7 +176,7 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
         assertEquals("name", intAttrName.getField());
-        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchema());
         assertNull(intAttrName.getSchemaType());
         assertNull(intAttrName.getEnclosingGroup());
         assertEquals("hp", intAttrName.getRelatedAnyObject());
@@ -183,8 +192,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("cn", intAttrName.getSchemaName());
+        assertEquals("cn", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof DerSchema);
         assertNull(intAttrName.getEnclosingGroup());
         assertEquals("top", intAttrName.getMembershipOfGroup());
         assertNull(intAttrName.getRelatedAnyObject());
@@ -200,8 +210,9 @@ public class IntAttrNameParserTest extends AbstractTest {
         assertNotNull(intAttrName);
         assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
         assertNull(intAttrName.getField());
-        assertEquals("location", intAttrName.getSchemaName());
+        assertEquals("location", intAttrName.getSchema().getKey());
         assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+        assertTrue(intAttrName.getSchema() instanceof PlainSchema);
         assertEquals("inclusion", intAttrName.getRelationshipType());
         assertEquals("PRINTER", intAttrName.getRelationshipAnyType());
         assertNull(intAttrName.getEnclosingGroup());
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
index b1eb869..e5fd10e 100644
--- a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/oidc/OIDCUserManager.java
@@ -34,9 +34,11 @@ import org.apache.syncope.common.lib.to.OIDCLoginResponseTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
+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.OIDCProvider;
 import org.apache.syncope.core.persistence.api.entity.OIDCProviderItem;
@@ -133,12 +135,11 @@ public class OIDCUserManager {
                 case PLAIN:
                     PlainAttrValue value = entityFactory.newEntity(UPlainAttrValue.class);
 
-                    PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
-                    if (schema == null) {
+                    if (intAttrName.getSchemaType() == SchemaType.PLAIN) {
                         value.setStringValue(transformed);
                     } else {
                         try {
-                            value.parseValue(schema, transformed);
+                            value.parseValue((PlainSchema) intAttrName.getSchema(), transformed);
                         } catch (ParsingValidationException e) {
                             LOG.error("While parsing provided key value {}", transformed, e);
                             value.setStringValue(transformed);
@@ -146,7 +147,7 @@ public class OIDCUserManager {
                     }
 
                     CollectionUtils.collect(
-                            userDAO.findByPlainAttrValue(intAttrName.getSchemaName(), value),
+                            userDAO.findByPlainAttrValue((PlainSchema) intAttrName.getSchema(), value),
                             new Transformer<User, String>() {
 
                         @Override
@@ -158,7 +159,7 @@ public class OIDCUserManager {
 
                 case DERIVED:
                     CollectionUtils.collect(
-                            userDAO.findByDerAttrValue(intAttrName.getSchemaName(), transformed),
+                            userDAO.findByDerAttrValue((DerSchema) intAttrName.getSchema(), transformed),
                             new Transformer<User, String>() {
 
                         @Override
@@ -233,9 +234,9 @@ public class OIDCUserManager {
             } else if (intAttrName != null && intAttrName.getSchemaType() != null) {
                 switch (intAttrName.getSchemaType()) {
                     case PLAIN:
-                        AttrTO attr = userTO.getPlainAttr(intAttrName.getSchemaName());
+                        AttrTO attr = userTO.getPlainAttr(intAttrName.getSchema().getKey());
                         if (attr == null) {
-                            attr = new AttrTO.Builder().schema(intAttrName.getSchemaName()).build();
+                            attr = new AttrTO.Builder().schema(intAttrName.getSchema().getKey()).build();
                             userTO.getPlainAttrs().add(attr);
                         }
                         attr.getValues().clear();
@@ -243,7 +244,7 @@ public class OIDCUserManager {
                         break;
 
                     default:
-                        LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchemaName());
+                        LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchema().getKey());
                 }
             }
         }
diff --git a/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
index 1849fe3..22d3461 100644
--- a/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
+++ b/ext/oidcclient/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/OIDCProviderDataBinderImpl.java
@@ -112,15 +112,15 @@ public class OIDCProviderDataBinderImpl implements OIDCProviderDataBinder {
                             && intAttrName.getRelatedAnyObject() == null) {
                         switch (intAttrName.getSchemaType()) {
                             case PLAIN:
-                                allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             case DERIVED:
-                                allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             case VIRTUAL:
-                                allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             default:
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
index 3a3cc48..33cfe6d 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/saml2/SAML2UserManager.java
@@ -35,9 +35,11 @@ import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.SAML2LoginResponseTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
+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.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
@@ -132,12 +134,11 @@ public class SAML2UserManager {
                 case PLAIN:
                     PlainAttrValue value = entityFactory.newEntity(UPlainAttrValue.class);
 
-                    PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
-                    if (schema == null) {
+                    if (intAttrName.getSchemaType() == SchemaType.PLAIN) {
                         value.setStringValue(transformed);
                     } else {
                         try {
-                            value.parseValue(schema, transformed);
+                            value.parseValue((PlainSchema) intAttrName.getSchema(), transformed);
                         } catch (ParsingValidationException e) {
                             LOG.error("While parsing provided key value {}", transformed, e);
                             value.setStringValue(transformed);
@@ -145,7 +146,7 @@ public class SAML2UserManager {
                     }
 
                     CollectionUtils.collect(
-                            userDAO.findByPlainAttrValue(intAttrName.getSchemaName(), value),
+                            userDAO.findByPlainAttrValue((PlainSchema) intAttrName.getSchema(), value),
                             new Transformer<User, String>() {
 
                         @Override
@@ -157,7 +158,7 @@ public class SAML2UserManager {
 
                 case DERIVED:
                     CollectionUtils.collect(
-                            userDAO.findByDerAttrValue(intAttrName.getSchemaName(), transformed),
+                            userDAO.findByDerAttrValue((DerSchema) intAttrName.getSchema(), transformed),
                             new Transformer<User, String>() {
 
                         @Override
@@ -230,9 +231,9 @@ public class SAML2UserManager {
             } else if (intAttrName != null && intAttrName.getSchemaType() != null) {
                 switch (intAttrName.getSchemaType()) {
                     case PLAIN:
-                        AttrTO attr = userTO.getPlainAttr(intAttrName.getSchemaName());
+                        AttrTO attr = userTO.getPlainAttr(intAttrName.getSchema().getKey());
                         if (attr == null) {
-                            attr = new AttrTO.Builder().schema(intAttrName.getSchemaName()).build();
+                            attr = new AttrTO.Builder().schema(intAttrName.getSchema().getKey()).build();
                             userTO.getPlainAttrs().add(attr);
                         }
                         attr.getValues().clear();
@@ -240,7 +241,7 @@ public class SAML2UserManager {
                         break;
 
                     default:
-                        LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchemaName());
+                        LOG.warn("Unsupported: {} {}", intAttrName.getSchemaType(), intAttrName.getSchema().getKey());
                 }
             }
         }
diff --git a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
index 0c59385..7df199d 100644
--- a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
+++ b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java
@@ -112,15 +112,15 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder {
                             && intAttrName.getRelatedAnyObject() == null) {
                         switch (intAttrName.getSchemaType()) {
                             case PLAIN:
-                                allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             case DERIVED:
-                                allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             case VIRTUAL:
-                                allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchemaName());
+                                allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchema().getKey());
                                 break;
 
                             default:
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DateToDateItemTransformer.java
similarity index 56%
copy from fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
copy to fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DateToDateItemTransformer.java
index 80a386e..1145638 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DateToDateItemTransformer.java
@@ -18,49 +18,33 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 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.data.DefaultItemTransformer;
 
-public class PrefixItemTransformer extends DefaultItemTransformer {
-
-    public static final String PREFIX = "PREFIX_";
+public class DateToDateItemTransformer extends DefaultItemTransformer {
 
     @Override
-    public List<PlainAttrValue> beforePropagation(
+    public Pair<AttrSchemaType, List<PlainAttrValue>> beforePropagation(
             final Item item,
             final Entity entity,
+            final AttrSchemaType schemaType,
             final List<PlainAttrValue> values) {
 
-        if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
-            return super.beforePropagation(item, entity, values);
-        } else {
-            String value = values.get(0).getStringValue();
-            values.get(0).setStringValue(PREFIX + value);
-
-            return values;
-        }
-    }
-
-    @Override
-    public List<Object> beforePull(
-            final Item item,
-            final EntityTO entityTO,
-            final List<Object> values) {
-
-        if (values == null || values.isEmpty() || values.get(0) == null) {
-            return super.beforePull(item, entityTO, values);
+        if (values == null || values.isEmpty() || values.get(0).getDateValue() == null) {
+            return super.beforePropagation(item, entity, schemaType, values);
         } else {
-            List<Object> newValues = new ArrayList<>(values);
-            newValues.set(0, StringUtils.substringAfter(values.get(0).toString(), PREFIX));
+            Calendar cal = Calendar.getInstance();
+            cal.setTime(values.get(0).getDateValue());
+            cal.add(Calendar.DAY_OF_MONTH, 1);
+            values.get(0).setDateValue(cal.getTime());
 
-            return newValues;
+            return Pair.of(schemaType, values);
         }
     }
-
 }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DateToLongItemTransformer.java
similarity index 56%
copy from fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
copy to fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DateToLongItemTransformer.java
index 80a386e..33aec06 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/DateToLongItemTransformer.java
@@ -18,49 +18,34 @@
  */
 package org.apache.syncope.fit.core.reference;
 
-import java.util.ArrayList;
 import java.util.List;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 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.data.DefaultItemTransformer;
 
-public class PrefixItemTransformer extends DefaultItemTransformer {
-
-    public static final String PREFIX = "PREFIX_";
+public class DateToLongItemTransformer extends DefaultItemTransformer {
 
     @Override
-    public List<PlainAttrValue> beforePropagation(
+    public Pair<AttrSchemaType, List<PlainAttrValue>> beforePropagation(
             final Item item,
             final Entity entity,
+            final AttrSchemaType schemaType,
             final List<PlainAttrValue> values) {
 
-        if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
-            return super.beforePropagation(item, entity, values);
+        if (values == null || values.isEmpty() || values.get(0).getDateValue() == null) {
+            return super.beforePropagation(item, entity, schemaType, values);
         } else {
-            String value = values.get(0).getStringValue();
-            values.get(0).setStringValue(PREFIX + value);
-
-            return values;
+            values.get(0).setLongValue(values.get(0).getDateValue().getTime());
+            values.get(0).setBinaryValue(null);
+            values.get(0).setBooleanValue(null);
+            values.get(0).setDateValue(null);
+            values.get(0).setDoubleValue(null);
+            values.get(0).setStringValue(null);
+
+            return Pair.of(AttrSchemaType.Long, values);
         }
     }
-
-    @Override
-    public List<Object> beforePull(
-            final Item item,
-            final EntityTO entityTO,
-            final List<Object> values) {
-
-        if (values == null || values.isEmpty() || values.get(0) == null) {
-            return super.beforePull(item, entityTO, values);
-        } else {
-            List<Object> newValues = new ArrayList<>(values);
-            newValues.set(0, StringUtils.substringAfter(values.get(0).toString(), PREFIX));
-
-            return newValues;
-        }
-    }
-
 }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
index 6b828e3..5e24483 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
@@ -107,6 +107,8 @@ public class ITImplementationLookup implements ImplementationLookup {
             put(Type.PASSWORD_RULE_CONF, classNames);
 
             classNames = new HashSet<>();
+            classNames.add(DateToDateItemTransformer.class.getName());
+            classNames.add(DateToLongItemTransformer.class.getName());
             classNames.add(PrefixItemTransformer.class.getName());
             classNames.add(DefaultItemTransformer.class.getName());
             put(Type.ITEM_TRANSFORMER, classNames);
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
index 80a386e..65a9d9f 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixItemTransformer.java
@@ -21,7 +21,9 @@ package org.apache.syncope.fit.core.reference;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 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;
@@ -32,18 +34,19 @@ public class PrefixItemTransformer extends DefaultItemTransformer {
     public static final String PREFIX = "PREFIX_";
 
     @Override
-    public List<PlainAttrValue> beforePropagation(
+    public Pair<AttrSchemaType, List<PlainAttrValue>> beforePropagation(
             final Item item,
             final Entity entity,
+            final AttrSchemaType schemaType,
             final List<PlainAttrValue> values) {
 
         if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
-            return super.beforePropagation(item, entity, values);
+            return super.beforePropagation(item, entity, schemaType, values);
         } else {
             String value = values.get(0).getStringValue();
             values.get(0).setStringValue(PREFIX + value);
 
-            return values;
+            return Pair.of(schemaType, values);
         }
     }
 
@@ -62,5 +65,4 @@ public class PrefixItemTransformer extends DefaultItemTransformer {
             return newValues;
         }
     }
-
 }
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index d17ecbe..5692667 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -23,13 +23,21 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.TaskTO;
@@ -45,11 +53,17 @@ import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
 import org.apache.syncope.common.rest.api.beans.ExecQuery;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.apache.syncope.fit.core.reference.DateToDateItemTransformer;
+import org.apache.syncope.fit.core.reference.DateToLongItemTransformer;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.AttributeUtil;
 import org.junit.Test;
 
 public class PropagationTaskITCase extends AbstractTaskITCase {
@@ -276,4 +290,114 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
         assertTrue(orderedTasks.getResult().equals(unorderedTasks.getResult()));
     }
 
+    @Test
+    public void issueSYNCOPE1430() throws ParseException {
+        ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP);
+        try {
+            // 1. clone the LDAP resource and add some sensible mappings
+            ProvisionTO provision = ldap.getProvision(AnyTypeKind.USER.name());
+            assertNotNull(provision);
+            CollectionUtils.filterInverse(provision.getMapping().getItems(), new Predicate<ItemTO>() {
+
+                @Override
+                public boolean evaluate(final ItemTO item) {
+                    return "mail".equals(item.getExtAttrName());
+                }
+            });
+            provision.getVirSchemas().clear();
+
+            // Date -> long (JEXL expression) -> string (as all JEXL in Syncope)
+            ItemTO loginDateForJexlAsLong = new ItemTO();
+            loginDateForJexlAsLong.setPurpose(MappingPurpose.PROPAGATION);
+            loginDateForJexlAsLong.setIntAttrName("loginDate");
+            loginDateForJexlAsLong.setExtAttrName("employeeNumber");
+            loginDateForJexlAsLong.setPropagationJEXLTransformer("value.getTime()");
+            provision.getMapping().add(loginDateForJexlAsLong);
+
+            // Date -> string (JEXL expression)
+            ItemTO loginDateForJexlAsString = new ItemTO();
+            loginDateForJexlAsString.setPurpose(MappingPurpose.PROPAGATION);
+            loginDateForJexlAsString.setIntAttrName("loginDate");
+            loginDateForJexlAsString.setExtAttrName("street");
+            loginDateForJexlAsString.setPropagationJEXLTransformer(
+                    "value.toInstant().toString().split(\"T\")[0].replace(\"-\", \"\")");
+            provision.getMapping().add(loginDateForJexlAsString);
+
+            // Date -> long
+            ItemTO loginDateForJavaToLong = new ItemTO();
+            loginDateForJavaToLong.setPurpose(MappingPurpose.PROPAGATION);
+            loginDateForJavaToLong.setIntAttrName("loginDate");
+            loginDateForJavaToLong.setExtAttrName("st");
+            loginDateForJavaToLong.getTransformerClassNames().add(DateToLongItemTransformer.class.getName());
+            provision.getMapping().add(loginDateForJavaToLong);
+
+            // Date -> date
+            ItemTO loginDateForJavaToDate = new ItemTO();
+            loginDateForJavaToDate.setPurpose(MappingPurpose.PROPAGATION);
+            loginDateForJavaToDate.setIntAttrName("loginDate");
+            loginDateForJavaToDate.setExtAttrName("carLicense");
+            loginDateForJavaToDate.getTransformerClassNames().add(DateToDateItemTransformer.class.getName());
+            provision.getMapping().add(loginDateForJavaToDate);
+
+            ldap.getProvisions().clear();
+            ldap.getProvisions().add(provision);
+            ldap.setKey(RESOURCE_NAME_LDAP + "1430" + getUUIDString());
+            resourceService.create(ldap);
+
+            // 2. create user with the new resource assigned
+            UserTO user = UserITCase.getUniqueSampleTO("syncope1430@syncope.apache.org");
+            user.getResources().clear();
+            user.getResources().add(ldap.getKey());
+            CollectionUtils.filterInverse(user.getPlainAttrs(), new Predicate<AttrTO>() {
+
+                @Override
+                public boolean evaluate(final AttrTO attr) {
+                    return "loginDate".equals(attr.getSchema());
+                }
+            });
+            user.getPlainAttrs().add(attrTO("loginDate", "2019-01-29"));
+            user = createUser(user).getEntity();
+
+            // 3. check attributes prepared for propagation
+            PagedResult<PropagationTaskTO> tasks = taskService.search(new TaskQuery.Builder(TaskType.PROPAGATION).
+                    resource(user.getResources().iterator().next()).
+                    anyTypeKind(AnyTypeKind.USER).entityKey(user.getKey()).build());
+            assertEquals(1, tasks.getSize());
+
+            Set<Attribute> propagationAttrs = new HashSet<>();
+            if (StringUtils.isNotBlank(tasks.getResult().get(0).getAttributes())) {
+                propagationAttrs.addAll(Arrays.asList(
+                        POJOHelper.deserialize(tasks.getResult().get(0).getAttributes(), Attribute[].class)));
+            }
+
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+
+            Calendar loginDate = Calendar.getInstance();
+            loginDate.setTime(sdf.parse(user.getPlainAttr("loginDate").getValues().get(0)));
+
+            Attribute employeeNumber = AttributeUtil.find("employeeNumber", propagationAttrs);
+            assertNotNull(employeeNumber);
+            assertEquals(String.valueOf(loginDate.getTimeInMillis()), employeeNumber.getValue().get(0));
+
+            Attribute street = AttributeUtil.find("street", propagationAttrs);
+            assertNotNull(street);
+            assertEquals(loginDate.toInstant().toString().split("T")[0].replace("-", ""), street.getValue().get(0));
+
+            Attribute st = AttributeUtil.find("st", propagationAttrs);
+            assertNotNull(st);
+            assertEquals(loginDate.getTimeInMillis(), st.getValue().get(0));
+
+            loginDate.add(Calendar.DAY_OF_MONTH, 1);
+
+            Attribute carLicense = AttributeUtil.find("carLicense", propagationAttrs);
+            assertNotNull(carLicense);
+            assertEquals(sdf.format(loginDate.getTime()), carLicense.getValue().get(0));
+        } finally {
+            try {
+                resourceService.delete(ldap.getKey());
+            } catch (Exception ignore) {
+                // ignore
+            }
+        }
+    }
 }
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
index 0efb6ae..01ddec4 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
@@ -710,5 +710,4 @@ public class VirAttrITCase extends AbstractITCase {
             }
         }
     }
-
 }