You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/10/22 14:26:55 UTC

[01/10] syncope git commit: Complete JRebel profile on fit/console-reference

Repository: syncope
Updated Branches:
  refs/heads/master 80f2548a0 -> 55fdc58c9


Complete JRebel profile on fit/console-reference


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

Branch: refs/heads/master
Commit: ef28d8e680f2003d99eaf5eb7f3c5af027a99cc6
Parents: 80f2548
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Oct 15 12:34:26 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Oct 22 11:40:32 2015 +0200

----------------------------------------------------------------------
 fit/console-reference/pom.xml | 70 ++++++++++++++++++++++++++++++++++++++
 fit/core-reference/pom.xml    |  1 +
 2 files changed, 71 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/ef28d8e6/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index 7227f04..b518886 100644
--- a/fit/console-reference/pom.xml
+++ b/fit/console-reference/pom.xml
@@ -453,6 +453,71 @@ ORYX.Editor.createByUrl = function(modelUrl){"/>
                   <resource>
                     <directory>${basedir}/../../common/rest-api/target/classes</directory>
                   </resource>
+
+                  <resource>
+                    <directory>${basedir}/../../core/logic/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/rest-cxf/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/misc/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/persistence-api/target/classes</directory>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/persistence-jpa/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/provisioning-api/target/classes</directory>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/provisioning-java/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/workflow-api/target/classes</directory>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/workflow-java/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../core/workflow-activiti/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../ext/camel/provisioning-camel/target/classes</directory>
+                    <excludes>
+                      <exclude>*Context.xml</exclude>
+                    </excludes>
+                  </resource>
+
+                  <resource>
+                    <directory>${basedir}/../../common/lib/target/classes</directory>
+                  </resource>
+                  <resource>
+                    <directory>${basedir}/../../common/rest-api/target/classes</directory>
+                  </resource>
                   <resource>
                     <directory>${basedir}/../../core/logic/target/classes</directory>
                     <excludes>
@@ -523,6 +588,11 @@ ORYX.Editor.createByUrl = function(modelUrl){"/>
                 <resources>
                   <resource>
                     <target>/</target>
+                    <directory>${basedir}/../../ext/swagger-ui/target/classes/META-INF/resources</directory>
+                  </resource>
+
+                  <resource>
+                    <target>/</target>
                     <directory>${basedir}/../../client/console/target/classes/META-INF/resources/</directory>
                   </resource>
                   <resource>

http://git-wip-us.apache.org/repos/asf/syncope/blob/ef28d8e6/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 8f4f62a..7e0fd9f 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -754,6 +754,7 @@ under the License.
                   <resource>
                     <directory>${basedir}/../../common/rest-api/target/classes</directory>
                   </resource>
+
                   <resource>
                     <directory>${basedir}/../../core/logic/target/classes</directory>
                     <excludes>


[09/10] syncope git commit: [SYNCOPE-715] Implemented

Posted by il...@apache.org.
[SYNCOPE-715] Implemented


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

Branch: refs/heads/master
Commit: fa5e65aa95fae91387d3c1ba4992ceb5bd3e4b6c
Parents: e20dd0a
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Oct 22 13:59:44 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Oct 22 13:59:44 2015 +0200

----------------------------------------------------------------------
 .../apache/syncope/core/logic/UserLogic.java    | 27 ++++++-------
 .../core/persistence/jpa/dao/JPAConfDAO.java    | 28 +++++++------
 .../main/resources/domains/MasterContent.xml    |  6 +++
 .../persistence/jpa/inner/MultitenancyTest.java |  2 +-
 .../persistence/jpa/inner/PlainSchemaTest.java  |  2 +-
 .../test/resources/domains/MasterContent.xml    |  8 +++-
 .../src/test/resources/domains/TwoContent.xml   |  6 +++
 .../provisioning/api/data/UserDataBinder.java   |  2 +
 .../java/data/UserDataBinderImpl.java           |  9 +++++
 .../fit/core/reference/MultitenancyITCase.java  |  2 +-
 .../fit/core/reference/SyncTaskITCase.java      | 41 +++++++++-----------
 .../syncope/fit/core/reference/UserITCase.java  |  8 ++--
 12 files changed, 87 insertions(+), 54 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index 776f427..deab762 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -121,7 +121,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
 
                     @Override
                     public UserTO transform(final User input) {
-                        return binder.getUserTO(input, details);
+                        return binder.returnUserTO(binder.getUserTO(input, details));
                     }
                 }, new ArrayList<UserTO>());
     }
@@ -131,14 +131,14 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
     public Pair<String, UserTO> readSelf() {
         return ImmutablePair.of(
                 POJOHelper.serialize(AuthContextUtils.getAuthorizations()),
-                binder.getAuthenticatedUserTO());
+                binder.returnUserTO(binder.getAuthenticatedUserTO()));
     }
 
     @PreAuthorize("hasRole('" + Entitlement.USER_READ + "')")
     @Transactional(readOnly = true)
     @Override
     public UserTO read(final Long key) {
-        return binder.getUserTO(key);
+        return binder.returnUserTO(binder.getUserTO(key));
     }
 
     @PreAuthorize("hasRole('" + Entitlement.USER_SEARCH + "')")
@@ -163,7 +163,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
 
             @Override
             public UserTO transform(final User input) {
-                return binder.getUserTO(input, details);
+                return binder.returnUserTO(binder.getUserTO(input, details));
             }
         }, new ArrayList<UserTO>());
     }
@@ -203,7 +203,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
         UserTO savedTO = binder.getUserTO(created.getKey());
         savedTO.getPropagationStatusTOs().addAll(created.getValue());
 
-        return afterCreate(savedTO, before.getValue());
+        return binder.returnUserTO(afterCreate(savedTO, before.getValue()));
     }
 
     @PreAuthorize("isAuthenticated() and not(hasRole('" + Entitlement.ANONYMOUS + "'))")
@@ -240,7 +240,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
         UserTO updatedTO = binder.getUserTO(updated.getKey());
         updatedTO.getPropagationStatusTOs().addAll(updated.getValue());
 
-        return afterUpdate(updatedTO, before.getRight());
+        return binder.returnUserTO(afterUpdate(updatedTO, before.getRight()));
     }
 
     protected Map.Entry<Long, List<PropagationStatus>> setStatusOnWfAdapter(final StatusPatch statusPatch) {
@@ -277,7 +277,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
         Map.Entry<Long, List<PropagationStatus>> updated = setStatusOnWfAdapter(statusPatch);
         UserTO savedTO = binder.getUserTO(updated.getKey());
         savedTO.getPropagationStatusTOs().addAll(updated.getValue());
-        return savedTO;
+        return binder.returnUserTO(savedTO);
     }
 
     @PreAuthorize("hasRole('" + Entitlement.MUST_CHANGE_PASSWORD + "')")
@@ -366,7 +366,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
         }
         deletedTO.getPropagationStatusTOs().addAll(statuses);
 
-        return afterDelete(deletedTO, before.getRight());
+        return binder.returnUserTO(afterDelete(deletedTO, before.getRight()));
     }
 
     @PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@@ -389,7 +389,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
             }
         }));
 
-        return binder.getUserTO(provisioningManager.unlink(patch));
+        return binder.returnUserTO(binder.getUserTO(provisioningManager.unlink(patch)));
     }
 
     @PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@@ -412,7 +412,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
             }
         }));
 
-        return binder.getUserTO(provisioningManager.link(patch));
+        return binder.returnUserTO(binder.getUserTO(provisioningManager.link(patch)));
     }
 
     @PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@@ -485,7 +485,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
 
         UserTO updatedTO = binder.getUserTO(key);
         updatedTO.getPropagationStatusTOs().addAll(statuses);
-        return updatedTO;
+        return binder.returnUserTO(updatedTO);
     }
 
     @PreAuthorize("hasRole('" + Entitlement.USER_UPDATE + "')")
@@ -504,7 +504,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
         securityChecks(effectiveRealms, user.getRealm(), user.getKey());
 
         user.getPropagationStatusTOs().addAll(provisioningManager.provision(key, changePwd, password, resources));
-        return user;
+        return binder.returnUserTO(user);
     }
 
     @Override
@@ -527,7 +527,8 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserPatch> {
 
         if ((key != null) && !key.equals(0L)) {
             try {
-                return key instanceof Long ? binder.getUserTO((Long) key) : binder.getUserTO((String) key);
+                return binder.returnUserTO(key instanceof Long
+                        ? binder.getUserTO((Long) key) : binder.getUserTO((String) key));
             } catch (Throwable ignore) {
                 LOG.debug("Unresolved reference", ignore);
                 throw new UnresolvedReferenceException(ignore);

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
index 4afe78e..985c7aa 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
@@ -22,6 +22,7 @@ import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.conf.Conf;
 import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainAttr;
@@ -64,19 +65,22 @@ public class JPAConfDAO extends AbstractDAO<Conf, Long> implements ConfDAO {
     public CPlainAttr find(final String key, final String defaultValue) {
         CPlainAttr result = find(key);
         if (result == null) {
-            JPACPlainAttr newAttr = new JPACPlainAttr();
-            newAttr.setSchema(schemaDAO.find(key));
-
-            JPACPlainAttrValue attrValue;
-            if (newAttr.getSchema().isUniqueConstraint()) {
-                attrValue = new JPACPlainAttrValue();
-                ((PlainAttrUniqueValue) attrValue).setSchema(newAttr.getSchema());
-            } else {
-                attrValue = new JPACPlainAttrValue();
+            PlainSchema schema = schemaDAO.find(key);
+            if (schema != null) {
+                JPACPlainAttr newAttr = new JPACPlainAttr();
+                newAttr.setSchema(schemaDAO.find(key));
+
+                JPACPlainAttrValue attrValue;
+                if (newAttr.getSchema().isUniqueConstraint()) {
+                    attrValue = new JPACPlainAttrValue();
+                    ((PlainAttrUniqueValue) attrValue).setSchema(newAttr.getSchema());
+                } else {
+                    attrValue = new JPACPlainAttrValue();
+                }
+                newAttr.add(defaultValue, attrValue);
+
+                result = newAttr;
             }
-            newAttr.add(defaultValue, attrValue);
-
-            result = newAttr;
         }
 
         return result;

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/domains/MasterContent.xml b/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
index 92216fd..ed1c035 100644
--- a/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
@@ -85,6 +85,12 @@ under the License.
   <CPlainAttr id="12" owner_id="1" schema_name="tasks.interruptMaxRetries"/>
   <CPlainAttrValue id="12" attribute_id="12" longValue="20"/>
 
+  <!-- Return hashed password values when reading users -->
+  <PlainSchema name="return.password.value" type="Boolean"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="14" owner_id="1" schema_name="return.password.value"/>
+  <CPlainAttrValue id="14" attribute_id="14" booleanValue="0"/>
+
   <AnyType name="USER" kind="USER"/>
   <AnyTypeClass name="BaseUser"/>
   <AnyType_AnyTypeClass anyType_name="USER" anyTypeClass_name="BaseUser"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/MultitenancyTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/MultitenancyTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/MultitenancyTest.java
index 074c26e..7d1dfea 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/MultitenancyTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/MultitenancyTest.java
@@ -83,7 +83,7 @@ public class MultitenancyTest extends AbstractTest {
 
     @Test
     public void readPlainSchemas() {
-        assertEquals(16, plainSchemaDAO.findAll().size());
+        assertEquals(17, plainSchemaDAO.findAll().size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
index c425460..21636b7 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
@@ -47,7 +47,7 @@ public class PlainSchemaTest extends AbstractTest {
     @Test
     public void findAll() {
         List<PlainSchema> schemas = plainSchemaDAO.findAll();
-        assertEquals(43, schemas.size());
+        assertEquals(44, schemas.size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 96e606f..d1fde9e 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -84,7 +84,13 @@ under the License.
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="12" owner_id="1" schema_name="tasks.interruptMaxRetries"/>
   <CPlainAttrValue id="12" attribute_id="12" longValue="20"/>
-
+  
+  <!-- Return hashed password values when reading users -->
+  <PlainSchema name="return.password.value" type="Boolean"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="14" owner_id="1" schema_name="return.password.value"/>
+  <CPlainAttrValue id="14" attribute_id="14" booleanValue="0"/>
+  
   <!-- For usage with admin console -->
   <PlainSchema name="admin.user.layout" type="String"
                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
index cce2ec8..cc36a9d 100644
--- a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
@@ -71,6 +71,12 @@ under the License.
   <CPlainAttr id="12" owner_id="1" schema_name="tasks.interruptMaxRetries"/>
   <CPlainAttrValue id="12" attribute_id="12" longValue="20"/>
 
+  <!-- Return hashed password values when reading users -->
+  <PlainSchema name="return.password.value" type="Boolean"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <CPlainAttr id="14" owner_id="1" schema_name="return.password.value"/>
+  <CPlainAttrValue id="14" attribute_id="14" booleanValue="0"/>
+  
   <AnyType name="USER" kind="USER"/>
   <AnyTypeClass name="BaseUser"/>
   <AnyType_AnyTypeClass anyType_name="USER" anyTypeClass_name="BaseUser"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/UserDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/UserDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/UserDataBinder.java
index ff645f4..9592a3f 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/UserDataBinder.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/UserDataBinder.java
@@ -25,6 +25,8 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 
 public interface UserDataBinder {
 
+    UserTO returnUserTO(UserTO userTO);
+
     UserTO getAuthenticatedUserTO();
 
     UserTO getUserTO(String username);

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 4bb7bdf..147683c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -101,6 +101,15 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
 
     @Transactional(readOnly = true)
     @Override
+    public UserTO returnUserTO(final UserTO userTO) {
+        if (!confDAO.find("return.password.value", "false").getValues().get(0).getBooleanValue()) {
+            userTO.setPassword(null);
+        }
+        return userTO;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
     public UserTO getAuthenticatedUserTO() {
         final UserTO authUserTO;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
index c1ce3b0..9a54b7f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/MultitenancyITCase.java
@@ -98,7 +98,7 @@ public class MultitenancyITCase extends AbstractITCase {
 
     @Test
     public void readPlainSchemas() {
-        assertEquals(16, adminClient.getService(SchemaService.class).list(SchemaType.PLAIN).size());
+        assertEquals(17, adminClient.getService(SchemaService.class).list(SchemaType.PLAIN).size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
index d645c77..e8ffd56 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
@@ -28,11 +28,13 @@ import static org.junit.Assert.fail;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import javax.ws.rs.core.Response;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
@@ -674,9 +676,9 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(Encryptor.getInstance().encode("security123", CipherAlgorithm.SHA1), value.toUpperCase());
 
         // 3. Update the password in the DB
-        String newPassword = Encryptor.getInstance().encode("new-security", CipherAlgorithm.SHA1);
-        jdbcTemplate.execute(
-                "UPDATE test set PASSWORD='" + newPassword + "' where ID='" + user.getUsername() + "'");
+        String newCleanPassword = "new-security";
+        String newPassword = Encryptor.getInstance().encode(newCleanPassword, CipherAlgorithm.SHA1);
+        jdbcTemplate.execute("UPDATE test set PASSWORD='" + newPassword + "' where ID='" + user.getUsername() + "'");
 
         // 4. Sync the user from the resource
         SyncTaskTO syncTask = new SyncTaskTO();
@@ -701,8 +703,8 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
 
         // 5. Test the sync'd user
-        UserTO updatedUser = userService.read(user.getKey());
-        assertEquals(newPassword, updatedUser.getPassword());
+        Pair<Map<String, Set<String>>, UserTO> self = clientFactory.create(user.getUsername(), newCleanPassword).self();
+        assertNotNull(self);
 
         // 6. Delete SyncTask + user
         taskService.delete(syncTask.getKey());
@@ -715,30 +717,31 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         ldapCleanup();
 
         // 1. create user in LDAP
+        String oldCleanPassword = "security123";
         UserTO user = UserITCase.getUniqueSampleTO("syncope313-ldap@syncope.apache.org");
-        user.setPassword("security123");
+        user.setPassword(oldCleanPassword);
         user.getResources().add(RESOURCE_NAME_LDAP);
         user = createUser(user);
         assertNotNull(user);
         assertFalse(user.getResources().isEmpty());
 
         // 2. request to change password only on Syncope and not on LDAP
+        String newCleanPassword = "new-security123";
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(user.getKey());
-        userPatch.setPassword(new PasswordPatch.Builder().value("new-security123").build());
-        updateUser(userPatch);
+        userPatch.setPassword(new PasswordPatch.Builder().value(newCleanPassword).build());
+        user = updateUser(userPatch);
 
         // 3. Check that the Syncope user now has the changed password
-        UserTO updatedUser = userService.read(user.getKey());
-        String encodedNewPassword = Encryptor.getInstance().encode("new-security123", CipherAlgorithm.SHA1);
-        assertEquals(encodedNewPassword, updatedUser.getPassword());
+        Pair<Map<String, Set<String>>, UserTO> self = clientFactory.create(user.getUsername(), newCleanPassword).self();
+        assertNotNull(self);
 
         // 4. Check that the LDAP resource has the old password
         ConnObjectTO connObject =
                 resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.USER.name(), user.getKey());
         assertNotNull(getLdapRemoteObject(
                 connObject.getPlainAttrMap().get(Name.NAME).getValues().get(0),
-                "security123",
+                oldCleanPassword,
                 connObject.getPlainAttrMap().get(Name.NAME).getValues().get(0)));
 
         // 5. Update the LDAP Connector to retrieve passwords
@@ -761,27 +764,21 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         syncTask.getActionsClassNames().add(LDAPPasswordSyncActions.class.getName());
         Response taskResponse = taskService.create(syncTask);
 
-        SyncTaskTO actual = getObject(taskResponse.getLocation(), TaskService.class, SyncTaskTO.class);
-        assertNotNull(actual);
-
-        syncTask = taskService.read(actual.getKey());
+        syncTask = getObject(taskResponse.getLocation(), TaskService.class, SyncTaskTO.class);
         assertNotNull(syncTask);
-        assertEquals(actual.getKey(), syncTask.getKey());
-        assertEquals(actual.getJobDelegateClassName(), syncTask.getJobDelegateClassName());
 
         TaskExecTO execution = execProvisioningTask(taskService, syncTask.getKey(), 50, false);
         assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
 
         // 7. Test the sync'd user
-        String syncedPassword = Encryptor.getInstance().encode("security123", CipherAlgorithm.SHA1);
-        updatedUser = userService.read(user.getKey());
-        assertEquals(syncedPassword, updatedUser.getPassword());
+        self = clientFactory.create(user.getUsername(), oldCleanPassword).self();
+        assertNotNull(self);
 
         // 8. Delete SyncTask + user + reset the connector
         taskService.delete(syncTask.getKey());
         property.getValues().clear();
         property.getValues().add(Boolean.FALSE);
         connectorService.update(resourceConnector);
-        deleteUser(updatedUser.getKey());
+        deleteUser(user.getKey());
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/fa5e65aa/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
index 91da759..ebaf02b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
@@ -569,6 +569,7 @@ public class UserITCase extends AbstractITCase {
         UserTO userTO = userService.read(1L);
 
         assertNotNull(userTO);
+        assertNull(userTO.getPassword());
         assertNotNull(userTO.getPlainAttrs());
         assertFalse(userTO.getPlainAttrs().isEmpty());
     }
@@ -2352,14 +2353,15 @@ public class UserITCase extends AbstractITCase {
         userTO = createUser(userTO);
         assertNotNull(userTO);
 
-        connObjectTO =
-                resourceService.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), userTO.getKey());
+        connObjectTO = resourceService.readConnObject(RESOURCE_NAME_CSV, AnyTypeKind.USER.name(), userTO.getKey());
         assertNotNull(connObjectTO);
 
         // check if password has been correctly propagated on Syncope and resource-csv as usual
         assertEquals("passwordTESTNULL1", connObjectTO.getPlainAttrMap().
                 get(OperationalAttributes.PASSWORD_NAME).getValues().get(0));
-        assertNotNull(userTO.getPassword());
+        Pair<Map<String, Set<String>>, UserTO> self =
+                clientFactory.create(userTO.getUsername(), "passwordTESTNULL1").self();
+        assertNotNull(self);
 
         // 4. add password policy to resource with passwordNotStore to false --> must store password
         ResourceTO csv = resourceService.read(RESOURCE_NAME_CSV);


[04/10] syncope git commit: [SYNCOPE-709] Refactoring completed

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
index 3d60089..5763449 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.provisioning.java;
 
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -27,26 +26,12 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
+import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.patch.AttrPatch;
-import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
-import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
-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;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 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;
@@ -68,30 +53,17 @@ import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
 @Component
-@Transactional(rollbackFor = { Throwable.class })
 public class VirAttrHandlerImpl implements VirAttrHandler {
 
     private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
 
     @Autowired
-    private VirSchemaDAO virSchemaDAO;
-
-    @Autowired
-    private VirAttrDAO virAttrDAO;
-
-    @Autowired
     private AnyObjectDAO anyObjectDAO;
 
     @Autowired
     private UserDAO userDAO;
 
     @Autowired
-    private GroupDAO groupDAO;
-
-    @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
-
-    @Autowired
     private ConnectorFactory connFactory;
 
     /**
@@ -103,290 +75,102 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
     @Autowired
     private MappingUtils mappingUtils;
 
-    @Override
-    public VirSchema getVirSchema(final String virSchemaName) {
-        VirSchema virtualSchema = null;
-        if (StringUtils.isNotBlank(virSchemaName)) {
-            virtualSchema = virSchemaDAO.find(virSchemaName);
-
-            if (virtualSchema == null) {
-                LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
-            }
+    private Map<VirSchema, List<String>> getValues(final Any<?, ?> any, final Set<VirSchema> schemas) {
+        Collection<? extends ExternalResource> ownedResources;
+        if (any instanceof User) {
+            ownedResources = userDAO.findAllResources((User) any);
+        } else if (any instanceof AnyObject) {
+            ownedResources = anyObjectDAO.findAllResources((AnyObject) any);
+        } else {
+            ownedResources = ((Group) any).getResources();
         }
 
-        return virtualSchema;
-    }
-
-    @Override
-    public void updateOnResourcesIfMappingMatches(final Any<?, ?, ?> any, final String schemaKey,
-            final Iterable<? extends ExternalResource> resources, final IntMappingType mappingType,
-            final PropagationByResource propByRes) {
+        Map<VirSchema, List<String>> result = new HashMap<>();
 
-        for (ExternalResource resource : resources) {
-            for (MappingItem mapItem
-                    : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+        Map<Provision, Set<VirSchema>> toRead = new HashMap<>();
 
-                if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
-                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
-                }
-            }
-        }
-    }
-
-    private Iterable<? extends ExternalResource> getAllResources(final Any<?, ?, ?> any) {
-        return any instanceof User
-                ? userDAO.findAllResources((User) any)
-                : any instanceof AnyObject
-                        ? anyObjectDAO.findAllResources((AnyObject) any)
-                        : any instanceof Group
-                                ? ((Group) any).getResources()
-                                : Collections.<ExternalResource>emptySet();
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @Override
-    public void createVirtual(final Any any, final Collection<AttrTO> vAttrs) {
-        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+        for (VirSchema schema : schemas) {
+            if (ownedResources.contains(schema.getProvision().getResource())) {
+                VirAttrCacheValue virAttrCacheValue =
+                        virAttrCache.get(any.getType().getKey(), any.getKey(), schema.getKey());
 
-        for (AttrTO attrTO : vAttrs) {
-            VirAttr virAttr = any.getVirAttr(attrTO.getSchema());
-            if (virAttr == null) {
-                VirSchema virSchema = getVirSchema(attrTO.getSchema());
-                if (virSchema != null) {
-                    virAttr = anyUtils.newVirAttr();
-                    virAttr.setSchema(virSchema);
-                    if (virAttr.getSchema() == null) {
-                        LOG.debug("Ignoring {} because no valid schema was found", attrTO);
-                    } else {
-                        virAttr.setOwner(any);
-                        any.add(virAttr);
-                        virAttr.getValues().clear();
-                        virAttr.getValues().addAll(attrTO.getValues());
+                if (virAttrCache.isValidEntry(virAttrCacheValue)) {
+                    LOG.debug("Values for {} found in cache: {}", schema, virAttrCacheValue);
+                    result.put(schema, virAttrCacheValue.getValues());
+                } else {
+                    Set<VirSchema> schemasToRead = toRead.get(schema.getProvision());
+                    if (schemasToRead == null) {
+                        schemasToRead = new HashSet<>();
+                        toRead.put(schema.getProvision(), schemasToRead);
                     }
+                    schemasToRead.add(schema);
                 }
             } else {
-                virAttr.getValues().clear();
-                virAttr.getValues().addAll(attrTO.getValues());
+                LOG.debug("Not considering {} since {} is not assigned to {}",
+                        schema, any, schema.getProvision().getResource());
             }
         }
-    }
-
-    private Any<?, ?, ?> find(final Long key, final AnyTypeKind anyTypeKind) {
-        Any<?, ?, ?> result;
-
-        switch (anyTypeKind) {
-            case USER:
-                result = userDAO.authFind(key);
-                break;
-
-            case GROUP:
-                result = groupDAO.authFind(key);
-                break;
-
-            case ANY_OBJECT:
-            default:
-                result = anyObjectDAO.authFind(key);
-        }
-
-        return result;
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    @Override
-    public PropagationByResource updateVirtual(final Any any, final Collection<AttrPatch> vAttrs) {
-        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-
-        PropagationByResource propByRes = new PropagationByResource();
-
-        Iterable<? extends ExternalResource> externalResources = getAllResources(any);
-
-        for (AttrPatch patch : vAttrs) {
-            VirSchema virSchema = getVirSchema(patch.getAttrTO().getSchema());
-            if (virSchema != null) {
-                VirAttr virAttr = any.getVirAttr(virSchema.getKey());
-                switch (patch.getOperation()) {
-                    case ADD_REPLACE:
-                        if (virAttr == null) {
-                            virAttr = anyUtils.newVirAttr();
-                            virAttr.setOwner(any);
-                            virAttr.setSchema(virSchema);
-
-                            any.add(virAttr);
-                        }
-
-                        updateOnResourcesIfMappingMatches(
-                                any, virSchema.getKey(), externalResources, anyUtils.virIntMappingType(), propByRes);
-
-                        if (!virAttr.getValues().equals(patch.getAttrTO().getValues())) {
-                            virAttr.getValues().clear();
-                            virAttr.getValues().addAll(patch.getAttrTO().getValues());
-                        }
-                        break;
-
-                    case DELETE:
-                    default:
-                        if (virAttr == null) {
-                            LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
-                        } else {
-                            any.remove(virAttr);
-                            virAttrDAO.delete(virAttr);
-                        }
-
-                        for (ExternalResource resource : externalResources) {
-                            for (MappingItem mapItem
-                                    : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
 
-                                if (virSchema.getKey().equals(mapItem.getIntAttrName())
-                                        && mapItem.getIntMappingType() == anyUtils.virIntMappingType()) {
+        for (Map.Entry<Provision, Set<VirSchema>> entry : toRead.entrySet()) {
+            LOG.debug("About to read from {}: {}", entry.getKey(), entry.getValue());
 
-                                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
-
-                                    // Using virtual attribute as ConnObjectKey must be avoided
-                                    if (mapItem.isConnObjectKey()
-                                            && virAttr != null && !virAttr.getValues().isEmpty()) {
-
-                                        propByRes.addOldConnObjectKey(
-                                                resource.getKey(), virAttr.getValues().get(0).toString());
-                                    }
-                                }
-                            }
-                        }
+            String connObjectKey = MappingUtils.getConnObjectKeyItem(entry.getKey()) == null
+                    ? null
+                    : mappingUtils.getConnObjectKeyValue(any, entry.getKey());
+            if (StringUtils.isBlank(connObjectKey)) {
+                LOG.error("No ConnObjectKey found for {}, ignoring...", entry.getKey());
+            } else {
+                Set<MappingItem> linkingMappingItems = new HashSet<>();
+                for (VirSchema schema : entry.getValue()) {
+                    linkingMappingItems.add(schema.asLinkingMappingItem());
                 }
-            }
-        }
-
-        return propByRes;
-    }
-
-    @Transactional
-    @Override
-    public PropagationByResource updateVirtual(
-            final Long key, final AnyTypeKind anyTypeKind, final Collection<AttrPatch> vAttrs) {
-
-        return updateVirtual(find(key, anyTypeKind), vAttrs);
-    }
-
-    @Override
-    public void retrieveVirAttrValues(final Any<?, ?, ?> any) {
-        IntMappingType type = any.getType().getKind() == AnyTypeKind.USER
-                ? IntMappingType.UserVirtualSchema
-                : any.getType().getKind() == AnyTypeKind.GROUP
-                        ? IntMappingType.GroupVirtualSchema
-                        : IntMappingType.AnyObjectVirtualSchema;
-
-        Map<String, ConnectorObject> resources = new HashMap<>();
-
-        // -----------------------
-        // Retrieve virtual attribute values if and only if they have not been retrieved yet
-        // -----------------------
-        for (VirAttr<?> virAttr : any.getVirAttrs()) {
-            // reset value set
-            if (virAttr.getValues().isEmpty()) {
-                retrieveVirAttrValue(any, virAttr, type, resources);
-            }
-        }
-        // -----------------------
-    }
-
-    private void retrieveVirAttrValue(
-            final Any<?, ?, ?> any,
-            final VirAttr<?> virAttr,
-            final IntMappingType type,
-            final Map<String, ConnectorObject> externalResources) {
-
-        String schemaName = virAttr.getSchema().getKey();
-        VirAttrCacheValue virAttrCacheValue = virAttrCache.get(any.getType().getKey(), any.getKey(), schemaName);
-
-        LOG.debug("Retrieve values for virtual attribute {} ({})", schemaName, type);
-
-        if (virAttrCache.isValidEntry(virAttrCacheValue)) {
-            // cached ...
-            LOG.debug("Values found in cache {}", virAttrCacheValue);
-            virAttr.getValues().clear();
-            virAttr.getValues().addAll(new ArrayList<>(virAttrCacheValue.getValues()));
-        } else {
-            // not cached ...
-            LOG.debug("Need one or more remote connections");
-
-            VirAttrCacheValue toBeCached = new VirAttrCacheValue();
-
-            for (ExternalResource resource : getTargetResources(virAttr, type, any.getType())) {
-                Provision provision = resource.getProvision(any.getType());
-                LOG.debug("Search values into {},{}", resource, provision);
 
+                Connector connector = connFactory.getConnector(entry.getKey().getResource());
                 try {
-                    List<MappingItem> mapItems = MappingUtils.getBothMappingItems(provision);
+                    ConnectorObject connectorObject = connector.getObject(
+                            entry.getKey().getObjectClass(),
+                            new Uid(connObjectKey),
+                            connector.getOperationOptions(linkingMappingItems.iterator()));
 
-                    ConnectorObject connectorObject;
-                    if (externalResources.containsKey(resource.getKey())) {
-                        connectorObject = externalResources.get(resource.getKey());
+                    if (connectorObject == null) {
+                        LOG.debug("No read from {} about {}", entry.getKey(), connObjectKey);
                     } else {
-                        LOG.debug("Perform connection to {}", resource.getKey());
-                        String connObjectKey = MappingUtils.getConnObjectKeyItem(provision) == null
-                                ? null
-                                : mappingUtils.getConnObjectKeyValue(any, provision);
-
-                        if (StringUtils.isBlank(connObjectKey)) {
-                            throw new IllegalArgumentException("No ConnObjectKey found for " + resource.getKey());
-                        }
-
-                        Connector connector = connFactory.getConnector(resource);
-                        connectorObject = connector.getObject(
-                                provision.getObjectClass(),
-                                new Uid(connObjectKey),
-                                connector.getOperationOptions(MappingUtils.getMatchingMappingItems(mapItems, type)));
-                        externalResources.put(resource.getKey(), connectorObject);
-                    }
-
-                    if (connectorObject != null) {
-                        // the same virtual attribute could be mapped with one or more external attributes
-                        for (MappingItem mapItem : MappingUtils.getMatchingMappingItems(mapItems, schemaName, type)) {
-                            Attribute attr = connectorObject.getAttributeByName(mapItem.getExtAttrName());
-                            if (attr != null && attr.getValue() != null) {
-                                for (Object obj : attr.getValue()) {
-                                    if (obj != null) {
-                                        virAttr.getValues().add(obj.toString());
-                                    }
-                                }
+                        for (VirSchema schema : entry.getValue()) {
+                            Attribute attr = connectorObject.getAttributeByName(schema.getExtAttrName());
+                            if (attr != null) {
+                                VirAttrCacheValue virAttrCacheValue = new VirAttrCacheValue();
+                                virAttrCacheValue.setValues(attr.getValue());
+                                virAttrCache.put(any.getType().getKey(), any.getKey(), schema.getKey(),
+                                        virAttrCacheValue);
+                                LOG.debug("Values for {} set in cache: {}", schema, virAttrCacheValue);
+
+                                result.put(schema, virAttrCacheValue.getValues());
                             }
                         }
-
-                        toBeCached.setResourceValues(resource.getKey(), new HashSet<>(virAttr.getValues()));
-
-                        LOG.debug("Retrieved values {}", virAttr.getValues());
                     }
                 } catch (Exception e) {
-                    LOG.error("Error reading connector object from {}", resource.getKey(), e);
-
-                    if (virAttrCacheValue != null) {
-                        toBeCached.forceExpiring();
-                        LOG.debug("Search for a cached value (even expired!) ...");
-                        final Set<String> cachedValues = virAttrCacheValue.getValues(resource.getKey());
-                        if (cachedValues != null) {
-                            LOG.debug("Use cached value {}", cachedValues);
-                            virAttr.getValues().addAll(cachedValues);
-                            toBeCached.setResourceValues(resource.getKey(), new HashSet<>(cachedValues));
-                        }
-                    }
+                    LOG.error("Error reading from {}", entry.getKey(), e);
                 }
             }
-
-            virAttrCache.put(any.getType().getKey(), any.getKey(), schemaName, toBeCached);
         }
+
+        return result;
     }
 
-    private Collection<ExternalResource> getTargetResources(
-            final VirAttr<?> attr, final IntMappingType type, final AnyType anyType) {
+    @Transactional(readOnly = true)
+    @Override
+    public List<String> getValues(final Any<?, ?> any, final VirSchema schema) {
+        if (!any.getAllowedVirSchemas().contains(schema)) {
+            LOG.debug("{} not allowed for {}", schema, any);
+            return Collections.emptyList();
+        }
 
-        return CollectionUtils.select(getAllResources(attr.getOwner()), new Predicate<ExternalResource>() {
+        return ListUtils.emptyIfNull(getValues(any, Collections.singleton(schema)).get(schema));
+    }
 
-            @Override
-            public boolean evaluate(final ExternalResource resource) {
-                return resource.getProvision(anyType) != null
-                        && !MappingUtils.getMatchingMappingItems(
-                                MappingUtils.getBothMappingItems(resource.getProvision(anyType)),
-                                attr.getSchema().getKey(), type).isEmpty();
-            }
-        });
+    @Transactional(readOnly = true)
+    @Override
+    public Map<VirSchema, List<String>> getValues(final Any<?, ?> any) {
+        return getValues(any, any.getAllowedVirSchemas());
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/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 4a203f9..93a0b31 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
@@ -42,6 +42,7 @@ import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
 import org.apache.syncope.core.persistence.api.dao.DerAttrDAO;
@@ -53,7 +54,6 @@ import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
@@ -61,8 +61,6 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 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.VirAttr;
-import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.ConnObjectUtils;
@@ -80,6 +78,7 @@ import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.Membership;
 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.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -130,9 +129,6 @@ abstract class AbstractAnyDataBinder {
     protected DerAttrDAO derAttrDAO;
 
     @Autowired
-    protected VirAttrDAO virAttrDAO;
-
-    @Autowired
     protected PlainAttrValueDAO plainAttrValueDAO;
 
     @Autowired
@@ -159,7 +155,7 @@ abstract class AbstractAnyDataBinder {
     @Autowired
     protected MappingUtils mappingUtils;
 
-    protected void setRealm(final Any<?, ?, ?> any, final AnyPatch anyPatch) {
+    protected void setRealm(final Any<?, ?> any, final AnyPatch anyPatch) {
         if (anyPatch.getRealm() != null && StringUtils.isNotBlank(anyPatch.getRealm().getValue())) {
             Realm newRealm = realmDAO.find(anyPatch.getRealm().getValue());
             if (newRealm == null) {
@@ -225,7 +221,7 @@ abstract class AbstractAnyDataBinder {
         }
     }
 
-    private List<String> evaluateMandatoryCondition(final Provision provision, final Any<?, ?, ?> any) {
+    private List<String> evaluateMandatoryCondition(final Provision provision, final Any<?, ?> any) {
         List<String> missingAttrNames = new ArrayList<>();
 
         if (provision != null) {
@@ -235,7 +231,7 @@ abstract class AbstractAnyDataBinder {
                         || item.getPurpose() == MappingPurpose.BOTH)) {
 
                     List<PlainAttrValue> values = mappingUtils.getIntValues(
-                            provision, item, Collections.<Any<?, ?, ?>>singletonList(any), null);
+                            provision, item, Collections.<Any<?, ?>>singletonList(any));
                     if (values.isEmpty() && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
                         missingAttrNames.add(item.getIntAttrName());
                     }
@@ -247,7 +243,7 @@ abstract class AbstractAnyDataBinder {
     }
 
     private SyncopeClientException checkMandatoryOnResources(
-            final Any<?, ?, ?> any, final Set<ExternalResource> resources) {
+            final Any<?, ?> any, final Set<ExternalResource> resources) {
 
         SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
@@ -266,7 +262,7 @@ abstract class AbstractAnyDataBinder {
         return reqValMissing;
     }
 
-    private SyncopeClientException checkMandatory(final Any<?, ?, ?> any) {
+    private SyncopeClientException checkMandatory(final Any<?, ?> any) {
         SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
         // Check if there is some mandatory schema defined for which no value has been provided
@@ -284,7 +280,7 @@ abstract class AbstractAnyDataBinder {
         return reqValMissing;
     }
 
-    private Set<ExternalResource> getAllResources(final Any<?, ?, ?> any) {
+    private Set<ExternalResource> getAllResources(final Any<?, ?> any) {
         Set<ExternalResource> resources = new HashSet<>();
 
         if (any instanceof User) {
@@ -323,21 +319,26 @@ abstract class AbstractAnyDataBinder {
 
         switch (patch.getOperation()) {
             case ADD_REPLACE:
-                virAttrHander.updateOnResourcesIfMappingMatches(
-                        any, schema.getKey(), resources, anyUtils.plainIntMappingType(), propByRes);
-
                 // 1.1 remove values
-                Collection<Long> valuesToBeRemoved = attr.getSchema().isUniqueConstraint()
-                        ? Collections.singleton(attr.getUniqueValue().getKey())
-                        : CollectionUtils.collect(attr.getValues(), new Transformer<PlainAttrValue, Long>() {
-
-                            @Override
-                            public Long transform(final PlainAttrValue input) {
-                                return input.getKey();
-                            }
-                        });
-                for (Long attrValueKey : valuesToBeRemoved) {
-                    plainAttrValueDAO.delete(attrValueKey, anyUtils.plainAttrValueClass());
+                if (attr.getSchema().isUniqueConstraint()) {
+                    if (attr.getUniqueValue() != null
+                            && !patch.getAttrTO().getValues().isEmpty()
+                            && !patch.getAttrTO().getValues().get(0).equals(attr.getUniqueValue().getValueAsString())) {
+
+                        plainAttrValueDAO.delete(attr.getUniqueValue().getKey(), anyUtils.plainAttrUniqueValueClass());
+                    }
+                } else {
+                    Collection<Long> valuesToBeRemoved = CollectionUtils.collect(attr.getValues(),
+                            new Transformer<PlainAttrValue, Long>() {
+
+                                @Override
+                                public Long transform(final PlainAttrValue input) {
+                                    return input.getKey();
+                                }
+                            });
+                    for (Long attrValueKey : valuesToBeRemoved) {
+                        plainAttrValueDAO.delete(attrValueKey, anyUtils.plainAttrValueClass());
+                    }
                 }
 
                 // 1.2 add values
@@ -359,22 +360,20 @@ abstract class AbstractAnyDataBinder {
             default:
                 any.remove(attr);
                 plainAttrDAO.delete(attr.getKey(), anyUtils.plainAttrClass());
+        }
 
-                for (ExternalResource resource : resources) {
-                    for (MappingItem mapItem
-                            : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
-
-                        if (schema.getKey().equals(mapItem.getIntAttrName())
-                                && mapItem.getIntMappingType() == anyUtils.plainIntMappingType()) {
+        for (ExternalResource resource : resources) {
+            for (MappingItem mapItem : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+                if (schema.getKey().equals(mapItem.getIntAttrName())
+                        && mapItem.getIntMappingType() == anyUtils.plainIntMappingType()) {
 
-                            propByRes.add(ResourceOperation.UPDATE, resource.getKey());
+                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 
-                            if (mapItem.isConnObjectKey() && !attr.getValuesAsStrings().isEmpty()) {
-                                propByRes.addOldConnObjectKey(resource.getKey(), attr.getValuesAsStrings().get(0));
-                            }
-                        }
+                    if (mapItem.isConnObjectKey() && !attr.getValuesAsStrings().isEmpty()) {
+                        propByRes.addOldConnObjectKey(resource.getKey(), attr.getValuesAsStrings().get(0));
                     }
                 }
+            }
         }
     }
 
@@ -400,36 +399,26 @@ abstract class AbstractAnyDataBinder {
             }
         }
 
-        switch (patch.getOperation()) {
-            case ADD_REPLACE:
-                virAttrHander.updateOnResourcesIfMappingMatches(
-                        any, schema.getKey(), resources, anyUtils.derIntMappingType(), propByRes);
-                break;
-
-            case DELETE:
-            default:
-                derAttrDAO.delete(attr);
-
-                for (ExternalResource resource : resources) {
-                    for (MappingItem mapItem
-                            : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+        if (patch.getOperation() == PatchOperation.DELETE) {
+            derAttrDAO.delete(attr);
+        }
 
-                        if (schema.getKey().equals(mapItem.getIntAttrName())
-                                && mapItem.getIntMappingType() == anyUtils.derIntMappingType()) {
+        for (ExternalResource resource : resources) {
+            for (MappingItem mapItem : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+                if (schema.getKey().equals(mapItem.getIntAttrName())
+                        && mapItem.getIntMappingType() == anyUtils.derIntMappingType()) {
 
-                            propByRes.add(ResourceOperation.UPDATE, resource.getKey());
+                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 
-                            if (mapItem.isConnObjectKey() && !attr.getValue(any.getPlainAttrs()).isEmpty()) {
-                                propByRes.addOldConnObjectKey(resource.getKey(), attr.getValue(any.getPlainAttrs()));
-                            }
-                        }
+                    if (mapItem.isConnObjectKey() && !attr.getValue(any.getPlainAttrs()).isEmpty()) {
+                        propByRes.addOldConnObjectKey(resource.getKey(), attr.getValue(any.getPlainAttrs()));
                     }
                 }
+            }
         }
     }
 
-    @SuppressWarnings("rawtypes")
-    protected PropagationByResource fill(final Any any, final AnyPatch anyPatch, final AnyUtils anyUtils,
+    protected PropagationByResource fill(final Any<?, ?> any, final AnyPatch anyPatch, final AnyUtils anyUtils,
             final SyncopeClientCompositeException scce) {
 
         PropagationByResource propByRes = new PropagationByResource();
@@ -576,25 +565,12 @@ abstract class AbstractAnyDataBinder {
             }
         }
 
-        // 3. virtual attributes
-        for (AttrTO vattrTO : anyTO.getVirAttrs()) {
-            VirSchema virSchema = virAttrHander.getVirSchema(vattrTO.getSchema());
-            if (virSchema != null) {
-                VirAttr virAttr = anyUtils.newVirAttr();
-                virAttr.setOwner(any);
-                virAttr.setSchema(virSchema);
-                any.add(virAttr);
-            }
-        }
-
         SyncopeClientException requiredValuesMissing = checkMandatory(any);
         if (!requiredValuesMissing.isEmpty()) {
             scce.addException(requiredValuesMissing);
         }
 
-        virAttrHander.createVirtual(any, anyTO.getVirAttrs());
-
-        // 4. realm & resources
+        // 3. realm & resources
         Realm realm = realmDAO.find(anyTO.getRealm());
         if (realm == null) {
             SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
@@ -628,7 +604,7 @@ abstract class AbstractAnyDataBinder {
             final Collection<? extends AnyTypeClass> auxClasses,
             final Collection<? extends PlainAttr<?>> attrs,
             final Collection<? extends DerAttr<?>> derAttrs,
-            final Collection<? extends VirAttr<?>> virAttrs,
+            final Map<VirSchema, List<String>> virAttrs,
             final Collection<? extends ExternalResource> resources) {
 
         anyTO.setRealm(realmFullPath);
@@ -659,11 +635,11 @@ abstract class AbstractAnyDataBinder {
             anyTO.getDerAttrs().add(attrTO);
         }
 
-        for (VirAttr<?> virAttr : virAttrs) {
+        for (Map.Entry<VirSchema, List<String>> entry : virAttrs.entrySet()) {
             AttrTO attrTO = new AttrTO();
-            attrTO.setSchema(virAttr.getSchema().getKey());
-            attrTO.getValues().addAll(virAttr.getValues());
-            attrTO.setReadonly(virAttr.getSchema().isReadonly());
+            attrTO.setSchema(entry.getKey().getKey());
+            attrTO.getValues().addAll(entry.getValue());
+            attrTO.setReadonly(entry.getKey().isReadonly());
 
             anyTO.getVirAttrs().add(attrTO);
         }
@@ -673,21 +649,21 @@ abstract class AbstractAnyDataBinder {
         }
     }
 
-    protected RelationshipTO getRelationshipTO(final Relationship<? extends Any<?, ?, ?>, AnyObject> relationship) {
+    protected RelationshipTO getRelationshipTO(final Relationship<? extends Any<?, ?>, AnyObject> relationship) {
         return new RelationshipTO.Builder().
                 left(relationship.getLeftEnd().getType().getKey(), relationship.getLeftEnd().getKey()).
                 right(relationship.getRightEnd().getType().getKey(), relationship.getRightEnd().getKey()).
                 build();
     }
 
-    protected MembershipTO getMembershipTO(final Membership<? extends Any<?, ?, ?>> membership) {
+    protected MembershipTO getMembershipTO(final Membership<? extends Any<?, ?>> membership) {
         return new MembershipTO.Builder().
                 left(membership.getLeftEnd().getType().getKey(), membership.getLeftEnd().getKey()).
                 group(membership.getRightEnd().getKey(), membership.getRightEnd().getName()).
                 build();
     }
 
-    protected Map<String, String> getConnObjectKeys(final Any<?, ?, ?> any) {
+    protected Map<String, String> getConnObjectKeys(final Any<?, ?> any) {
         Map<String, String> connObjectKeys = new HashMap<>();
 
         Iterable<? extends ExternalResource> iterable = any instanceof User

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index 91edd7e..2dca6e4 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.provisioning.java.data;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
@@ -41,6 +43,7 @@ import org.apache.syncope.core.misc.spring.BeanUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -75,12 +78,12 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
         BeanUtils.copyProperties(anyObject, anyObjectTO, IGNORE_PROPERTIES);
 
-        if (details) {
-            virAttrHander.retrieveVirAttrValues(anyObject);
-        }
+        Map<VirSchema, List<String>> virAttrValues = details
+                ? virAttrHander.getValues(anyObject)
+                : Collections.<VirSchema, List<String>>emptyMap();
 
         fillTO(anyObjectTO, anyObject.getRealm().getFullPath(), anyObject.getAuxClasses(),
-                anyObject.getPlainAttrs(), anyObject.getDerAttrs(), anyObject.getVirAttrs(),
+                anyObject.getPlainAttrs(), anyObject.getDerAttrs(), virAttrValues,
                 anyObjectDAO.findAllResources(anyObject));
 
         if (details) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index 155034c..620cdf8 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
+import java.util.Collections;
+import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
@@ -34,6 +36,7 @@ import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.DynGroupMembership;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
 import org.springframework.stereotype.Component;
@@ -203,12 +206,12 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
             groupTO.setGroupOwner(group.getGroupOwner().getKey());
         }
 
-        if (details) {
-            virAttrHander.retrieveVirAttrValues(group);
-        }
+        Map<VirSchema, List<String>> virAttrValues = details
+                ? virAttrHander.getValues(group)
+                : Collections.<VirSchema, List<String>>emptyMap();
 
         fillTO(groupTO, group.getRealm().getFullPath(), group.getAuxClasses(),
-                group.getPlainAttrs(), group.getDerAttrs(), group.getVirAttrs(), group.getResources());
+                group.getPlainAttrs(), group.getDerAttrs(), virAttrValues, group.getResources());
 
         if (group.getADynMembership() != null) {
             groupTO.setADynMembershipCond(group.getADynMembership().getFIQLCond());

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/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 e5dfadf..d04dfd3 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
@@ -21,9 +21,8 @@ package org.apache.syncope.core.provisioning.java.data;
 import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
 import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -50,7 +49,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.syncope.core.misc.spring.BeanUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -76,6 +77,9 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
     private PolicyDAO policyDAO;
 
     @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
     private EntityFactory entityFactory;
 
     @Override
@@ -112,7 +116,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
         for (ProvisionTO provisionTO : resourceTO.getProvisions()) {
             AnyType anyType = anyTypeDAO.find(provisionTO.getAnyType());
             if (anyType == null) {
-                LOG.debug("Invalid AnyType specified {}, ignoring...", provisionTO.getAnyType());
+                LOG.debug("Invalid {} specified {}, ignoring...",
+                        AnyType.class.getSimpleName(), provisionTO.getAnyType());
             } else {
                 Provision provision = resource.getProvision(anyType);
                 if (provision == null) {
@@ -124,7 +129,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
                 if (provisionTO.getObjectClass() == null) {
                     SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidProvision);
-                    sce.getElements().add("Null ObjectClass");
+                    sce.getElements().add("Null " + ObjectClass.class.getSimpleName());
                     throw sce;
                 }
                 provision.setObjectClass(new ObjectClass(provisionTO.getObjectClass()));
@@ -146,17 +151,36 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                     }
                     populateMapping(provisionTO.getMapping(), mapping, entityFactory.newEntity(MappingItem.class));
                 }
+
+                if (provisionTO.getVirSchemas().isEmpty()) {
+                    for (VirSchema schema : virSchemaDAO.findByProvision(provision)) {
+                        virSchemaDAO.delete(schema.getKey());
+                    }
+                } else {
+                    for (String schemaName : provisionTO.getVirSchemas()) {
+                        VirSchema schema = virSchemaDAO.find(schemaName);
+                        if (schema == null) {
+                            LOG.debug("Invalid {} specified: {}, ignoring...",
+                                    VirSchema.class.getSimpleName(), schemaName);
+                        } else {
+                            schema.setProvision(provision);
+                        }
+                    }
+                }
             }
         }
 
-        // 2. remove all abouts not contained in the TO
-        CollectionUtils.filter(resource.getProvisions(), new Predicate<Provision>() {
+        // 2. remove all provisions not contained in the TO
+        for (Iterator<? extends Provision> itor = resource.getProvisions().iterator(); itor.hasNext();) {
+            Provision provision = itor.next();
+            if (resourceTO.getProvision(provision.getAnyType().getKey()) == null) {
+                for (VirSchema schema : virSchemaDAO.findByProvision(provision)) {
+                    virSchemaDAO.delete(schema.getKey());
+                }
 
-            @Override
-            public boolean evaluate(final Provision provision) {
-                return resourceTO.getProvision(provision.getAnyType().getKey()) != null;
+                itor.remove();
             }
-        });
+        }
 
         resource.setCreateTraceLevel(resourceTO.getCreateTraceLevel());
         resource.setUpdateTraceLevel(resourceTO.getUpdateTraceLevel());
@@ -310,6 +334,10 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                 populateMappingTO(provision.getMapping(), mappingTO);
             }
 
+            for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
+                provisionTO.getVirSchemas().add(virSchema.getKey());
+            }
+
             resourceTO.getProvisions().add(provisionTO);
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
index 0794f8c..006a998 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
@@ -35,11 +35,13 @@ import org.apache.syncope.core.misc.spring.BeanUtils;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 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.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 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.Provision;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,7 +52,7 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
 
     private static final Logger LOG = LoggerFactory.getLogger(SchemaDataBinder.class);
 
-    private static final String[] IGNORE_PROPERTIES = { "anyTypeClass" };
+    private static final String[] IGNORE_PROPERTIES = { "anyTypeClass", "provision" };
 
     @Autowired
     private AnyTypeClassDAO anyTypeClassDAO;
@@ -65,6 +67,9 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
     private VirSchemaDAO virSchemaDAO;
 
     @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
     private EntityFactory entityFactory;
 
     @Autowired
@@ -235,6 +240,14 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
             merged.setAnyTypeClass(null);
         }
 
+        Provision provision = resourceDAO.findProvision(schemaTO.getProvision());
+        if (provision == null) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSchemaDefinition);
+            sce.getElements().add("Provision " + schemaTO.getProvision() + " not found");
+            throw sce;
+        }
+        merged.setProvision(provision);
+
         return merged;
     }
 
@@ -253,6 +266,7 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
         VirSchemaTO schemaTO = new VirSchemaTO();
         BeanUtils.copyProperties(schema, schemaTO, IGNORE_PROPERTIES);
         schemaTO.setAnyTypeClass(schema.getAnyTypeClass() == null ? null : schema.getAnyTypeClass().getKey());
+        schemaTO.setProvision(schema.getProvision().getKey());
 
         return schemaTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 3420d27..4bb7bdf 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -19,8 +19,10 @@
 package org.apache.syncope.core.provisioning.java.data;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import javax.annotation.Resource;
@@ -57,6 +59,7 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
+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.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -431,12 +434,12 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             userTO.setSecurityQuestion(user.getSecurityQuestion().getKey());
         }
 
-        if (details) {
-            virAttrHander.retrieveVirAttrValues(user);
-        }
+        Map<VirSchema, List<String>> virAttrValues = details
+                ? virAttrHander.getValues(user)
+                : Collections.<VirSchema, List<String>>emptyMap();
 
         fillTO(userTO, user.getRealm().getFullPath(), user.getAuxClasses(),
-                user.getPlainAttrs(), user.getDerAttrs(), user.getVirAttrs(), userDAO.findAllResources(user));
+                user.getPlainAttrs(), user.getDerAttrs(), virAttrValues, userDAO.findAllResources(user));
 
         if (details) {
             // roles

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
index dbfeca5..7c6d34c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/TaskJob.java
@@ -21,7 +21,7 @@ package org.apache.syncope.core.provisioning.java.job;
 import java.util.Date;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.commons.lang3.ClassUtils;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.apache.syncope.core.misc.security.AuthContextUtils;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.provisioning.api.job.JobInstanceLoader;
@@ -114,7 +114,7 @@ public class TaskJob implements InterruptableJob {
         if (thread == null) {
             LOG.warn("Unable to retrieve the thread of the current job execution");
         } else {
-            LOG.info("Interrupting job from thread {} at {} ", thread.getId(), DataFormat.format(new Date()));
+            LOG.info("Interrupting job from thread {} at {} ", thread.getId(), FormatUtils.format(new Date()));
 
             if (interruptMaxRetries < 1) {
                 interruptMaxRetries = 1;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index 412b978..fd4af1b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -50,16 +50,17 @@ import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
 import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
 import org.apache.syncope.core.persistence.api.entity.user.UDerAttr;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
 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.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
@@ -76,9 +77,6 @@ import org.springframework.transaction.annotation.Transactional;
 @Transactional(rollbackFor = { Throwable.class })
 public class NotificationManagerImpl implements NotificationManager {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(NotificationManager.class);
 
     public static final String MAIL_TEMPLATES = "mailTemplates/";
@@ -87,6 +85,9 @@ public class NotificationManagerImpl implements NotificationManager {
 
     public static final String MAIL_TEMPLATE_TEXT_SUFFIX = ".txt.vm";
 
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
     /**
      * Notification DAO.
      */
@@ -169,11 +170,11 @@ public class NotificationManagerImpl implements NotificationManager {
      */
     private NotificationTask getNotificationTask(
             final Notification notification,
-            final Any<?, ?, ?> any,
+            final Any<?, ?> any,
             final Map<String, Object> model) {
 
         if (any != null) {
-            virAttrHander.retrieveVirAttrValues(any);
+            virAttrHander.getValues(any);
         }
 
         List<User> recipients = new ArrayList<>();
@@ -191,7 +192,7 @@ public class NotificationManagerImpl implements NotificationManager {
         Set<String> recipientEmails = new HashSet<>();
         List<UserTO> recipientTOs = new ArrayList<>(recipients.size());
         for (User recipient : recipients) {
-            virAttrHander.retrieveVirAttrValues(recipient);
+            virAttrHander.getValues(recipient);
 
             String email = getRecipientEmail(notification.getRecipientAttrType(),
                     notification.getRecipientAttrName(), recipient);
@@ -267,7 +268,7 @@ public class NotificationManagerImpl implements NotificationManager {
             final Object output,
             final Object... input) {
 
-        Any<?, ?, ?> any = null;
+        Any<?, ?> any = null;
 
         if (before instanceof UserTO) {
             any = userDAO.find(((UserTO) before).getKey());
@@ -357,9 +358,12 @@ public class NotificationManagerImpl implements NotificationManager {
                 break;
 
             case UserVirtualSchema:
-                UVirAttr virAttr = user.getVirAttr(recipientAttrName);
-                if (virAttr != null) {
-                    email = virAttr.getValues().isEmpty() ? null : virAttr.getValues().get(0);
+                VirSchema schema = virSchemaDAO.find(recipientAttrName);
+                if (schema == null) {
+                    LOG.warn("Ignoring non existing {} {}", VirSchema.class.getSimpleName(), recipientAttrName);
+                } else {
+                    List<String> virAttrValues = virAttrHander.getValues(user, schema);
+                    email = virAttrValues.isEmpty() ? null : virAttrValues.get(0);
                 }
                 break;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/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 69a2e9d..316f91a 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
@@ -27,6 +27,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.apache.commons.collections4.IteratorUtils;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
@@ -49,12 +50,17 @@ import org.apache.syncope.core.misc.ConnObjectUtils;
 import org.apache.syncope.core.misc.ExceptionUtils2;
 import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+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.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.ExternalResource;
+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.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
 import org.identityconnectors.framework.common.exceptions.ConnectorException;
 import org.identityconnectors.framework.common.objects.Attribute;
@@ -110,6 +116,9 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
     @Autowired
     protected TaskDAO taskDAO;
 
+    @Autowired
+    protected VirSchemaDAO virSchemaDAO;
+
     /**
      * Notification Manager.
      */
@@ -125,6 +134,9 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
     @Autowired
     protected EntityFactory entityFactory;
 
+    @Autowired
+    protected VirAttrCache virAttrCache;
+
     @Override
     public TaskExec execute(final PropagationTask task) {
         return execute(task, null);
@@ -149,12 +161,15 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
     }
 
     /**
-     * Transform a
-     * <code>Collection</code> of {@link Attribute} instances into a {@link Map}. The key to each element in the map is
-     * the <i>name</i> of an
-     * <code>Attribute</code>. The value of each element in the map is the
-     * <code>Attribute</code> instance with that name. <br/> Different from the original because: <ul> <li>map keys are
-     * transformed toUpperCase()</li> <li>returned map is mutable</li> </ul>
+     * Transform a {@link Collection} of {@link Attribute} instances into a {@link Map}.
+     * The key to each element in the map is the {@code name} of an {@link Attribute}.
+     * The value of each element in the map is the {@link Attribute} instance with that name.
+     * <br/>
+     * Different from the original because:
+     * <ul>
+     * <li>map keys are transformed toUpperCase()</li>
+     * <li>returned map is mutable</li>
+     * </ul>
      *
      * @param attributes set of attribute to transform to a map.
      * @return a map of string and attribute.
@@ -173,7 +188,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
             final PropagationTask task,
             final ConnectorObject beforeObj,
             final Connector connector,
-            final Set<String> propagationAttempted) {
+            final Boolean[] propagationAttempted) {
 
         // set of attributes to be propagated
         Set<Attribute> attributes = new HashSet<>(task.getAttributes());
@@ -201,14 +216,10 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
 
         if (beforeObj == null) {
             LOG.debug("Create {} on {}", attributes, task.getResource().getKey());
-            connector.create(
-                    new ObjectClass(task.getObjectClassName()),
-                    attributes,
-                    null,
-                    propagationAttempted);
+            connector.create(new ObjectClass(task.getObjectClassName()), attributes, null, propagationAttempted);
         } else {
             // 1. check if rename is really required
-            final Name newName = (Name) AttributeUtil.find(Name.NAME, attributes);
+            Name newName = (Name) AttributeUtil.find(Name.NAME, attributes);
 
             LOG.debug("Rename required with value {}", newName);
 
@@ -254,8 +265,8 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         }
     }
 
-    protected Any<?, ?, ?> getAny(final PropagationTask task) {
-        Any<?, ?, ?> any = null;
+    protected Any<?, ?> getAny(final PropagationTask task) {
+        Any<?, ?> any = null;
 
         if (task.getAnyKey() != null) {
             switch (task.getAnyTypeKind()) {
@@ -289,8 +300,11 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         return any;
     }
 
-    protected void delete(final PropagationTask task, final ConnectorObject beforeObj,
-            final Connector connector, final Set<String> propagationAttempted) {
+    protected void delete(
+            final PropagationTask task,
+            final ConnectorObject beforeObj,
+            final Connector connector,
+            final Boolean[] propagationAttempted) {
 
         if (beforeObj == null) {
             LOG.debug("{} not found on external resource: ignoring delete", task.getConnObjectKey());
@@ -310,7 +324,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
              * update, this user / group used to have the current resource assigned by more than one mean (for example,
              * two different memberships with the same resource).
              */
-            Any<?, ?, ?> any = getAny(task);
+            Any<?, ?> any = getAny(task);
             Collection<String> resources = any instanceof User
                     ? userDAO.findAllResourceNames((User) any)
                     : any instanceof AnyObject
@@ -321,11 +335,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
             if (!resources.contains(task.getResource().getKey())) {
                 LOG.debug("Delete {} on {}", beforeObj.getUid(), task.getResource().getKey());
 
-                connector.delete(
-                        beforeObj.getObjectClass(),
-                        beforeObj.getUid(),
-                        null,
-                        propagationAttempted);
+                connector.delete(beforeObj.getObjectClass(), beforeObj.getUid(), null, propagationAttempted);
             } else {
                 createOrUpdate(task, beforeObj, connector, propagationAttempted);
             }
@@ -345,7 +355,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         String failureReason = null;
 
         // Flag to state whether any propagation has been attempted
-        Set<String> propagationAttempted = new HashSet<>();
+        Boolean[] propagationAttempted = new Boolean[] { false };
 
         ConnectorObject beforeObj = null;
         ConnectorObject afterObj = null;
@@ -411,7 +421,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
                 LOG.error("While executing KO action on {}", execution, wft);
             }
 
-            propagationAttempted.add(task.getOperation().name().toLowerCase());
+            propagationAttempted[0] = true;
 
             for (PropagationActions action : actions) {
                 action.onError(task, execution, e);
@@ -434,7 +444,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
             execution.setEndDate(new Date());
 
             if (hasToBeregistered(task, execution)) {
-                if (propagationAttempted.isEmpty()) {
+                if (!propagationAttempted[0]) {
                     LOG.debug("No propagation attempted for {}", execution);
                 } else {
                     execution.setTask(task);
@@ -535,20 +545,41 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
      * @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 Provision provision, final boolean latest) {
+    protected ConnectorObject getRemoteObject(
+            final PropagationTask task,
+            final Connector connector,
+            final Provision provision,
+            final boolean latest) {
 
         String connObjectKey = latest || task.getOldConnObjectKey() == null
                 ? task.getConnObjectKey()
                 : task.getOldConnObjectKey();
 
+        List<MappingItem> linkingMappingItems = new ArrayList<>();
+        for (VirSchema schema : virSchemaDAO.findByProvision(provision)) {
+            linkingMappingItems.add(schema.asLinkingMappingItem());
+        }
+
         ConnectorObject obj = null;
         try {
             obj = connector.getObject(
                     task.getOperation(),
                     new ObjectClass(task.getObjectClassName()),
                     new Uid(connObjectKey),
-                    connector.getOperationOptions(MappingUtils.getPropagationMappingItems(provision)));
+                    connector.getOperationOptions(IteratorUtils.chainedIterator(
+                                    MappingUtils.getPropagationMappingItems(provision).iterator(),
+                                    linkingMappingItems.iterator())));
+
+            for (MappingItem item : linkingMappingItems) {
+                Attribute attr = obj.getAttributeByName(item.getExtAttrName());
+                if (attr == null) {
+                    virAttrCache.expire(task.getAnyType(), task.getAnyKey(), item.getIntAttrName());
+                } else {
+                    VirAttrCacheValue cacheValue = new VirAttrCacheValue();
+                    cacheValue.setValues(attr.getValue());
+                    virAttrCache.put(task.getAnyType(), task.getAnyKey(), item.getIntAttrName(), cacheValue);
+                }
+            }
         } catch (TimeoutException toe) {
             LOG.debug("Request timeout", toe);
             throw toe;


[10/10] syncope git commit: [SYNCOPE-709] Adding linking mapping items in ResourceTO, for info

Posted by il...@apache.org.
[SYNCOPE-709] Adding linking mapping items in ResourceTO, for info


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

Branch: refs/heads/master
Commit: 55fdc58c959fae949cf660d008b9c670f97e37ae
Parents: fa5e65a
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Oct 22 14:26:29 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Oct 22 14:26:29 2015 +0200

----------------------------------------------------------------------
 .../org/apache/syncope/common/lib/to/MappingTO.java     |  9 +++++++++
 .../org/apache/syncope/common/lib/to/ProvisionTO.java   |  2 +-
 .../provisioning/java/data/ResourceDataBinderImpl.java  | 12 ++++++++----
 .../syncope/fit/core/reference/ResourceITCase.java      |  9 +++++++--
 4 files changed, 25 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/55fdc58c/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
index c573278..73c0523 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
@@ -40,6 +40,8 @@ public class MappingTO extends AbstractBaseBean {
 
     private final List<MappingItemTO> items = new ArrayList<>();
 
+    private final List<MappingItemTO> linkingItems = new ArrayList<>();
+
     public String getConnObjectLink() {
         return connObjectLink;
     }
@@ -96,4 +98,11 @@ public class MappingTO extends AbstractBaseBean {
     public boolean remove(final MappingItemTO item) {
         return this.items.remove(item);
     }
+
+    @XmlElementWrapper(name = "linkingItems")
+    @XmlElement(name = "item")
+    @JsonProperty("linkingItems")
+    public List<MappingItemTO> getLinkingItems() {
+        return linkingItems;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/55fdc58c/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
index b25053d..da23a59 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
@@ -43,7 +43,7 @@ public class ProvisionTO extends AbstractBaseBean {
 
     private MappingTO mapping;
 
-    private List<String> virSchemas = new ArrayList<>();
+    private final List<String> virSchemas = new ArrayList<>();
 
     public long getKey() {
         return key;

http://git-wip-us.apache.org/repos/asf/syncope/blob/55fdc58c/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 d04dfd3..388f099 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
@@ -299,10 +299,6 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
     @Override
     public ResourceTO getResourceTO(final ExternalResource resource) {
-        if (resource == null) {
-            return null;
-        }
-
         ResourceTO resourceTO = new ResourceTO();
 
         // set sys info
@@ -336,6 +332,14 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
             for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
                 provisionTO.getVirSchemas().add(virSchema.getKey());
+
+                MappingItem linkingMappingItem = virSchema.asLinkingMappingItem();
+
+                MappingItemTO itemTO = new MappingItemTO();
+                itemTO.setKey(linkingMappingItem.getKey());
+                BeanUtils.copyProperties(linkingMappingItem, itemTO, MAPPINGITEM_IGNORE_PROPERTIES);
+
+                provisionTO.getMapping().getLinkingItems().add(itemTO);
             }
 
             resourceTO.getProvisions().add(provisionTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/55fdc58c/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
index 07433b7..e0539c8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
@@ -453,8 +453,13 @@ public class ResourceITCase extends AbstractITCase {
 
     @Test
     public void read() {
-        ResourceTO actual = resourceService.read(RESOURCE_NAME_TESTDB);
-        assertNotNull(actual);
+        ResourceTO resource = resourceService.read(RESOURCE_NAME_DBVIRATTR);
+        assertNotNull(resource);
+        
+        ProvisionTO provision = resource.getProvision(AnyTypeKind.USER.name());
+        assertNotNull(provision);
+        assertFalse(provision.getMapping().getItems().isEmpty());
+        assertFalse(provision.getMapping().getLinkingItems().isEmpty());
     }
 
     @Test


[02/10] syncope git commit: [SYNCOPE-709] Refactoring completed

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
index 7de863e..91da759 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
@@ -45,7 +45,6 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.common.util.Base64Utility;
 import org.apache.cxf.helpers.IOUtils;
 import org.apache.syncope.client.lib.SyncopeClient;
-import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.patch.AssociationPatch;
@@ -137,7 +136,6 @@ public class UserITCase extends AbstractITCase {
         userTO.getPlainAttrs().add(attrTO("email", email));
         userTO.getPlainAttrs().add(attrTO("loginDate", DATE_FORMAT.get().format(new Date())));
         userTO.getDerAttrs().add(attrTO("cn", null));
-        userTO.getVirAttrs().add(attrTO("virtualdata", "virtualvalue"));
         return userTO;
     }
 
@@ -154,7 +152,6 @@ public class UserITCase extends AbstractITCase {
 
         // create a new user
         UserTO userTO = getUniqueSampleTO("xxx@xxx.xxx");
-
         userTO.setPassword("password123");
         userTO.getResources().add(RESOURCE_NAME_NOPROPAGATION);
 
@@ -173,7 +170,6 @@ public class UserITCase extends AbstractITCase {
 
         // get last task
         PropagationTaskTO taskTO = taskService.read(newMaxId);
-
         assertNotNull(taskTO);
         assertTrue(taskTO.getExecutions().isEmpty());
     }
@@ -387,15 +383,6 @@ public class UserITCase extends AbstractITCase {
         // check for changePwdDate
         assertNotNull(newUserTO.getCreationDate());
 
-        // 2. check for virtual attribute value
-        newUserTO = userService.read(newUserTO.getKey());
-        assertNotNull(newUserTO);
-
-        assertNotNull(newUserTO.getVirAttrMap());
-        assertNotNull(newUserTO.getVirAttrMap().get("virtualdata").getValues());
-        assertFalse(newUserTO.getVirAttrMap().get("virtualdata").getValues().isEmpty());
-        assertEquals("virtualvalue", newUserTO.getVirAttrMap().get("virtualdata").getValues().get(0));
-
         // get the new task list
         tasks = taskService.list(
                 TaskType.PROPAGATION,
@@ -751,7 +738,7 @@ public class UserITCase extends AbstractITCase {
 
         long newMaxKey = tasks.getResult().iterator().next().getKey();
 
-        // default configuration for ws-target-resource2:
+        // default configuration for ws-target-resource2 during create:
         // only failed executions have to be registered
         // --> no more tasks/executions should be added
         assertEquals(newMaxKey, maxKey);
@@ -762,7 +749,7 @@ public class UserITCase extends AbstractITCase {
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(userTO.getKey());
 
-        userPatch.getPlainAttrs().add(attrAddReplacePatch("surname", "surname"));
+        userPatch.getPlainAttrs().add(attrAddReplacePatch("surname", "surname2"));
 
         userTO = updateUser(userPatch);
 
@@ -776,11 +763,11 @@ public class UserITCase extends AbstractITCase {
         maxKey = newMaxKey;
         newMaxKey = tasks.getResult().iterator().next().getKey();
 
-        // default configuration for ws-target-resource2:
+        // default configuration for ws-target-resource2 during update:
         // all update executions have to be registered
         assertTrue(newMaxKey > maxKey);
 
-        final PropagationTaskTO taskTO = taskService.read(newMaxKey);
+        PropagationTaskTO taskTO = taskService.read(newMaxKey);
 
         assertNotNull(taskTO);
         assertEquals(1, taskTO.getExecutions().size());
@@ -1004,37 +991,6 @@ public class UserITCase extends AbstractITCase {
     }
 
     @Test
-    public void issue270() {
-        // 1. create a new user without virtual attributes
-        UserTO original = getUniqueSampleTO("issue270@syncope.apache.org");
-        // be sure to remove all virtual attributes
-        original.getVirAttrs().clear();
-
-        original = createUser(original);
-
-        assertNotNull(original);
-
-        assertTrue(original.getVirAttrs().isEmpty());
-
-        UserTO toBeUpdated = userService.read(original.getKey());
-
-        AttrTO virtual = attrTO("virtualdata", "virtualvalue");
-        toBeUpdated.getVirAttrs().add(virtual);
-
-        // 2. try to update by adding a resource, but no password: must fail
-        UserPatch userPatch = AnyOperations.diff(toBeUpdated, original, false);
-        assertNotNull(userPatch);
-
-        toBeUpdated = updateUser(userPatch);
-        assertNotNull(toBeUpdated);
-
-        assertFalse(toBeUpdated.getVirAttrs().isEmpty());
-        assertNotNull(toBeUpdated.getVirAttrs().iterator().next());
-
-        assertEquals(virtual.getSchema(), toBeUpdated.getVirAttrs().iterator().next().getSchema());
-    }
-
-    @Test
     public final void issue280() {
         UserTO userTO = getUniqueSampleTO("issue280@syncope.apache.org");
         userTO.getResources().clear();
@@ -1353,6 +1309,7 @@ public class UserITCase extends AbstractITCase {
         // create user and check virtual attribute value propagation
         // ----------------------------------
         UserTO userTO = getUniqueSampleTO("syncope267@apache.org");
+        userTO.getVirAttrs().add(attrTO("virtualdata", "virtualvalue"));
         userTO.getResources().clear();
         userTO.getResources().add(RESOURCE_NAME_DBVIRATTR);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
index 1856eee..e96026f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.fit.core.reference;
 
+import static org.apache.syncope.fit.core.reference.AbstractITCase.getUUIDString;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -25,14 +26,15 @@ import static org.junit.Assert.assertTrue;
 
 import java.util.Locale;
 import java.util.Map;
+import javax.ws.rs.core.Response;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
-import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.PasswordPatch;
 import org.apache.syncope.common.lib.patch.StatusPatch;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
@@ -43,13 +45,16 @@ import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.lib.types.StatusPatchType;
+import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
 import org.apache.syncope.common.rest.api.service.ResourceService;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.junit.FixMethodOrder;
@@ -63,38 +68,60 @@ public class VirAttrITCase extends AbstractITCase {
     @Test
     public void issueSYNCOPE16() {
         UserTO userTO = UserITCase.getUniqueSampleTO("issue16@apache.org");
-
+        userTO.getVirAttrs().add(attrTO("virtualdata", "virtualvalue"));
+        userTO.getResources().add(RESOURCE_NAME_DBVIRATTR);
         userTO.getMemberships().add(new MembershipTO.Builder().group(8L).build());
 
         // 1. create user
-        UserTO actual = createUser(userTO);
-        assertNotNull(actual);
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
 
         // 2. check for virtual attribute value
-        actual = userService.read(actual.getKey());
-        assertNotNull(actual);
-        assertEquals("virtualvalue", actual.getVirAttrMap().get("virtualdata").getValues().get(0));
+        userTO = userService.read(userTO.getKey());
+        assertNotNull(userTO);
+        assertEquals("virtualvalue", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
 
         UserPatch userPatch = new UserPatch();
-        userPatch.setKey(actual.getKey());
-        userPatch.getVirAttrs().add(attrAddReplacePatch("virtualdata", "virtualupdated"));
+        userPatch.setKey(userTO.getKey());
+        userPatch.getVirAttrs().add(attrTO("virtualdata", "virtualupdated"));
 
         // 3. update virtual attribute
-        actual = updateUser(userPatch);
-        assertNotNull(actual);
+        userTO = updateUser(userPatch);
+        assertNotNull(userTO);
 
         // 4. check for virtual attribute value
-        actual = userService.read(actual.getKey());
-        assertNotNull(actual);
-        assertEquals("virtualupdated", actual.getVirAttrMap().get("virtualdata").getValues().get(0));
+        userTO = userService.read(userTO.getKey());
+        assertNotNull(userTO);
+        assertEquals("virtualupdated", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
     }
 
     @Test
     public void issueSYNCOPE260() {
+        // create new virtual schema for the resource below
+        ResourceTO ws2 = resourceService.read(RESOURCE_NAME_WS2);
+        ProvisionTO provision = ws2.getProvision(AnyTypeKind.USER.name());
+        assertNotNull(provision);
+
+        VirSchemaTO virSchema = new VirSchemaTO();
+        virSchema.setKey("syncope260" + getUUIDString());
+        virSchema.setExtAttrName("companyName");
+        virSchema.setProvision(provision.getKey());
+        virSchema = createSchema(SchemaType.VIRTUAL, virSchema);
+        assertNotNull(virSchema);
+
+        AnyTypeClassTO newClass = new AnyTypeClassTO();
+        newClass.setKey("syncope260" + getUUIDString());
+        newClass.getVirSchemas().add(virSchema.getKey());
+        Response response = anyTypeClassService.create(newClass);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
+        newClass = getObject(response.getLocation(), AnyTypeClassService.class, AnyTypeClassTO.class);
+
         // ----------------------------------
         // create user and check virtual attribute value propagation
         // ----------------------------------
         UserTO userTO = UserITCase.getUniqueSampleTO("260@a.com");
+        userTO.getAuxClasses().add(newClass.getKey());
+        userTO.getVirAttrs().add(attrTO(virSchema.getKey(), "virtualvalue"));
         userTO.getResources().add(RESOURCE_NAME_WS2);
 
         userTO = createUser(userTO);
@@ -105,8 +132,7 @@ public class VirAttrITCase extends AbstractITCase {
 
         ConnObjectTO connObjectTO =
                 resourceService.readConnObject(RESOURCE_NAME_WS2, AnyTypeKind.USER.name(), userTO.getKey());
-        assertNotNull(connObjectTO);
-        assertEquals("virtualvalue", connObjectTO.getPlainAttrMap().get("NAME").getValues().get(0));
+        assertEquals("virtualvalue", connObjectTO.getPlainAttrMap().get("COMPANYNAME").getValues().get(0));
         // ----------------------------------
 
         // ----------------------------------
@@ -114,17 +140,16 @@ public class VirAttrITCase extends AbstractITCase {
         // ----------------------------------
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(userTO.getKey());
-        userPatch.getVirAttrs().add(attrAddReplacePatch("virtualdata", "virtualvalue2"));
+        userPatch.getVirAttrs().add(attrTO(virSchema.getKey(), "virtualvalue2"));
 
         userTO = updateUser(userPatch);
         assertNotNull(userTO);
         assertFalse(userTO.getPropagationStatusTOs().isEmpty());
-        assertEquals("ws-target-resource-2", userTO.getPropagationStatusTOs().get(0).getResource());
+        assertEquals(RESOURCE_NAME_WS2, userTO.getPropagationStatusTOs().get(0).getResource());
         assertEquals(PropagationTaskExecStatus.SUCCESS, userTO.getPropagationStatusTOs().get(0).getStatus());
 
         connObjectTO = resourceService.readConnObject(RESOURCE_NAME_WS2, AnyTypeKind.USER.name(), userTO.getKey());
-        assertNotNull(connObjectTO);
-        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("NAME").getValues().get(0));
+        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("COMPANYNAME").getValues().get(0));
         // ----------------------------------
 
         // ----------------------------------
@@ -137,9 +162,7 @@ public class VirAttrITCase extends AbstractITCase {
         assertEquals("suspended", userTO.getStatus());
 
         connObjectTO = resourceService.readConnObject(RESOURCE_NAME_WS2, AnyTypeKind.USER.name(), userTO.getKey());
-        assertNotNull(connObjectTO);
-        assertFalse(connObjectTO.getPlainAttrMap().get("NAME").getValues().isEmpty());
-        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("NAME").getValues().get(0));
+        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("COMPANYNAME").getValues().get(0));
 
         statusPatch = new StatusPatch();
         statusPatch.setKey(userTO.getKey());
@@ -148,9 +171,7 @@ public class VirAttrITCase extends AbstractITCase {
         assertEquals("active", userTO.getStatus());
 
         connObjectTO = resourceService.readConnObject(RESOURCE_NAME_WS2, AnyTypeKind.USER.name(), userTO.getKey());
-        assertNotNull(connObjectTO);
-        assertFalse(connObjectTO.getPlainAttrMap().get("NAME").getValues().isEmpty());
-        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("NAME").getValues().get(0));
+        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("COMPANYNAME").getValues().get(0));
         // ----------------------------------
 
         // ----------------------------------
@@ -167,36 +188,11 @@ public class VirAttrITCase extends AbstractITCase {
         assertEquals(PropagationTaskExecStatus.SUCCESS, userTO.getPropagationStatusTOs().get(0).getStatus());
 
         connObjectTO = resourceService.readConnObject(RESOURCE_NAME_WS2, AnyTypeKind.USER.name(), userTO.getKey());
-        assertNotNull(connObjectTO);
         assertEquals("Surname2", connObjectTO.getPlainAttrMap().get("SURNAME").getValues().get(0));
 
-        // attribute "name" mapped on virtual attribute "virtualdata" shouldn't be changed
-        assertFalse(connObjectTO.getPlainAttrMap().get("NAME").getValues().isEmpty());
-        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("NAME").getValues().get(0));
-        // ----------------------------------
-
-        // ----------------------------------
-        // remove user virtual attribute and check virtual attribute value (reset)
-        // ----------------------------------
-        userPatch = new UserPatch();
-        userPatch.setKey(userTO.getKey());
-        userPatch.getVirAttrs().add(new AttrPatch.Builder().
-                operation(PatchOperation.DELETE).
-                attrTO(new AttrTO.Builder().schema("virtualdata").build()).build());
-
-        userTO = updateUser(userPatch);
-        assertNotNull(userTO);
-        assertTrue(userTO.getVirAttrs().isEmpty());
-        assertFalse(userTO.getPropagationStatusTOs().isEmpty());
-        assertEquals(RESOURCE_NAME_WS2, userTO.getPropagationStatusTOs().get(0).getResource());
-        assertEquals(PropagationTaskExecStatus.SUCCESS, userTO.getPropagationStatusTOs().get(0).getStatus());
-
-        connObjectTO = resourceService.readConnObject(RESOURCE_NAME_WS2, AnyTypeKind.USER.name(), userTO.getKey());
-        assertNotNull(connObjectTO);
-
-        // attribute "name" mapped on virtual attribute "virtualdata" should be reset
-        assertTrue(connObjectTO.getPlainAttrMap().get("NAME").getValues() == null
-                || connObjectTO.getPlainAttrMap().get("NAME").getValues().isEmpty());
+        // virtual attribute value did not change
+        assertFalse(connObjectTO.getPlainAttrMap().get("COMPANYNAME").getValues().isEmpty());
+        assertEquals("virtualvalue2", connObjectTO.getPlainAttrMap().get("COMPANYNAME").getValues().get(0));
         // ----------------------------------
     }
 
@@ -241,7 +237,7 @@ public class VirAttrITCase extends AbstractITCase {
 
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(actual.getKey());
-        userPatch.getVirAttrs().add(attrAddReplacePatch("virtualdata", "virtualupdated"));
+        userPatch.getVirAttrs().add(attrTO("virtualdata", "virtualupdated"));
 
         // 5. update virtual attribute
         actual = updateUser(userPatch);
@@ -256,36 +252,46 @@ public class VirAttrITCase extends AbstractITCase {
     @Test
     public void issueSYNCOPE397() {
         ResourceTO csv = resourceService.read(RESOURCE_NAME_CSV);
+
+        // change mapping of resource-csv
         MappingTO origMapping = SerializationUtils.clone(csv.getProvisions().get(0).getMapping());
         try {
-            // change mapping of resource-csv
-            assertNotNull(origMapping);
-            for (MappingItemTO item : csv.getProvisions().get(0).getMapping().getItems()) {
-                if ("email".equals(item.getIntAttrName())) {
-                    // unset internal attribute mail and set virtual attribute virtualdata as mapped to external email
-                    item.setIntMappingType(IntMappingType.UserVirtualSchema);
-                    item.setIntAttrName("virtualdata");
-                    item.setPurpose(MappingPurpose.BOTH);
-                    item.setExtAttrName("email");
-                }
-            }
+            // remove this mapping
+            CollectionUtils.filterInverse(csv.getProvisions().get(0).getMapping().getItems(),
+                    new Predicate<MappingItemTO>() {
+
+                        @Override
+                        public boolean evaluate(final MappingItemTO item) {
+                            return "email".equals(item.getIntAttrName());
+                        }
+                    });
 
             resourceService.update(csv);
             csv = resourceService.read(RESOURCE_NAME_CSV);
             assertNotNull(csv.getProvisions().get(0).getMapping());
 
-            boolean found = false;
-            for (MappingItemTO item : csv.getProvisions().get(0).getMapping().getItems()) {
-                if ("email".equals(item.getExtAttrName()) && "virtualdata".equals(item.getIntAttrName())) {
-                    found = true;
-                }
-            }
+            // create new virtual schema for the resource below
+            ProvisionTO provision = csv.getProvision(AnyTypeKind.USER.name());
+            assertNotNull(provision);
 
-            assertTrue(found);
+            VirSchemaTO virSchema = new VirSchemaTO();
+            virSchema.setKey("syncope397" + getUUIDString());
+            virSchema.setExtAttrName("email");
+            virSchema.setProvision(provision.getKey());
+            virSchema = createSchema(SchemaType.VIRTUAL, virSchema);
+            assertNotNull(virSchema);
+
+            AnyTypeClassTO newClass = new AnyTypeClassTO();
+            newClass.setKey("syncope397" + getUUIDString());
+            newClass.getVirSchemas().add(virSchema.getKey());
+            Response response = anyTypeClassService.create(newClass);
+            assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
+            newClass = getObject(response.getLocation(), AnyTypeClassService.class, AnyTypeClassTO.class);
 
             // create a new user
             UserTO userTO = UserITCase.getUniqueSampleTO("397@syncope.apache.org");
             userTO.getAuxClasses().add("csv");
+            userTO.getAuxClasses().add(newClass.getKey());
             userTO.getResources().clear();
             userTO.getMemberships().clear();
             userTO.getDerAttrs().clear();
@@ -293,18 +299,18 @@ public class VirAttrITCase extends AbstractITCase {
 
             userTO.getDerAttrs().add(attrTO("csvuserid", null));
             userTO.getDerAttrs().add(attrTO("cn", null));
-            userTO.getVirAttrs().add(attrTO("virtualdata", "test@testone.org"));
+            userTO.getVirAttrs().add(attrTO(virSchema.getKey(), "test@testone.org"));
             // assign resource-csv to user
             userTO.getResources().add(RESOURCE_NAME_CSV);
             // save user
-            UserTO created = createUser(userTO);
+            userTO = createUser(userTO);
             // make std controls about user
-            assertNotNull(created);
-            assertTrue(RESOURCE_NAME_CSV.equals(created.getResources().iterator().next()));
-            assertEquals("test@testone.org", created.getVirAttrs().iterator().next().getValues().get(0));
+            assertNotNull(userTO);
+            assertTrue(RESOURCE_NAME_CSV.equals(userTO.getResources().iterator().next()));
+            assertEquals("test@testone.org", userTO.getVirAttrs().iterator().next().getValues().get(0));
 
             // update user
-            UserTO toBeUpdated = userService.read(created.getKey());
+            UserTO toBeUpdated = userService.read(userTO.getKey());
             UserPatch userPatch = new UserPatch();
             userPatch.setKey(toBeUpdated.getKey());
             userPatch.setPassword(new PasswordPatch.Builder().value("password234").build());
@@ -312,7 +318,7 @@ public class VirAttrITCase extends AbstractITCase {
             userPatch.getResources().add(new StringPatchItem.Builder().
                     operation(PatchOperation.ADD_REPLACE).value(RESOURCE_NAME_WS2).build());
             // modify virtual attribute
-            userPatch.getVirAttrs().add(attrAddReplacePatch("virtualdata", "test@testoneone.com"));
+            userPatch.getVirAttrs().add(attrTO(virSchema.getKey(), "test@testoneone.com"));
 
             // check Syncope change password
             userPatch.setPassword(new PasswordPatch.Builder().
@@ -348,15 +354,15 @@ public class VirAttrITCase extends AbstractITCase {
         userTO.getResources().add(RESOURCE_NAME_DBVIRATTR);
 
         // 1. create user
-        UserTO actual = createUser(userTO);
-        assertNotNull(actual);
+        userTO = createUser(userTO);
+        assertNotNull(userTO);
 
         // 2. check for virtual attribute value
-        actual = userService.read(actual.getKey());
-        assertEquals("virattrcache", actual.getVirAttrMap().get("virtualdata").getValues().get(0));
+        userTO = userService.read(userTO.getKey());
+        assertEquals("virattrcache", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
 
         // ----------------------------------------
-        // 3. force cache expiring without any modification
+        // 3. change connector URL so that we are sure that any provided value will come from virtual cache
         // ----------------------------------------
         String jdbcURL = null;
         ConnInstanceTO connInstanceTO = connectorService.readByResource(
@@ -370,36 +376,29 @@ public class VirAttrITCase extends AbstractITCase {
         }
 
         connectorService.update(connInstanceTO);
-
-        UserPatch userPatch = new UserPatch();
-        userPatch.setKey(actual.getKey());
-        userPatch.getVirAttrs().add(attrAddReplacePatch("virtualdata", "virtualupdated"));
-
-        actual = updateUser(userPatch);
-        assertNotNull(actual);
         // ----------------------------------------
 
         // ----------------------------------------
-        // 4. update virtual attribute
+        // 4. update value on external resource
         // ----------------------------------------
-        final JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
 
         String value = jdbcTemplate.queryForObject(
-                "SELECT USERNAME FROM testsync WHERE ID=?", String.class, actual.getKey());
+                "SELECT USERNAME FROM testsync WHERE ID=?", String.class, userTO.getKey());
         assertEquals("virattrcache", value);
 
-        jdbcTemplate.update("UPDATE testsync set USERNAME='virattrcache2' WHERE ID=?", actual.getKey());
+        jdbcTemplate.update("UPDATE testsync set USERNAME='virattrcache2' WHERE ID=?", userTO.getKey());
 
         value = jdbcTemplate.queryForObject(
-                "SELECT USERNAME FROM testsync WHERE ID=?", String.class, actual.getKey());
+                "SELECT USERNAME FROM testsync WHERE ID=?", String.class, userTO.getKey());
         assertEquals("virattrcache2", value);
         // ----------------------------------------
 
-        actual = userService.read(actual.getKey());
-        assertEquals("virattrcache", actual.getVirAttrMap().get("virtualdata").getValues().get(0));
+        userTO = userService.read(userTO.getKey());
+        assertEquals("virattrcache", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
 
         // ----------------------------------------
-        // 5. restore connector
+        // 5. restore connector URL, values can be read again from external resource
         // ----------------------------------------
         for (ConnConfProperty prop : connInstanceTO.getConfiguration()) {
             if ("jdbcUrlTemplate".equals(prop.getSchema().getName())) {
@@ -411,8 +410,20 @@ public class VirAttrITCase extends AbstractITCase {
         connectorService.update(connInstanceTO);
         // ----------------------------------------
 
-        actual = userService.read(actual.getKey());
-        assertEquals("virattrcache2", actual.getVirAttrMap().get("virtualdata").getValues().get(0));
+        // cached value still in place...
+        userTO = userService.read(userTO.getKey());
+        assertEquals("virattrcache", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
+
+        // force cache update by adding a resource which has virtualdata mapped for propagation
+        UserPatch userPatch = new UserPatch();
+        userPatch.setKey(userTO.getKey());
+        userPatch.getResources().add(new StringPatchItem.Builder().
+                operation(PatchOperation.ADD_REPLACE).value(RESOURCE_NAME_WS2).build());
+        userTO = updateUser(userPatch);
+        assertNotNull(userTO);
+
+        userTO = userService.read(userTO.getKey());
+        assertEquals("virattrcache2", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
     }
 
     @Test
@@ -423,7 +434,7 @@ public class VirAttrITCase extends AbstractITCase {
         userTO.getResources().add(RESOURCE_NAME_LDAP);
         userTO.getVirAttrs().add(attrTO("virtualReadOnly", "readOnly"));
         userTO = createUser(userTO);
-        //Finding no values because the virtual attribute is readonly 
+        // finding no values because the virtual attribute is readonly 
         assertTrue(userTO.getVirAttrMap().get("virtualReadOnly").getValues().isEmpty());
     }
 
@@ -527,27 +538,13 @@ public class VirAttrITCase extends AbstractITCase {
     public void issueSYNCOPE459() {
         UserTO userTO = UserITCase.getUniqueSampleTO("syncope459@apache.org");
         userTO.getResources().clear();
+        userTO.getResources().add(RESOURCE_NAME_LDAP);
         userTO.getMemberships().clear();
         userTO.getVirAttrs().clear();
 
-        AttrTO virtualReadOnly = attrTO("virtualReadOnly", "");
-        virtualReadOnly.getValues().clear();
-
-        userTO.getVirAttrs().add(virtualReadOnly);
-
         userTO = createUser(userTO);
 
         assertNotNull(userTO.getVirAttrMap().get("virtualReadOnly"));
-
-        UserPatch userPatch = new UserPatch();
-        userPatch.setKey(userTO.getKey());
-        userPatch.getVirAttrs().add(new AttrPatch.Builder().
-                operation(PatchOperation.ADD_REPLACE).
-                attrTO(new AttrTO.Builder().schema("virtualdata").build()).
-                build());
-
-        userTO = updateUser(userPatch);
-        assertNotNull(userTO.getVirAttrMap().get("virtualdata"));
     }
 
     @Test
@@ -572,7 +569,7 @@ public class VirAttrITCase extends AbstractITCase {
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(userTO.getKey());
         // change virtual attribute value
-        userPatch.getVirAttrs().add(attrAddReplacePatch("virtualdata", "syncope501_updated@apache.org"));
+        userPatch.getVirAttrs().add(attrTO("virtualdata", "syncope501_updated@apache.org"));
 
         userTO = updateUser(userPatch);
         assertNotNull(userTO);
@@ -584,80 +581,76 @@ public class VirAttrITCase extends AbstractITCase {
 
     @Test
     public void issueSYNCOPE691() {
-        final String res = RESOURCE_NAME_LDAP + "691";
-
         ResourceTO ldap = resourceService.read(RESOURCE_NAME_LDAP);
-        ldap.setKey(res);
-
         try {
+            ProvisionTO provision = ldap.getProvision(AnyTypeKind.USER.name());
+            assertNotNull(provision);
+            CollectionUtils.filterInverse(provision.getMapping().getItems(), new Predicate<MappingItemTO>() {
 
-            CollectionUtils.filterInverse(ldap.getProvision(AnyTypeKind.USER.name()).getMapping().getItems(),
-                    new Predicate<MappingItemTO>() {
-
-                        @Override
-                        public boolean evaluate(final MappingItemTO item) {
-                            return "mail".equals(item.getExtAttrName());
-                        }
-                    });
-
-            final MappingItemTO mail = new MappingItemTO();
-            // unset internal attribute mail and set virtual attribute virtualdata as mapped to external email
-            mail.setIntMappingType(IntMappingType.UserVirtualSchema);
-            mail.setIntAttrName("virtualdata");
-            mail.setPurpose(MappingPurpose.BOTH);
-            mail.setExtAttrName("mail");
-
-            ldap.getProvision(AnyTypeKind.USER.name()).getMapping().getItems().add(mail);
+                @Override
+                public boolean evaluate(final MappingItemTO item) {
+                    return "mail".equals(item.getExtAttrName());
+                }
+            });
+            provision.getVirSchemas().clear();
 
+            ldap.setKey(RESOURCE_NAME_LDAP + "691" + getUUIDString());
             resourceService.create(ldap);
 
-            ldap = resourceService.read(res);
-            assertNotNull(ldap.getProvision(AnyTypeKind.USER.name()).getMapping());
-
-            assertTrue(CollectionUtils.exists(ldap.getProvision(AnyTypeKind.USER.name()).getMapping().getItems(),
-                    new Predicate<MappingItemTO>() {
-
-                        @Override
-                        public boolean evaluate(final MappingItemTO item) {
-                            return "mail".equals(item.getExtAttrName()) && "virtualdata".equals(item.getIntAttrName());
-                        }
-                    }));
+            ldap = resourceService.read(ldap.getKey());
+            provision = ldap.getProvision(AnyTypeKind.USER.name());
+            assertNotNull(provision);
+
+            // create new virtual schema for the resource below
+            VirSchemaTO virSchema = new VirSchemaTO();
+            virSchema.setKey("syncope691" + getUUIDString());
+            virSchema.setExtAttrName("mail");
+            virSchema.setProvision(provision.getKey());
+            virSchema = createSchema(SchemaType.VIRTUAL, virSchema);
+            assertNotNull(virSchema);
+
+            AnyTypeClassTO newClass = new AnyTypeClassTO();
+            newClass.setKey("syncope691" + getUUIDString());
+            newClass.getVirSchemas().add(virSchema.getKey());
+            Response response = anyTypeClassService.create(newClass);
+            assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
+            newClass = getObject(response.getLocation(), AnyTypeClassService.class, AnyTypeClassTO.class);
 
             // create a new user
             UserTO userTO = UserITCase.getUniqueSampleTO("syncope691@syncope.apache.org");
+            userTO.getAuxClasses().add(newClass.getKey());
             userTO.getResources().clear();
             userTO.getMemberships().clear();
             userTO.getDerAttrs().clear();
             userTO.getVirAttrs().clear();
 
-            final AttrTO emailTO = new AttrTO();
-            emailTO.setSchema("virtualdata");
+            AttrTO emailTO = new AttrTO();
+            emailTO.setSchema(virSchema.getKey());
             emailTO.getValues().add("test@issue691.dom1.org");
             emailTO.getValues().add("test@issue691.dom2.org");
 
             userTO.getVirAttrs().add(emailTO);
             // assign resource-ldap691 to user
-            userTO.getResources().add(res);
+            userTO.getResources().add(ldap.getKey());
             // save user
-            UserTO created = createUser(userTO);
+            userTO = createUser(userTO);
             // make std controls about user
-            assertNotNull(created);
-            assertTrue(res.equals(created.getResources().iterator().next()));
+            assertNotNull(userTO);
+            assertTrue(ldap.getKey().equals(userTO.getResources().iterator().next()));
 
-            assertEquals(2, created.getVirAttrs().iterator().next().getValues().size(), 0);
-            assertTrue(created.getVirAttrs().iterator().next().getValues().contains("test@issue691.dom1.org"));
-            assertTrue(created.getVirAttrs().iterator().next().getValues().contains("test@issue691.dom2.org"));
+            assertEquals(2, userTO.getVirAttrs().iterator().next().getValues().size(), 0);
+            assertTrue(userTO.getVirAttrs().iterator().next().getValues().contains("test@issue691.dom1.org"));
+            assertTrue(userTO.getVirAttrs().iterator().next().getValues().contains("test@issue691.dom2.org"));
 
             // update user
             UserPatch userPatch = new UserPatch();
-            userPatch.setKey(created.getKey());
+            userPatch.setKey(userTO.getKey());
             // modify virtual attribute
-            userPatch.getVirAttrs().add(new AttrPatch.Builder().
-                    operation(PatchOperation.ADD_REPLACE).
-                    attrTO(new AttrTO.Builder().schema("virtualdata").
-                            value("test@issue691.dom3.org").
-                            value("test@issue691.dom4.org").
-                            build()).build());
+            userPatch.getVirAttrs().add(
+                    new AttrTO.Builder().schema(virSchema.getKey()).
+                    value("test@issue691.dom3.org").
+                    value("test@issue691.dom4.org").
+                    build());
 
             UserTO updated = updateUser(userPatch);
             assertNotNull(updated);
@@ -666,7 +659,7 @@ public class VirAttrITCase extends AbstractITCase {
             assertTrue(updated.getVirAttrs().iterator().next().getValues().contains("test@issue691.dom4.org"));
         } finally {
             try {
-                resourceService.delete(res);
+                resourceService.delete(ldap.getKey());
             } catch (Exception ignore) {
                 // ignore
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
index a1ee34d..caae156 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
@@ -27,6 +27,7 @@ import static org.junit.Assert.fail;
 import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.EntityViolationType;
@@ -48,41 +49,47 @@ public class VirSchemaITCase extends AbstractITCase {
     }
 
     @Test
-    public void read() {
-        VirSchemaTO vSchemaTO = schemaService.read(SchemaType.VIRTUAL, "mvirtualdata");
-        assertNotNull(vSchemaTO);
-    }
+    public void crud() {
+        ResourceTO csv = resourceService.read(RESOURCE_NAME_CSV);
+        assertNotNull(csv);
+        assertEquals(1, csv.getProvisions().size());
+        assertTrue(csv.getProvisions().get(0).getVirSchemas().isEmpty());
 
-    @Test
-    public void create() {
         VirSchemaTO schema = new VirSchemaTO();
-        schema.setKey("virtual");
+        schema.setKey("virtualTest" + getUUIDString());
+        schema.setExtAttrName("name");
+        schema.setProvision(csv.getProvisions().get(0).getKey());
 
-        VirSchemaTO actual = createSchema(SchemaType.VIRTUAL, schema);
-        assertNotNull(actual);
+        schema = createSchema(SchemaType.VIRTUAL, schema);
+        assertNotNull(schema);
+        assertEquals(csv.getProvisions().get(0).getKey(), schema.getProvision());
 
-        actual = schemaService.read(SchemaType.VIRTUAL, actual.getKey());
-        assertNotNull(actual);
-    }
+        csv = resourceService.read(RESOURCE_NAME_CSV);
+        assertNotNull(csv);
+        assertEquals(1, csv.getProvisions().size());
+        assertFalse(csv.getProvisions().get(0).getVirSchemas().isEmpty());
 
-    @Test
-    public void delete() {
-        VirSchemaTO schema = schemaService.read(SchemaType.VIRTUAL, "rvirtualdata");
+        schema = schemaService.read(SchemaType.VIRTUAL, schema.getKey());
         assertNotNull(schema);
 
         schemaService.delete(SchemaType.VIRTUAL, schema.getKey());
 
         try {
-            schemaService.read(SchemaType.VIRTUAL, "rvirtualdata");
+            schemaService.read(SchemaType.VIRTUAL, schema.getKey());
             fail();
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.NotFound, e.getType());
         }
+
+        csv = resourceService.read(RESOURCE_NAME_CSV);
+        assertNotNull(csv);
+        assertEquals(1, csv.getProvisions().size());
+        assertTrue(csv.getProvisions().get(0).getVirSchemas().isEmpty());
     }
 
     @Test
     public void issueSYNCOPE323() {
-        VirSchemaTO actual = schemaService.read(SchemaType.VIRTUAL, "mvirtualdata");
+        VirSchemaTO actual = schemaService.read(SchemaType.VIRTUAL, "virtualdata");
         assertNotNull(actual);
 
         try {


[03/10] syncope git commit: [SYNCOPE-709] Refactoring completed

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/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 0d15ffd..77efd28 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
@@ -29,7 +29,6 @@ import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AttrTO;
@@ -40,9 +39,7 @@ import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
-import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
@@ -51,11 +48,15 @@ import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+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.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.ExternalResource;
 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.VirAttrHandler;
+import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -73,6 +74,9 @@ public class PropagationManagerImpl implements PropagationManager {
     protected static final Logger LOG = LoggerFactory.getLogger(PropagationManager.class);
 
     @Autowired
+    protected VirSchemaDAO virSchemaDAO;
+
+    @Autowired
     protected AnyObjectDAO anyObjectDAO;
 
     /**
@@ -103,13 +107,10 @@ public class PropagationManagerImpl implements PropagationManager {
     protected ConnObjectUtils connObjectUtils;
 
     @Autowired
-    protected VirAttrHandler virAttrHandler;
-
-    @Autowired
     protected MappingUtils mappingUtils;
 
-    protected Any<?, ?, ?> find(final AnyTypeKind kind, final Long key) {
-        AnyDAO<? extends Any<?, ?, ?>> dao;
+    protected Any<?, ?> find(final AnyTypeKind kind, final Long key) {
+        AnyDAO<? extends Any<?, ?>> dao;
         switch (kind) {
             case ANY_OBJECT:
                 dao = anyObjectDAO;
@@ -135,12 +136,7 @@ public class PropagationManagerImpl implements PropagationManager {
             final Collection<AttrTO> vAttrs,
             final Collection<String> noPropResourceNames) {
 
-        Any<?, ?, ?> any = find(kind, key);
-        if (vAttrs != null && !vAttrs.isEmpty()) {
-            virAttrHandler.createVirtual(any, vAttrs);
-        }
-
-        return getCreateTasks(any, null, null, propByRes, noPropResourceNames);
+        return getCreateTasks(find(kind, key), null, null, propByRes, vAttrs, noPropResourceNames);
     }
 
     @Override
@@ -152,19 +148,15 @@ public class PropagationManagerImpl implements PropagationManager {
             final Collection<AttrTO> vAttrs,
             final Collection<String> noPropResourceNames) {
 
-        User user = userDAO.authFind(key);
-        if (vAttrs != null && !vAttrs.isEmpty()) {
-            virAttrHandler.createVirtual(user, vAttrs);
-        }
-
-        return getCreateTasks(user, password, enable, propByRes, noPropResourceNames);
+        return getCreateTasks(userDAO.authFind(key), password, enable, propByRes, vAttrs, noPropResourceNames);
     }
 
     protected List<PropagationTask> getCreateTasks(
-            final Any<?, ?, ?> any,
+            final Any<?, ?> any,
             final String password,
             final Boolean enable,
             final PropagationByResource propByRes,
+            final Collection<AttrTO> vAttrs,
             final Collection<String> noPropResourceNames) {
 
         if (propByRes == null || propByRes.isEmpty()) {
@@ -175,7 +167,7 @@ public class PropagationManagerImpl implements PropagationManager {
             propByRes.get(ResourceOperation.CREATE).removeAll(noPropResourceNames);
         }
 
-        return createTasks(any, password, true, null, enable, false, propByRes);
+        return createTasks(any, password, true, enable, false, propByRes, vAttrs);
     }
 
     @Override
@@ -185,7 +177,7 @@ public class PropagationManagerImpl implements PropagationManager {
             final boolean changePwd,
             final Boolean enable,
             final PropagationByResource propByRes,
-            final Collection<AttrPatch> vAttrs,
+            final Collection<AttrTO> vAttrs,
             final Collection<String> noPropResourceNames) {
 
         return getUpdateTasks(find(kind, key), null, changePwd, enable, propByRes, vAttrs, noPropResourceNames);
@@ -257,31 +249,19 @@ public class PropagationManagerImpl implements PropagationManager {
     }
 
     protected List<PropagationTask> getUpdateTasks(
-            final Any<?, ?, ?> any,
+            final Any<?, ?> any,
             final String password,
             final boolean changePwd,
             final Boolean enable,
             final PropagationByResource propByRes,
-            final Collection<AttrPatch> vAttrs,
+            final Collection<AttrTO> vAttrs,
             final Collection<String> noPropResourceNames) {
 
-        PropagationByResource localPropByRes = virAttrHandler.updateVirtual(
-                any,
-                vAttrs == null ? Collections.<AttrPatch>emptySet() : vAttrs);
-        localPropByRes.merge(propByRes);
         if (noPropResourceNames != null) {
-            localPropByRes.removeAll(noPropResourceNames);
-        }
-
-        Map<String, AttrPatch> vAttrsMap = null;
-        if (vAttrs != null) {
-            vAttrsMap = new HashMap<>();
-            for (AttrPatch attrPatch : vAttrs) {
-                vAttrsMap.put(attrPatch.getAttrTO().getSchema(), attrPatch);
-            }
+            propByRes.removeAll(noPropResourceNames);
         }
 
-        return createTasks(any, password, changePwd, vAttrsMap, enable, false, localPropByRes);
+        return createTasks(any, password, changePwd, enable, false, propByRes, vAttrs);
     }
 
     @Override
@@ -291,7 +271,7 @@ public class PropagationManagerImpl implements PropagationManager {
             final PropagationByResource propByRes,
             final Collection<String> noPropResourceNames) {
 
-        Any<?, ?, ?> any = find(kind, key);
+        Any<?, ?> any = find(kind, key);
 
         PropagationByResource localPropByRes = new PropagationByResource();
 
@@ -309,109 +289,143 @@ public class PropagationManagerImpl implements PropagationManager {
     }
 
     protected List<PropagationTask> getDeleteTasks(
-            final Any<?, ?, ?> any,
+            final Any<?, ?> any,
             final PropagationByResource propByRes,
             final Collection<String> noPropResourceNames) {
 
-        return createTasks(any, null, false, null, false, true, propByRes);
+        return createTasks(any, null, false, false, true, propByRes, null);
     }
 
     /**
      * Create propagation tasks.
      *
-     * @param any user / group to be provisioned
-     * @param password cleartext password to be provisioned
+     * @param any to be provisioned
+     * @param password clear text password to be provisioned
      * @param changePwd whether password should be included for propagation attributes or not
-     * @param vAttrs virtual attributes to be maaged
      * @param enable whether user must be enabled or not
-     * @param deleteOnResource whether user / group must be deleted anyway from external resource or not
+     * @param deleteOnResource whether any must be deleted anyway from external resource or not
      * @param propByRes operation to be performed per resource
+     * @param vAttrs virtual attributes to be set
      * @return list of propagation tasks created
      */
-    protected List<PropagationTask> createTasks(final Any<?, ?, ?> any,
+    protected List<PropagationTask> createTasks(final Any<?, ?> any,
             final String password, final boolean changePwd,
-            final Map<String, AttrPatch> vAttrs,
-            final Boolean enable, final boolean deleteOnResource, final PropagationByResource propByRes) {
+            final Boolean enable, final boolean deleteOnResource, final PropagationByResource propByRes,
+            final Collection<AttrTO> vAttrs) {
 
-        LOG.debug("Provisioning any {}:\n{}", any, propByRes);
+        LOG.debug("Provisioning {}:\n{}", any, propByRes);
 
-        if (!propByRes.get(ResourceOperation.CREATE).isEmpty() && vAttrs != null) {
-            virAttrHandler.retrieveVirAttrValues(any);
+        // Avoid duplicates - see javadoc
+        propByRes.purge();
+        LOG.debug("After purge {}:\n{}", any, propByRes);
+
+        // Virtual attributes
+        Set<String> virtualResources = new HashSet<>();
+        virtualResources.addAll(propByRes.get(ResourceOperation.CREATE));
+        virtualResources.addAll(propByRes.get(ResourceOperation.UPDATE));
+        if (any instanceof User) {
+            virtualResources.addAll(userDAO.findAllResourceNames((User) any));
+        } else if (any instanceof AnyObject) {
+            virtualResources.addAll(anyObjectDAO.findAllResourceNames((AnyObject) any));
+        } else {
+            virtualResources.addAll(((Group) any).getResourceNames());
+        }
 
-            // update vAttrsToBeUpdated as well
-            for (VirAttr<?> virAttr : any.getVirAttrs()) {
-                String schema = virAttr.getSchema().getKey();
+        Map<String, Set<Attribute>> vAttrMap = new HashMap<>();
+        for (AttrTO vAttr : CollectionUtils.emptyIfNull(vAttrs)) {
+            VirSchema schema = virSchemaDAO.find(vAttr.getSchema());
+            if (schema == null) {
+                LOG.warn("Ignoring invalid {} {}", VirSchema.class.getSimpleName(), vAttr.getSchema());
+            } else if (schema.isReadonly()) {
+                LOG.warn("Ignoring read-only {} {}", VirSchema.class.getSimpleName(), vAttr.getSchema());
+            } else {
+                if (any.getAllowedVirSchemas().contains(schema)
+                        && virtualResources.contains(schema.getProvision().getResource().getKey())) {
+
+                    Set<Attribute> values = vAttrMap.get(schema.getProvision().getResource().getKey());
+                    if (values == null) {
+                        values = new HashSet<>();
+                        vAttrMap.put(schema.getProvision().getResource().getKey(), values);
+                    }
+                    values.add(AttributeBuilder.build(schema.getExtAttrName(), vAttr.getValues()));
 
-                vAttrs.put(schema, new AttrPatch.Builder().
-                        attrTO(new AttrTO.Builder().schema(schema).values(virAttr.getValues()).build()).
-                        build());
+                    propByRes.add(ResourceOperation.UPDATE, schema.getProvision().getResource().getKey());
+                } else {
+                    LOG.warn("{} not owned by or {} not allowed for {}",
+                            schema.getProvision().getResource(), schema, any);
+                }
             }
         }
-
-        // Avoid duplicates - see javadoc
-        propByRes.purge();
-        LOG.debug("After purge: {}", propByRes);
+        LOG.debug("With virtual attributes {}:\n{}\n{}", any, propByRes, vAttrMap);
 
         List<PropagationTask> tasks = new ArrayList<>();
 
-        for (ResourceOperation operation : ResourceOperation.values()) {
-            for (String resourceName : propByRes.get(operation)) {
-                ExternalResource resource = resourceDAO.find(resourceName);
-                Provision provision = resource == null ? null : resource.getProvision(any.getType());
-                if (resource == null) {
-                    LOG.error("Invalid resource name specified: {}, ignoring...", resourceName);
-                } else if (provision == null) {
-                    LOG.error("No provision specified on resource {} for type {}, ignoring...",
-                            resource, any.getType());
-                } else if (MappingUtils.getPropagationMappingItems(provision).isEmpty()) {
-                    LOG.warn("Requesting propagation for {} but no propagation mapping provided for {}",
-                            any.getType(), resource);
-                } else {
-                    PropagationTask task = entityFactory.newEntity(PropagationTask.class);
-                    task.setResource(resource);
-                    task.setObjectClassName(
-                            resource.getProvision(any.getType()).getObjectClass().getObjectClassValue());
-                    task.setAnyTypeKind(any.getType().getKind());
-                    if (!deleteOnResource) {
-                        task.setAnyKey(any.getKey());
-                    }
-                    task.setOperation(operation);
-                    task.setOldConnObjectKey(propByRes.getOldConnObjectKey(resource.getKey()));
-
-                    Pair<String, Set<Attribute>> preparedAttrs = mappingUtils.prepareAttrs(
-                            any, password, changePwd, vAttrs, enable, provision);
-                    task.setConnObjectKey(preparedAttrs.getKey());
-
-                    // Check if any of mandatory attributes (in the mapping) is missing or not received any value: 
-                    // if so, add special attributes that will be evaluated by PropagationTaskExecutor
-                    List<String> mandatoryMissing = new ArrayList<>();
-                    List<String> mandatoryNullOrEmpty = new ArrayList<>();
-                    for (MappingItem item : MappingUtils.getPropagationMappingItems(provision)) {
-                        if (!item.isConnObjectKey()
-                                && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
-
-                            Attribute attr = AttributeUtil.find(item.getExtAttrName(), preparedAttrs.getValue());
-                            if (attr == null) {
-                                mandatoryMissing.add(item.getExtAttrName());
-                            } else if (attr.getValue() == null || attr.getValue().isEmpty()) {
-                                mandatoryNullOrEmpty.add(item.getExtAttrName());
-                            }
+        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
+                    ? Collections.<MappingItem>emptyList()
+                    : MappingUtils.getPropagationMappingItems(provision);
+
+            if (resource == null) {
+                LOG.error("Invalid resource name specified: {}, ignoring...", entry.getKey());
+            } else if (provision == null) {
+                LOG.error("No provision specified on resource {} for type {}, ignoring...",
+                        resource, any.getType());
+            } else if (mappingItems.isEmpty()) {
+                LOG.warn("Requesting propagation for {} but no propagation mapping provided for {}",
+                        any.getType(), resource);
+            } else {
+                PropagationTask task = entityFactory.newEntity(PropagationTask.class);
+                task.setResource(resource);
+                task.setObjectClassName(
+                        resource.getProvision(any.getType()).getObjectClass().getObjectClassValue());
+                task.setAnyTypeKind(any.getType().getKind());
+                task.setAnyType(any.getType().getKey());
+                if (!deleteOnResource) {
+                    task.setAnyKey(any.getKey());
+                }
+                task.setOperation(entry.getValue());
+                task.setOldConnObjectKey(propByRes.getOldConnObjectKey(resource.getKey()));
+
+                Pair<String, Set<Attribute>> preparedAttrs =
+                        mappingUtils.prepareAttrs(any, password, changePwd, enable, provision);
+                task.setConnObjectKey(preparedAttrs.getKey());
+
+                // Check if any of mandatory attributes (in the mapping) is missing or not received any value: 
+                // if so, add special attributes that will be evaluated by PropagationTaskExecutor
+                List<String> mandatoryMissing = new ArrayList<>();
+                List<String> mandatoryNullOrEmpty = new ArrayList<>();
+                for (MappingItem item : mappingItems) {
+                    if (!item.isConnObjectKey()
+                            && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
+
+                        Attribute attr = AttributeUtil.find(item.getExtAttrName(), preparedAttrs.getValue());
+                        if (attr == null) {
+                            mandatoryMissing.add(item.getExtAttrName());
+                        } else if (attr.getValue() == null || attr.getValue().isEmpty()) {
+                            mandatoryNullOrEmpty.add(item.getExtAttrName());
                         }
                     }
-                    if (!mandatoryMissing.isEmpty()) {
-                        preparedAttrs.getValue().add(AttributeBuilder.build(
-                                PropagationTaskExecutor.MANDATORY_MISSING_ATTR_NAME, mandatoryMissing));
-                    }
-                    if (!mandatoryNullOrEmpty.isEmpty()) {
-                        preparedAttrs.getValue().add(AttributeBuilder.build(
-                                PropagationTaskExecutor.MANDATORY_NULL_OR_EMPTY_ATTR_NAME, mandatoryNullOrEmpty));
-                    }
-
-                    task.setAttributes(preparedAttrs.getValue());
-                    tasks.add(task);
+                }
+                if (!mandatoryMissing.isEmpty()) {
+                    preparedAttrs.getValue().add(AttributeBuilder.build(
+                            PropagationTaskExecutor.MANDATORY_MISSING_ATTR_NAME, mandatoryMissing));
+                }
+                if (!mandatoryNullOrEmpty.isEmpty()) {
+                    preparedAttrs.getValue().add(AttributeBuilder.build(
+                            PropagationTaskExecutor.MANDATORY_NULL_OR_EMPTY_ATTR_NAME, mandatoryNullOrEmpty));
+                }
 
-                    LOG.debug("PropagationTask created: {}", task);
+                if (vAttrMap.containsKey(resource.getKey())) {
+                    preparedAttrs.getValue().addAll(vAttrMap.get(resource.getKey()));
                 }
+
+                task.setAttributes(preparedAttrs.getValue());
+
+                tasks.add(task);
+
+                LOG.debug("PropagationTask created: {}", task);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
index 94936eb..dcce5e5 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
@@ -20,25 +20,19 @@ package org.apache.syncope.core.provisioning.java.sync;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.List;
-import java.util.Set;
+import org.apache.commons.collections4.IteratorUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.syncope.common.lib.patch.AnyPatch;
-import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.task.PushTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
@@ -48,7 +42,6 @@ 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.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.Provision;
 import org.apache.syncope.core.provisioning.api.TimeoutException;
@@ -68,9 +61,9 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
     @Autowired
     protected MappingUtils mappingUtils;
 
-    protected abstract String getName(Any<?, ?, ?> any);
+    protected abstract String getName(Any<?, ?> any);
 
-    protected void deprovision(final Any<?, ?, ?> any) {
+    protected void deprovision(final Any<?, ?> any) {
         AnyTO before = getAnyTO(any.getKey());
 
         List<String> noPropResources = new ArrayList<>(before.getResources());
@@ -83,7 +76,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
                 noPropResources));
     }
 
-    protected void provision(final Any<?, ?, ?> any, final Boolean enabled) {
+    protected void provision(final Any<?, ?> any, final Boolean enabled) {
         AnyTO before = getAnyTO(any.getKey());
 
         List<String> noPropResources = new ArrayList<>(before.getResources());
@@ -101,7 +94,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
     }
 
     @SuppressWarnings("unchecked")
-    protected void link(final Any<?, ?, ?> any, final Boolean unlink) {
+    protected void link(final Any<?, ?> any, final Boolean unlink) {
         AnyPatch patch = newPatch(any.getKey());
         patch.getResources().add(new StringPatchItem.Builder().
                 operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
@@ -111,7 +104,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
     }
 
     @SuppressWarnings("unchecked")
-    protected void unassign(final Any<?, ?, ?> any) {
+    protected void unassign(final Any<?, ?> any) {
         AnyPatch patch = newPatch(any.getKey());
         patch.getResources().add(new StringPatchItem.Builder().
                 operation(PatchOperation.DELETE).
@@ -122,7 +115,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
         deprovision(any);
     }
 
-    protected void assign(final Any<?, ?, ?> any, final Boolean enabled) {
+    protected void assign(final Any<?, ?> any, final Boolean enabled) {
         AnyPatch patch = newPatch(any.getKey());
         patch.getResources().add(new StringPatchItem.Builder().
                 operation(PatchOperation.ADD_REPLACE).
@@ -141,7 +134,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
             obj = profile.getConnector().getObject(
                     objectClass,
                     uid,
-                    profile.getConnector().getOperationOptions(Collections.<MappingItem>emptySet()));
+                    profile.getConnector().getOperationOptions(IteratorUtils.<MappingItem>emptyIterator()));
         } catch (TimeoutException toe) {
             LOG.debug("Request timeout", toe);
             throw toe;
@@ -155,7 +148,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
     @Transactional(propagation = Propagation.REQUIRES_NEW)
     @Override
     public boolean handle(final long anyKey) {
-        Any<?, ?, ?> any = null;
+        Any<?, ?> any = null;
         try {
             any = getAny(anyKey);
             doHandle(any);
@@ -176,7 +169,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
         }
     }
 
-    protected final void doHandle(final Any<?, ?, ?> any) throws JobExecutionException {
+    protected final void doHandle(final Any<?, ?> any) throws JobExecutionException {
         AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
 
         ProvisioningResult result = new ProvisioningResult();
@@ -406,33 +399,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
         }
     }
 
-    protected Any<?, ?, ?> update(final Any<?, ?, ?> any, final Boolean enabled) {
-        Set<AttrPatch> vattrs = new HashSet<>();
-
-        // Search for all mapped vattrs
-        Mapping mapping = profile.getTask().getResource().getProvision(any.getType()).getMapping();
-        for (MappingItem mappingItem : mapping.getItems()) {
-            if (mappingItem.getIntMappingType() == IntMappingType.UserVirtualSchema) {
-                vattrs.add(new AttrPatch.Builder().
-                        operation(PatchOperation.DELETE).
-                        attrTO(new AttrTO.Builder().schema(mappingItem.getIntAttrName()).build()).
-                        build());
-            }
-        }
-
-        // Search for all user's vattrs and:
-        // 1. add mapped vattrs not owned by the user to the set of vattrs to be removed
-        // 2. add all vattrs owned by the user to the set of vattrs to be update
-        for (VirAttr<?> vattr : any.getVirAttrs()) {
-            vattrs.add(new AttrPatch.Builder().
-                    operation(PatchOperation.ADD_REPLACE).
-                    attrTO(new AttrTO.Builder().
-                            schema(vattr.getSchema().getKey()).
-                            values(vattr.getValues()).
-                            build()).
-                    build());
-        }
-
+    protected Any<?, ?> update(final Any<?, ?> any, final Boolean enabled) {
         boolean changepwd;
         Collection<String> resourceNames;
         if (any instanceof User) {
@@ -458,7 +425,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
                 changepwd,
                 null,
                 propByRes,
-                vattrs,
+                null,
                 noPropResources));
 
         return getAny(any.getKey());

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
index 2ca7eaa..3967f2b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
@@ -38,12 +38,17 @@ import org.apache.syncope.core.persistence.api.entity.task.SyncTask;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
 import org.apache.syncope.core.provisioning.api.sync.SyncActions;
 import org.apache.syncope.core.misc.security.DelegatedAdministrationException;
+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.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.api.ProvisioningManager;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
 import org.apache.syncope.core.provisioning.api.sync.IgnoreProvisionException;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
 import org.apache.syncope.core.provisioning.api.sync.SyncopeSyncResultHandler;
+import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.SyncDelta;
 import org.identityconnectors.framework.common.objects.SyncDeltaType;
 import org.quartz.JobExecutionException;
@@ -57,6 +62,12 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
     @Autowired
     protected SyncUtils syncUtilities;
 
+    @Autowired
+    protected VirSchemaDAO virSchemaDAO;
+
+    @Autowired
+    protected VirAttrCache virAttrCache;
+
     protected abstract String getName(AnyTO anyTO);
 
     protected abstract ProvisioningManager<?, ?> getProvisioningManager();
@@ -656,6 +667,8 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
 
         try {
             List<Long> anyKeys = syncUtilities.findExisting(uid, delta.getObject(), provision, anyUtils);
+            LOG.debug("Match(es) found for {} as {}: {}",
+                    delta.getUid().getUidValue(), delta.getObject().getObjectClass(), anyKeys);
 
             if (anyKeys.size() > 1) {
                 switch (profile.getResAct()) {
@@ -671,7 +684,7 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
                         break;
 
                     default:
-                    // keep anyIds as is
+                    // keep anyKeys unmodified
                 }
             }
 
@@ -694,25 +707,52 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
                         // do nothing
                     }
                 } else {
+                    // update VirAttrCache
+                    for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
+                        Attribute attr = delta.getObject().getAttributeByName(virSchema.getExtAttrName());
+                        for (Long anyKey : anyKeys) {
+                            if (attr == null) {
+                                virAttrCache.expire(
+                                        provision.getAnyType().getKey(),
+                                        anyKey,
+                                        virSchema.getKey());
+                            } else {
+                                VirAttrCacheValue cacheValue = new VirAttrCacheValue();
+                                cacheValue.setValues(attr.getValue());
+                                virAttrCache.put(
+                                        provision.getAnyType().getKey(),
+                                        anyKey,
+                                        virSchema.getKey(),
+                                        cacheValue);
+                            }
+                        }
+                    }
+
                     switch (profile.getTask().getMatchingRule()) {
                         case UPDATE:
                             profile.getResults().addAll(update(delta, anyKeys, provision));
                             break;
+
                         case DEPROVISION:
                             profile.getResults().addAll(deprovision(delta, anyKeys, provision, false));
                             break;
+
                         case UNASSIGN:
                             profile.getResults().addAll(deprovision(delta, anyKeys, provision, true));
                             break;
+
                         case LINK:
                             profile.getResults().addAll(link(delta, anyKeys, provision, false));
                             break;
+
                         case UNLINK:
                             profile.getResults().addAll(link(delta, anyKeys, provision, true));
                             break;
+
                         case IGNORE:
                             profile.getResults().addAll(ignore(delta, provision, true));
                             break;
+
                         default:
                         // do nothing
                     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
index 2527d5f..570cb76 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
@@ -137,7 +137,7 @@ public abstract class AbstractSyncopeResultHandler<T extends ProvisioningTask, A
 
     protected abstract AnyTO getAnyTO(long key);
 
-    protected abstract Any<?, ?, ?> getAny(long key);
+    protected abstract Any<?, ?> getAny(long key);
 
     protected abstract AnyPatch newPatch(final long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectPushResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectPushResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectPushResultHandlerImpl.java
index 755e818..7d9ab24 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectPushResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectPushResultHandlerImpl.java
@@ -36,12 +36,12 @@ public class AnyObjectPushResultHandlerImpl extends AbstractPushResultHandler im
     }
 
     @Override
-    protected String getName(final Any<?, ?, ?> any) {
+    protected String getName(final Any<?, ?> any) {
         return StringUtils.EMPTY;
     }
 
     @Override
-    protected Any<?, ?, ?> getAny(final long key) {
+    protected Any<?, ?> getAny(final long key) {
         try {
             return anyObjectDAO.authFind(key);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectSyncResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectSyncResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectSyncResultHandlerImpl.java
index 02f0b67..079529d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectSyncResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AnyObjectSyncResultHandlerImpl.java
@@ -54,7 +54,7 @@ public class AnyObjectSyncResultHandlerImpl extends AbstractSyncResultHandler im
     }
 
     @Override
-    protected Any<?, ?, ?> getAny(final long key) {
+    protected Any<?, ?> getAny(final long key) {
         try {
             return anyObjectDAO.authFind(key);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultPushActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultPushActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultPushActions.java
index a99b3e5..15f06e0 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultPushActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultPushActions.java
@@ -34,49 +34,49 @@ public abstract class DefaultPushActions implements PushActions {
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> A beforeAssign(final ProvisioningProfile<?, ?> profile, final A any)
+    public <A extends Any<?, ?>> A beforeAssign(final ProvisioningProfile<?, ?> profile, final A any)
             throws JobExecutionException {
 
         return any;
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> A beforeProvision(final ProvisioningProfile<?, ?> profile, final A any)
+    public <A extends Any<?, ?>> A beforeProvision(final ProvisioningProfile<?, ?> profile, final A any)
             throws JobExecutionException {
 
         return any;
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> A beforeLink(final ProvisioningProfile<?, ?> profile, final A any)
+    public <A extends Any<?, ?>> A beforeLink(final ProvisioningProfile<?, ?> profile, final A any)
             throws JobExecutionException {
 
         return any;
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> A beforeUnassign(final ProvisioningProfile<?, ?> profile, final A any)
+    public <A extends Any<?, ?>> A beforeUnassign(final ProvisioningProfile<?, ?> profile, final A any)
             throws JobExecutionException {
 
         return any;
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> A beforeDeprovision(final ProvisioningProfile<?, ?> profile, final A any)
+    public <A extends Any<?, ?>> A beforeDeprovision(final ProvisioningProfile<?, ?> profile, final A any)
             throws JobExecutionException {
 
         return any;
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> A beforeUnlink(final ProvisioningProfile<?, ?> profile, final A any)
+    public <A extends Any<?, ?>> A beforeUnlink(final ProvisioningProfile<?, ?> profile, final A any)
             throws JobExecutionException {
 
         return any;
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> void onError(
+    public <A extends Any<?, ?>> void onError(
             final ProvisioningProfile<?, ?> profile, final A any, final ProvisioningResult result,
             final Exception error) throws JobExecutionException {
 
@@ -84,7 +84,7 @@ public abstract class DefaultPushActions implements PushActions {
     }
 
     @Override
-    public <A extends Any<?, ?, ?>> void after(
+    public <A extends Any<?, ?>> void after(
             final ProvisioningProfile<?, ?> profile, final A any, final ProvisioningResult result)
             throws JobExecutionException {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupPushResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupPushResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupPushResultHandlerImpl.java
index 2fd1df7..212eb84 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupPushResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupPushResultHandlerImpl.java
@@ -36,12 +36,12 @@ public class GroupPushResultHandlerImpl extends AbstractPushResultHandler implem
     }
 
     @Override
-    protected String getName(final Any<?, ?, ?> any) {
+    protected String getName(final Any<?, ?> any) {
         return Group.class.cast(any).getName();
     }
 
     @Override
-    protected Any<?, ?, ?> getAny(final long key) {
+    protected Any<?, ?> getAny(final long key) {
         try {
             return groupDAO.authFind(key);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
index 2d803b2..c3b9eda 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
@@ -63,7 +63,7 @@ public class GroupSyncResultHandlerImpl extends AbstractSyncResultHandler implem
     }
 
     @Override
-    protected Any<?, ?, ?> getAny(final long key) {
+    protected Any<?, ?> getAny(final long key) {
         try {
             return groupDAO.authFind(key);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobDelegate.java
index ff6ff21..e13407d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobDelegate.java
@@ -145,13 +145,13 @@ public class PushJobDelegate extends AbstractProvisioningJobDelegate<PushTask> {
 
                 int count = anyDAO.count(SyncopeConstants.FULL_ADMIN_REALMS);
                 for (int page = 1; page <= (count / PAGE_SIZE) + 1; page++) {
-                    List<? extends Any<?, ?, ?>> localAnys = StringUtils.isBlank(filter)
+                    List<? extends Any<?, ?>> localAnys = StringUtils.isBlank(filter)
                             ? anyDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, page, PAGE_SIZE)
                             : searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
                                     SearchCondConverter.convert(filter),
                                     Collections.<OrderByClause>emptyList(), provision.getAnyType().getKind());
 
-                    for (Any<?, ?, ?> any : localAnys) {
+                    for (Any<?, ?> any : localAnys) {
                         SyncopePushResultHandler handler;
                         switch (provision.getAnyType().getKind()) {
                             case USER:

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
index 3f19afc..890cece 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobDelegate.java
@@ -19,15 +19,22 @@
 package org.apache.syncope.core.provisioning.java.sync;
 
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.IteratorUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.policy.SyncPolicySpec;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 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.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
+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.persistence.api.entity.task.ProvisioningTask;
 import org.apache.syncope.core.persistence.api.entity.task.SyncTask;
@@ -52,6 +59,9 @@ public class SyncJobDelegate extends AbstractProvisioningJobDelegate<SyncTask> {
     private GroupDAO groupDAO;
 
     @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
     protected SyncUtils syncUtils;
 
     protected void setGroupOwners(final GroupSyncResultHandler ghandler) {
@@ -163,12 +173,25 @@ public class SyncJobDelegate extends AbstractProvisioningJobDelegate<SyncTask> {
                         latestSyncToken = connector.getLatestSyncToken(provision.getObjectClass());
                     }
 
+                    Set<MappingItem> linkinMappingItems = new HashSet<>();
+                    for (VirSchema virSchema : virSchemaDAO.findByProvision(provision)) {
+                        linkinMappingItems.add(virSchema.asLinkingMappingItem());
+                    }
+                    Iterator<MappingItem> mapItems = IteratorUtils.chainedIterator(
+                            provision.getMapping().getItems().iterator(),
+                            linkinMappingItems.iterator());
+
                     if (syncTask.isFullReconciliation()) {
-                        connector.getAllObjects(provision.getObjectClass(), handler,
-                                connector.getOperationOptions(provision.getMapping().getItems()));
+                        connector.getAllObjects(
+                                provision.getObjectClass(),
+                                handler,
+                                connector.getOperationOptions(mapItems));
                     } else {
-                        connector.sync(provision.getObjectClass(), provision.getSyncToken(), handler,
-                                connector.getOperationOptions(provision.getMapping().getItems()));
+                        connector.sync(
+                                provision.getObjectClass(),
+                                provision.getSyncToken(),
+                                handler,
+                                connector.getOperationOptions(mapItems));
                     }
 
                     if (!dryRun && !syncTask.isFullReconciliation()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
index 0c01254..eefccad 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
@@ -128,7 +128,7 @@ public class SyncUtils {
                         return found.add(obj);
                     }
                 },
-                connector.getOperationOptions(MappingUtils.getSyncMappingItems(provision)));
+                connector.getOperationOptions(MappingUtils.getSyncMappingItems(provision).iterator()));
 
         if (found.isEmpty()) {
             LOG.debug("No {} found on {} with __NAME__ {}", provision.getObjectClass(), resource, name);
@@ -199,9 +199,9 @@ public class SyncUtils {
                     }
                 }
 
-                List<? extends Any<?, ?, ?>> anys =
+                List<? extends Any<?, ?>> anys =
                         getAnyDAO(connObjectKeyItem).findByAttrValue(connObjectKeyItem.getIntAttrName(), value);
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     result.add(any.getKey());
                 }
                 break;
@@ -210,7 +210,7 @@ public class SyncUtils {
             case GroupDerivedSchema:
             case AnyObjectDerivedSchema:
                 anys = getAnyDAO(connObjectKeyItem).findByDerAttrValue(connObjectKeyItem.getIntAttrName(), transfUid);
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     result.add(any.getKey());
                 }
                 break;
@@ -218,7 +218,7 @@ public class SyncUtils {
             case UserKey:
             case GroupKey:
             case AnyObjectKey:
-                Any<?, ?, ?> any = getAnyDAO(connObjectKeyItem).find(Long.parseLong(transfUid));
+                Any<?, ?> any = getAnyDAO(connObjectKeyItem).find(Long.parseLong(transfUid));
                 if (any != null) {
                     result.add(any.getKey());
                 }
@@ -249,7 +249,7 @@ public class SyncUtils {
             final ConnectorObject connObj, final SyncCorrelationRule rule, final AnyTypeKind type) {
 
         List<Long> result = new ArrayList<>();
-        for (Any<?, ?, ?> any : searchDAO.search(
+        for (Any<?, ?> any : searchDAO.search(
                 SyncopeConstants.FULL_ADMIN_REALMS,
                 rule.getSearchCond(connObj),
                 Collections.<OrderByClause>emptyList(),

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserPushResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserPushResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserPushResultHandlerImpl.java
index 5829216..8f70560 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserPushResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserPushResultHandlerImpl.java
@@ -41,7 +41,7 @@ public class UserPushResultHandlerImpl extends AbstractPushResultHandler impleme
     }
 
     @Override
-    protected void provision(final Any<?, ?, ?> any, final Boolean enabled) {
+    protected void provision(final Any<?, ?> any, final Boolean enabled) {
         AnyTO before = getAnyTO(any.getKey());
 
         List<String> noPropResources = new ArrayList<>(before.getResources());
@@ -60,12 +60,12 @@ public class UserPushResultHandlerImpl extends AbstractPushResultHandler impleme
     }
 
     @Override
-    protected String getName(final Any<?, ?, ?> any) {
+    protected String getName(final Any<?, ?> any) {
         return User.class.cast(any).getUsername();
     }
 
     @Override
-    protected Any<?, ?, ?> getAny(final long key) {
+    protected Any<?, ?> getAny(final long key) {
         try {
             return userDAO.authFind(key);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserSyncResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserSyncResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserSyncResultHandlerImpl.java
index c5e918a..23e209c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserSyncResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/UserSyncResultHandlerImpl.java
@@ -54,7 +54,7 @@ public class UserSyncResultHandlerImpl extends AbstractSyncResultHandler impleme
     }
 
     @Override
-    protected Any<?, ?, ?> getAny(final long key) {
+    protected Any<?, ?> getAny(final long key) {
         try {
             return userDAO.authFind(key);
         } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
index 39f5573..fe19915 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/ThreadLocalCleanupListener.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.rest.cxf;
 
 import javax.servlet.ServletRequestEvent;
 import javax.servlet.ServletRequestListener;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.identityconnectors.common.l10n.CurrentLocale;
 import org.identityconnectors.framework.impl.api.local.ThreadClassLoaderManager;
 
@@ -36,7 +36,7 @@ public class ThreadLocalCleanupListener implements ServletRequestListener {
 
     @Override
     public void requestDestroyed(final ServletRequestEvent sre) {
-        DataFormat.clear();
+        FormatUtils.clear();
 
         ThreadClassLoaderManager.clearInstance();
         CurrentLocale.clear();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
index d33cde2..4258e64 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractAnyService.java
@@ -179,23 +179,20 @@ public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
 
         P patch = newPatch(key);
 
-        Set<AttrPatch> patches;
         switch (schemaType) {
             case DERIVED:
-                patches = patch.getDerAttrs();
+                patch.getDerAttrs().add(new AttrPatch.Builder().operation(operation).attrTO(attrTO).build());
                 break;
 
             case VIRTUAL:
-                patches = patch.getVirAttrs();
+                patch.getVirAttrs().add(attrTO);
                 break;
 
             case PLAIN:
             default:
-                patches = patch.getPlainAttrs();
+                patch.getPlainAttrs().add(new AttrPatch.Builder().operation(operation).attrTO(attrTO).build());
         }
 
-        patches.add(new AttrPatch.Builder().operation(operation).attrTO(attrTO).build());
-
         update(patch);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
index 158cc09..3f2b690 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/AnyObjectUpdateProcessor.java
@@ -25,7 +25,6 @@ import org.apache.camel.Processor;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
@@ -60,17 +59,6 @@ public class AnyObjectUpdateProcessor implements Processor {
         AnyObjectPatch anyObjectPatch = exchange.getProperty("anyPatch", AnyObjectPatch.class);
         Set<String> excludedResources = exchange.getProperty("excludedResources", Set.class);
 
-        // SYNCOPE-459: take care of user virtual attributes ...
-        PropagationByResource propByResVirAttr = virtAttrHandler.updateVirtual(
-                updated.getResult(),
-                AnyTypeKind.ANY_OBJECT,
-                anyObjectPatch.getVirAttrs());
-        if (updated.getPropByRes() == null) {
-            updated.setPropByRes(propByResVirAttr);
-        } else {
-            updated.getPropByRes().merge(propByResVirAttr);
-        }
-
         List<PropagationTask> tasks = propagationManager.getUpdateTasks(
                 AnyTypeKind.ANY_OBJECT,
                 updated.getResult(),
@@ -79,7 +67,6 @@ public class AnyObjectUpdateProcessor implements Processor {
                 updated.getPropByRes(),
                 anyObjectPatch.getVirAttrs(),
                 excludedResources);
-
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
index 22868bf..599f54b 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
@@ -25,7 +25,6 @@ import org.apache.camel.Processor;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.syncope.common.lib.patch.GroupPatch;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
@@ -60,17 +59,6 @@ public class GroupUpdateProcessor implements Processor {
         GroupPatch groupPatch = exchange.getProperty("anyPatch", GroupPatch.class);
         Set<String> excludedResources = exchange.getProperty("excludedResources", Set.class);
 
-        // SYNCOPE-459: take care of user virtual attributes ...
-        PropagationByResource propByResVirAttr = virtAttrHandler.updateVirtual(
-                updated.getResult(),
-                AnyTypeKind.GROUP,
-                groupPatch.getVirAttrs());
-        if (updated.getPropByRes() == null) {
-            updated.setPropByRes(propByResVirAttr);
-        } else {
-            updated.getPropByRes().merge(propByResVirAttr);
-        }
-
         List<PropagationTask> tasks = propagationManager.getUpdateTasks(
                 AnyTypeKind.GROUP,
                 updated.getResult(),
@@ -79,7 +67,6 @@ public class GroupUpdateProcessor implements Processor {
                 updated.getPropByRes(),
                 groupPatch.getVirAttrs(),
                 excludedResources);
-
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateInSyncProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateInSyncProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateInSyncProcessor.java
index ffdd5d2..8b49a5d 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateInSyncProcessor.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateInSyncProcessor.java
@@ -54,12 +54,10 @@ public class UserUpdateInSyncProcessor implements Processor {
         WorkflowResult<Pair<UserPatch, Boolean>> updated = (WorkflowResult) exchange.getIn().getBody();
         Set<String> excludedResources = exchange.getProperty("excludedResources", Set.class);
 
-        PropagationReporter propagationReporter =
-                ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
-
         List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
                 updated, updated.getResult().getKey().getPassword() != null, excludedResources);
-
+        PropagationReporter propagationReporter =
+                ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         try {
             taskExecutor.execute(tasks, propagationReporter);
         } catch (PropagationException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
index bd0df76..8f175dd 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
@@ -24,8 +24,6 @@ import org.apache.camel.Processor;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.patch.UserPatch;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
@@ -57,30 +55,15 @@ public class UserUpdateProcessor implements Processor {
     @SuppressWarnings("unchecked")
     public void process(final Exchange exchange) {
         WorkflowResult<Pair<UserPatch, Boolean>> updated = (WorkflowResult) exchange.getIn().getBody();
-        UserPatch userPatch = exchange.getProperty("actual", UserPatch.class);
-
-        // SYNCOPE-459: take care of user virtual attributes ...
-        PropagationByResource propByResVirAttr = virtAttrHandler.updateVirtual(
-                updated.getResult().getKey().getKey(),
-                AnyTypeKind.USER,
-                userPatch.getVirAttrs());
-        if (updated.getPropByRes() == null) {
-            updated.setPropByRes(propByResVirAttr);
-        } else {
-            updated.getPropByRes().merge(propByResVirAttr);
-        }
 
         List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(updated);
-
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
-        if (!tasks.isEmpty()) {
-            try {
-                taskExecutor.execute(tasks, propagationReporter);
-            } catch (PropagationException e) {
-                LOG.error("Error propagation primary resource", e);
-                propagationReporter.onPrimaryResourceFailure(tasks);
-            }
+        try {
+            taskExecutor.execute(tasks, propagationReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propagationReporter.onPrimaryResourceFailure(tasks);
         }
 
         exchange.getOut().setBody(new ImmutablePair<>(

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/console-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/console-reference/pom.xml b/fit/console-reference/pom.xml
index b518886..3c89990 100644
--- a/fit/console-reference/pom.xml
+++ b/fit/console-reference/pom.xml
@@ -457,19 +457,19 @@ ORYX.Editor.createByUrl = function(modelUrl){"/>
                   <resource>
                     <directory>${basedir}/../../core/logic/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>logicContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../core/rest-cxf/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>restCXFContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../core/misc/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>securityContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
@@ -478,7 +478,7 @@ ORYX.Editor.createByUrl = function(modelUrl){"/>
                   <resource>
                     <directory>${basedir}/../../core/persistence-jpa/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>persistenceContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
@@ -487,7 +487,7 @@ ORYX.Editor.createByUrl = function(modelUrl){"/>
                   <resource>
                     <directory>${basedir}/../../core/provisioning-java/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>provisioningContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
@@ -496,85 +496,22 @@ ORYX.Editor.createByUrl = function(modelUrl){"/>
                   <resource>
                     <directory>${basedir}/../../core/workflow-java/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>workflowContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../core/workflow-activiti/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>workflowActivitiContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../ext/camel/provisioning-camel/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-
-                  <resource>
-                    <directory>${basedir}/../../common/lib/target/classes</directory>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../common/rest-api/target/classes</directory>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/logic/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/rest-cxf/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/misc/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/persistence-api/target/classes</directory>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/persistence-jpa/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/provisioning-api/target/classes</directory>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/provisioning-java/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/workflow-api/target/classes</directory>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/workflow-java/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../core/workflow-activiti/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
-                    </excludes>
-                  </resource>
-                  <resource>
-                    <directory>${basedir}/../../ext/camel/provisioning-camel/target/classes</directory>
-                    <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>provisioningCamelContext.xml</exclude>
                     </excludes>
                   </resource>
+                  
                   <resource>
                     <directory>${basedir}/../../client/console/target/classes</directory>
                   </resource>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/pom.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml
index 7e0fd9f..724f592 100644
--- a/fit/core-reference/pom.xml
+++ b/fit/core-reference/pom.xml
@@ -758,19 +758,19 @@ under the License.
                   <resource>
                     <directory>${basedir}/../../core/logic/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>logicContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../core/rest-cxf/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>restCXFContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../core/misc/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>securityContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
@@ -779,7 +779,7 @@ under the License.
                   <resource>
                     <directory>${basedir}/../../core/persistence-jpa/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>persistenceContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
@@ -788,7 +788,7 @@ under the License.
                   <resource>
                     <directory>${basedir}/../../core/provisioning-java/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>provisioningContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
@@ -797,19 +797,19 @@ under the License.
                   <resource>
                     <directory>${basedir}/../../core/workflow-java/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>workflowContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../core/workflow-activiti/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>workflowActivitiContext.xml</exclude>
                     </excludes>
                   </resource>
                   <resource>
                     <directory>${basedir}/../../ext/camel/provisioning-camel/target/classes</directory>
                     <excludes>
-                      <exclude>*Context.xml</exclude>
+                      <exclude>provisioningCamelContext.xml</exclude>
                     </excludes>
                   </resource>
                 </resources>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
index 1abb943..148f0eb 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
@@ -59,6 +59,7 @@ import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -218,27 +219,6 @@ public class GroupITCase extends AbstractITCase {
     }
 
     @Test
-    public void updateRemovingVirAttribute() {
-        GroupTO groupTO = getBasicSampleTO("withvirtual" + getUUIDString());
-        groupTO.getVirAttrs().add(attrTO("rvirtualdata", null));
-
-        groupTO = createGroup(groupTO);
-
-        assertNotNull(groupTO);
-        assertEquals(1, groupTO.getVirAttrs().size());
-
-        GroupPatch groupPatch = new GroupPatch();
-        groupPatch.setKey(groupTO.getKey());
-        groupPatch.getVirAttrs().add(new AttrPatch.Builder().operation(PatchOperation.DELETE).
-                attrTO(new AttrTO.Builder().schema("rvirtualdata").build()).
-                build());
-
-        groupTO = updateGroup(groupPatch);
-        assertNotNull(groupTO);
-        assertTrue(groupTO.getVirAttrs().isEmpty());
-    }
-
-    @Test
     public void updateRemovingDerAttribute() {
         GroupTO groupTO = getBasicSampleTO("withderived" + getUUIDString());
         groupTO.getDerAttrs().add(attrTO("rderivedschema", null));
@@ -638,6 +618,10 @@ public class GroupITCase extends AbstractITCase {
             newLDAP.setKey("new-ldap");
             newLDAP.setPropagationPrimary(true);
 
+            for (ProvisionTO provision : newLDAP.getProvisions()) {
+                provision.getVirSchemas().clear();
+            }
+
             MappingTO mapping = newLDAP.getProvision(AnyTypeKind.GROUP.name()).getMapping();
 
             MappingItemTO connObjectKey = mapping.getConnObjectKeyItem();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PropagationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PropagationTaskITCase.java
index 4115bfa..7f2964f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PropagationTaskITCase.java
@@ -85,14 +85,6 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
     }
 
     @Test
-    public void issue196() {
-        TaskExecTO exec = taskService.execute(6L, false);
-        assertNotNull(exec);
-        assertEquals(0, exec.getKey());
-        assertNotNull(exec.getTask());
-    }
-
-    @Test
     public void bulkAction() {
         PagedResult<PropagationTaskTO> before = taskService.list(
                 TaskType.PROPAGATION, SyncopeClient.getTaskQueryBuilder().build());

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
index 75049da..d645c77 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
@@ -607,6 +607,9 @@ public class SyncTaskITCase extends AbstractTaskITCase {
     @Test
     public void issueSYNCOPE307() {
         UserTO userTO = UserITCase.getUniqueSampleTO("s307@apache.org");
+        userTO.setUsername("test0");
+        userTO.getPlainAttrMap().get("firstname").getValues().clear();
+        userTO.getPlainAttrMap().get("firstname").getValues().add("nome0");
         userTO.getAuxClasses().add("csv");
 
         AttrTO csvuserid = new AttrTO();
@@ -615,37 +618,34 @@ public class SyncTaskITCase extends AbstractTaskITCase {
 
         userTO.getResources().clear();
         userTO.getResources().add(RESOURCE_NAME_WS2);
-        userTO.getResources().add(RESOURCE_NAME_CSV);
 
         userTO = createUser(userTO);
         assertNotNull(userTO);
 
         userTO = userService.read(userTO.getKey());
-        assertEquals("virtualvalue", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
+        assertTrue(userTO.getVirAttrMap().isEmpty());
 
         // Update sync task
         SyncTaskTO task = taskService.read(12L);
         assertNotNull(task);
 
-        //  add user template
         UserTO template = new UserTO();
+        template.setPassword("'password123'");
         template.getResources().add(RESOURCE_NAME_DBVIRATTR);
-
-        AttrTO userId = attrTO("userId", "'s307@apache.org'");
-        template.getPlainAttrs().add(userId);
-
-        AttrTO email = attrTO("email", "'s307@apache.org'");
-        template.getPlainAttrs().add(email);
+        template.getVirAttrs().add(attrTO("virtualdata", "'virtualvalue'"));
 
         task.getTemplates().put(AnyTypeKind.USER.name(), template);
 
         taskService.update(task);
+
+        // exec task: one user from CSV will match the user created above and template will be applied
         execProvisioningTask(taskService, task.getKey(), 50, false);
 
-        // check for sync policy
+        // check that template was successfully applied...
         userTO = userService.read(userTO.getKey());
         assertEquals("virtualvalue", userTO.getVirAttrMap().get("virtualdata").getValues().get(0));
 
+        // ...and that propagation to db succeeded
         try {
             JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
 


[08/10] syncope git commit: Removing @Column(nullable = false) in favor of @NotNull - better error messages

Posted by il...@apache.org.
Removing @Column(nullable = false) in favor of @NotNull - better error messages


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

Branch: refs/heads/master
Commit: e20dd0ae315244db0f74b29ffe6096760a7536b6
Parents: 9cd9230
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Oct 22 12:22:06 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Oct 22 12:22:06 2015 +0200

----------------------------------------------------------------------
 .../persistence/jpa/entity/AbstractExec.java    |  4 ++--
 .../persistence/jpa/entity/JPAConnInstance.java |  9 +++++----
 .../persistence/jpa/entity/JPADerSchema.java    |  4 ++--
 .../persistence/jpa/entity/JPANotification.java |  4 ++--
 .../persistence/jpa/entity/JPAPlainSchema.java  |  5 +++--
 .../persistence/jpa/entity/JPAVirSchema.java    |  6 +++---
 .../entity/resource/JPAExternalResource.java    | 16 ++++++++--------
 .../jpa/entity/resource/JPAMapping.java         |  4 ++--
 .../jpa/entity/resource/JPAMappingItem.java     | 11 ++++++-----
 .../persistence/jpa/inner/AnyObjectTest.java    |  5 +++++
 .../persistence/jpa/inner/VirSchemaTest.java    | 12 ++++++++++++
 .../java/data/SchemaDataBinderImpl.java         | 20 +++++++++-----------
 .../fit/core/reference/VirSchemaITCase.java     |  9 ++++++++-
 13 files changed, 67 insertions(+), 42 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
index 5c009d4..a9b5c13 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractExec.java
@@ -20,11 +20,11 @@ package org.apache.syncope.core.persistence.jpa.entity;
 
 import java.util.Date;
 
-import javax.persistence.Column;
 import javax.persistence.Lob;
 import javax.persistence.MappedSuperclass;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
+import javax.validation.constraints.NotNull;
 import org.apache.syncope.core.persistence.api.entity.Exec;
 
 @MappedSuperclass
@@ -32,7 +32,7 @@ public abstract class AbstractExec extends AbstractEntity<Long> implements Exec
 
     private static final long serialVersionUID = -812344822970166317L;
 
-    @Column(nullable = false)
+    @NotNull
     protected String status;
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
index 3929496..054dd69 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAConnInstance.java
@@ -36,6 +36,7 @@ import javax.persistence.JoinColumn;
 import javax.persistence.Lob;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
@@ -63,7 +64,7 @@ public class JPAConnInstance extends AbstractEntity<Long> implements ConnInstanc
     /**
      * URI identifying the local / remote ConnId location where the related connector bundle is found.
      */
-    @Column(nullable = false)
+    @NotNull
     private String location;
 
     /**
@@ -71,7 +72,7 @@ public class JPAConnInstance extends AbstractEntity<Long> implements ConnInstanc
      * Within a given location, the triple
      * (ConnectorBundle-Name, ConnectorBundle-Version, ConnectorBundle-Version) must be unique.
      */
-    @Column(nullable = false)
+    @NotNull
     private String connectorName;
 
     /**
@@ -79,7 +80,7 @@ public class JPAConnInstance extends AbstractEntity<Long> implements ConnInstanc
      * Within a given location, the triple
      * (ConnectorBundle-Name, ConnectorBundle-Version, ConnectorBundle-Version) must be unique.
      */
-    @Column(nullable = false)
+    @NotNull
     private String bundleName;
 
     /**
@@ -87,7 +88,7 @@ public class JPAConnInstance extends AbstractEntity<Long> implements ConnInstanc
      * Within a given location, the triple
      * (ConnectorBundle-Name, ConnectorBundle-Version, ConnectorBundle-Version) must be unique.
      */
-    @Column(nullable = false)
+    @NotNull
     private String version;
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
index 944afc4..45eea22 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
@@ -19,12 +19,12 @@
 package org.apache.syncope.core.persistence.jpa.entity;
 
 import javax.persistence.Cacheable;
-import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
@@ -46,7 +46,7 @@ public class JPADerSchema extends AbstractEntity<String> implements DerSchema {
     @OneToOne(fetch = FetchType.EAGER)
     private JPAAnyTypeClass anyTypeClass;
 
-    @Column(nullable = false)
+    @NotNull
     private String expression;
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
index 7e3d211..1c42cf0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
@@ -84,7 +84,7 @@ public class JPANotification extends AbstractEntity<Long> implements Notificatio
     @NotNull
     private String recipientAttrName;
 
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)
@@ -103,7 +103,7 @@ public class JPANotification extends AbstractEntity<Long> implements Notificatio
     @Enumerated(EnumType.STRING)
     private TraceLevel traceLevel;
 
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
index 68eeacf..4ba6fa3 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
@@ -32,6 +32,7 @@ import javax.persistence.Table;
 import javax.persistence.Transient;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -58,11 +59,11 @@ public class JPAPlainSchema extends AbstractEntity<String> implements PlainSchem
     @OneToOne(fetch = FetchType.EAGER)
     private JPAAnyTypeClass anyTypeClass;
 
-    @Column(nullable = false)
+    @NotNull
     @Enumerated(EnumType.STRING)
     private AttrSchemaType type;
 
-    @Column(nullable = false)
+    @NotNull
     private String mandatoryCondition;
 
     @Basic

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
index b984bb3..419e93a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
@@ -22,7 +22,6 @@ import java.util.Collections;
 import java.util.List;
 import javax.persistence.Basic;
 import javax.persistence.Cacheable;
-import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
@@ -31,6 +30,7 @@ import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -63,11 +63,11 @@ public class JPAVirSchema extends AbstractEntity<String> implements VirSchema {
     @Max(1)
     private Integer readonly;
 
-    @Column(nullable = false)
+    @NotNull
     @ManyToOne
     private JPAProvision provision;
 
-    @Column(nullable = false)
+    @NotNull
     private String extAttrName;
 
     public JPAVirSchema() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
index e9e59fd..de3931e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
@@ -82,7 +82,7 @@ public class JPAExternalResource extends AbstractAnnotatedEntity<String> impleme
     /**
      * Should this resource enforce the mandatory constraints?
      */
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)
@@ -101,7 +101,7 @@ public class JPAExternalResource extends AbstractAnnotatedEntity<String> impleme
     /**
      * Is this resource primary, for propagations?
      */
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)
@@ -110,32 +110,32 @@ public class JPAExternalResource extends AbstractAnnotatedEntity<String> impleme
     /**
      * Priority index for propagation ordering.
      */
-    @Column(nullable = false)
+    @NotNull
     private Integer propagationPriority;
 
     /**
      * Generate random password for propagation, if not provided?
      */
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)
     private Integer randomPwdIfNotProvided;
 
     @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
+    @NotNull
     private TraceLevel createTraceLevel;
 
     @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
+    @NotNull
     private TraceLevel updateTraceLevel;
 
     @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
+    @NotNull
     private TraceLevel deleteTraceLevel;
 
     @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
+    @NotNull
     private TraceLevel syncTraceLevel;
 
     @ManyToOne(fetch = FetchType.EAGER)

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
index 2d7af3c..872fee7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
@@ -22,13 +22,13 @@ import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.Cacheable;
 import javax.persistence.CascadeType;
-import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.types.IntMappingType;
@@ -49,7 +49,7 @@ public class JPAMapping extends AbstractEntity<Long> implements Mapping {
     @Id
     private Long id;
 
-    @Column(nullable = false)
+    @NotNull
     @OneToOne
     private JPAProvision provision;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 8dba286..c3ee73b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -35,6 +35,7 @@ import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
@@ -59,7 +60,7 @@ public class JPAMappingItem extends AbstractEntity<Long> implements MappingItem
     @Column(nullable = true)
     private String intAttrName;
 
-    @Column(nullable = false)
+    @NotNull
     @Enumerated(EnumType.STRING)
     private IntMappingType intMappingType;
 
@@ -72,13 +73,13 @@ public class JPAMappingItem extends AbstractEntity<Long> implements MappingItem
     /**
      * Specify if the mapped target resource's field is nullable.
      */
-    @Column(nullable = false)
+    @NotNull
     private String mandatoryCondition;
 
     /**
      * Specify if the mapped target resource's field is the key.
      */
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)
@@ -87,13 +88,13 @@ public class JPAMappingItem extends AbstractEntity<Long> implements MappingItem
     /**
      * Specify if the mapped target resource's field is the password.
      */
-    @Column(nullable = false)
+    @NotNull
     @Basic
     @Min(0)
     @Max(1)
     private Integer password;
 
-    @Column(nullable = false)
+    @NotNull
     @Enumerated(EnumType.STRING)
     private MappingPurpose purpose;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
index cd6b535..943a94f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
@@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue;
 import java.util.List;
 import org.apache.syncope.common.lib.SyncopeConstants;
 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.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
@@ -37,6 +38,9 @@ import org.springframework.transaction.annotation.Transactional;
 public class AnyObjectTest extends AbstractTest {
 
     @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @Autowired
     private AnyObjectDAO anyObjectDAO;
 
     @Autowired
@@ -68,6 +72,7 @@ public class AnyObjectTest extends AbstractTest {
     @Test
     public void save() {
         AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
+        anyObject.setType(anyTypeDAO.find("PRINTER"));
         anyObject.setRealm(realmDAO.find(SyncopeConstants.ROOT_REALM));
 
         anyObject = anyObjectDAO.save(anyObject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
index 66bd6cb..19193dd 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
@@ -27,9 +27,13 @@ import static org.junit.Assert.fail;
 import java.util.List;
 import org.apache.syncope.common.lib.types.EntityViolationType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
+import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 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.Provision;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -40,6 +44,9 @@ public class VirSchemaTest extends AbstractTest {
     @Autowired
     private VirSchemaDAO virSchemaDAO;
 
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
     @Test
     public void findAll() {
         List<VirSchema> list = virSchemaDAO.findAll();
@@ -54,8 +61,13 @@ public class VirSchemaTest extends AbstractTest {
 
     @Test
     public void save() {
+        ExternalResource csv = resourceDAO.find("resource-csv");
+        Provision provision = csv.getProvision(ObjectClass.ACCOUNT);
+        assertNotNull(provision);
+
         VirSchema virSchema = entityFactory.newEntity(VirSchema.class);
         virSchema.setKey("virtual");
+        virSchema.setProvision(provision);
         virSchema.setReadonly(true);
         virSchema.setExtAttrName("EXT_ATTR");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
index 006a998..6e9837f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
@@ -221,23 +221,21 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
     private VirSchema fill(final VirSchema schema, final VirSchemaTO schemaTO) {
         BeanUtils.copyProperties(schemaTO, schema, IGNORE_PROPERTIES);
 
-        VirSchema merged = virSchemaDAO.save(schema);
-
         if (schemaTO.getAnyTypeClass() != null
-                && (merged.getAnyTypeClass() == null
-                || !schemaTO.getAnyTypeClass().equals(merged.getAnyTypeClass().getKey()))) {
+                && (schema.getAnyTypeClass() == null
+                || !schemaTO.getAnyTypeClass().equals(schema.getAnyTypeClass().getKey()))) {
 
             AnyTypeClass anyTypeClass = anyTypeClassDAO.find(schemaTO.getAnyTypeClass());
             if (anyTypeClass == null) {
                 LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName()
                         + "{}, ignoring...", schemaTO.getAnyTypeClass());
             } else {
-                anyTypeClass.add(merged);
-                merged.setAnyTypeClass(anyTypeClass);
+                anyTypeClass.add(schema);
+                schema.setAnyTypeClass(anyTypeClass);
             }
-        } else if (schemaTO.getAnyTypeClass() == null && merged.getAnyTypeClass() != null) {
-            merged.getAnyTypeClass().remove(merged);
-            merged.setAnyTypeClass(null);
+        } else if (schemaTO.getAnyTypeClass() == null && schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+            schema.setAnyTypeClass(null);
         }
 
         Provision provision = resourceDAO.findProvision(schemaTO.getProvision());
@@ -246,9 +244,9 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
             sce.getElements().add("Provision " + schemaTO.getProvision() + " not found");
             throw sce;
         }
-        merged.setProvision(provision);
+        schema.setProvision(provision);
 
-        return merged;
+        return virSchemaDAO.save(schema);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/e20dd0ae/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
index caae156..c4e4ea0 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirSchemaITCase.java
@@ -112,8 +112,15 @@ public class VirSchemaITCase extends AbstractITCase {
 
     @Test
     public void issueSYNCOPE418() {
+        ResourceTO ws1 = resourceService.read(RESOURCE_NAME_WS1);
+        assertNotNull(ws1);
+        assertEquals(1, ws1.getProvisions().size());
+        assertTrue(ws1.getProvisions().get(0).getVirSchemas().isEmpty());
+
         VirSchemaTO schema = new VirSchemaTO();
         schema.setKey("http://schemas.examples.org/security/authorization/organizationUnit");
+        schema.setExtAttrName("name");
+        schema.setProvision(ws1.getProvisions().get(0).getKey());
 
         try {
             createSchema(SchemaType.VIRTUAL, schema);
@@ -121,7 +128,7 @@ public class VirSchemaITCase extends AbstractITCase {
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidVirSchema, e.getType());
 
-            assertTrue(e.getElements().iterator().next().toString().contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
         }
     }
 }


[06/10] syncope git commit: [SYNCOPE-709] Refactoring completed

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UVirAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UVirAttr.java
deleted file mode 100644
index bb3ab70..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UVirAttr.java
+++ /dev/null
@@ -1,25 +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.persistence.api.entity.user;
-
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-
-public interface UVirAttr extends VirAttr<User> {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
index 884e849..0a51c48 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
@@ -26,7 +26,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
 
-public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
+public interface User extends Any<UPlainAttr, UDerAttr> {
 
     String getUsername();
 
@@ -116,18 +116,6 @@ public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
     @Override
     List<? extends UDerAttr> getDerAttrs();
 
-    @Override
-    boolean add(UVirAttr attr);
-
-    @Override
-    boolean remove(UVirAttr virAttr);
-
-    @Override
-    UVirAttr getVirAttr(String virSchemaName);
-
-    @Override
-    List<? extends UVirAttr> getVirAttrs();
-
     boolean add(Role role);
 
     boolean remove(Role role);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
index edd430e..125b447 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/ContentLoaderHandler.java
@@ -27,7 +27,7 @@ import java.util.Map;
 import javax.sql.DataSource;
 import org.apache.commons.codec.DecoderException;
 import org.apache.commons.codec.binary.Hex;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.dao.DataAccessException;
@@ -125,7 +125,7 @@ class ContentLoaderHandler extends DefaultHandler {
                 case Types.TIME:
                 case Types.TIMESTAMP:
                     try {
-                        parameters[i] = DataFormat.parseDate(attrs.getValue(i));
+                        parameters[i] = FormatUtils.parseDate(attrs.getValue(i));
                     } catch (ParseException e) {
                         LOG.error("Unparsable Date '{}'", attrs.getValue(i));
                         parameters[i] = attrs.getValue(i);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
index 17f4bce..9512849 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/content/XMLContentExporter.java
@@ -50,7 +50,7 @@ import javax.xml.transform.stream.StreamResult;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.content.ContentExporter;
 import org.apache.syncope.core.persistence.jpa.entity.JPAReportExec;
@@ -60,7 +60,6 @@ import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAARelationship;
-import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAnyObject;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPATaskExec;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr;
@@ -69,7 +68,6 @@ import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAURelationship;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 import org.springframework.jdbc.datasource.DataSourceUtils;
 import org.springframework.security.crypto.codec.Hex;
@@ -87,9 +85,9 @@ public class XMLContentExporter extends AbstractContentDealer implements Content
             new HashSet<>(Arrays.asList(new String[] {
                 "QRTZ_", "LOGGING", JPAReportExec.TABLE, JPATaskExec.TABLE,
                 JPAUser.TABLE, JPAUPlainAttr.TABLE, JPAUPlainAttrValue.TABLE, JPAUPlainAttrUniqueValue.TABLE,
-                JPAUDerAttr.TABLE, JPAUVirAttr.TABLE,
+                JPAUDerAttr.TABLE,
                 JPAAnyObject.TABLE, JPAAPlainAttr.TABLE, JPAAPlainAttrValue.TABLE, JPAAPlainAttrUniqueValue.TABLE,
-                JPAADerAttr.TABLE, JPAAVirAttr.TABLE,
+                JPAADerAttr.TABLE,
                 JPAARelationship.TABLE, JPAAMembership.TABLE, JPAURelationship.TABLE, JPAUMembership.TABLE
             }));
 
@@ -206,7 +204,7 @@ public class XMLContentExporter extends AbstractContentDealer implements Content
                 case Types.TIMESTAMP:
                     final Timestamp timestamp = rs.getTimestamp(columnName);
                     if (timestamp != null) {
-                        res = DataFormat.format(new Date(timestamp.getTime()));
+                        res = FormatUtils.format(new Date(timestamp.getTime()));
                     }
                     break;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
----------------------------------------------------------------------
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 95f5b4e..960251f 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
@@ -47,14 +47,13 @@ import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 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.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
-public abstract class AbstractAnyDAO<A extends Any<?, ?, ?>> extends AbstractDAO<A, Long> implements AnyDAO<A> {
+public abstract class AbstractAnyDAO<A extends Any<?, ?>> extends AbstractDAO<A, Long> implements AnyDAO<A> {
 
     @Autowired
     protected PlainSchemaDAO plainSchemaDAO;
@@ -415,13 +414,7 @@ public abstract class AbstractAnyDAO<A extends Any<?, ?, ?>> extends AbstractDAO
 
     @Override
     public A save(final A any) {
-        A merged = entityManager().merge(any);
-        for (VirAttr<?> virAttr : merged.getVirAttrs()) {
-            virAttr.getValues().clear();
-            virAttr.getValues().addAll(any.getVirAttr(virAttr.getSchema().getKey()).getValues());
-        }
-
-        return merged;
+        return entityManager().merge(any);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 2b422eb..2acd683 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -67,7 +67,7 @@ import org.springframework.stereotype.Repository;
 import org.springframework.util.ReflectionUtils;
 
 @Repository
-public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements AnySearchDAO {
+public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?>, Long> implements AnySearchDAO {
 
     private static final String EMPTY_ATTR_QUERY = "SELECT any_id FROM user_search_attr WHERE 1=2";
 
@@ -150,14 +150,14 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements
     }
 
     @Override
-    public <T extends Any<?, ?, ?>> List<T> search(
+    public <T extends Any<?, ?>> List<T> search(
             final Set<String> adminRealms, final SearchCond searchCondition, final AnyTypeKind typeKind) {
 
         return search(adminRealms, searchCondition, Collections.<OrderByClause>emptyList(), typeKind);
     }
 
     @Override
-    public <T extends Any<?, ?, ?>> List<T> search(
+    public <T extends Any<?, ?>> List<T> search(
             final Set<String> adminRealms, final SearchCond searchCondition, final List<OrderByClause> orderBy,
             final AnyTypeKind typeKind) {
 
@@ -165,7 +165,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements
     }
 
     @Override
-    public <T extends Any<?, ?, ?>> List<T> search(
+    public <T extends Any<?, ?>> List<T> search(
             final Set<String> adminRealms, final SearchCond searchCondition, final int page, final int itemsPerPage,
             final List<OrderByClause> orderBy, final AnyTypeKind typeKind) {
 
@@ -189,7 +189,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements
     }
 
     @Override
-    public <T extends Any<?, ?, ?>> boolean matches(
+    public <T extends Any<?, ?>> boolean matches(
             final T any, final SearchCond searchCondition, final AnyTypeKind typeKind) {
 
         List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
@@ -347,7 +347,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?, ?, ?>, Long> implements
     }
 
     @SuppressWarnings("unchecked")
-    private <T extends Any<?, ?, ?>> List<T> doSearch(final Set<String> adminRealms,
+    private <T extends Any<?, ?>> List<T> doSearch(final Set<String> adminRealms,
             final SearchCond nodeCond, final int page, final int itemsPerPage, final List<OrderByClause> orderBy,
             final AnyTypeKind typeKind) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerAttrDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerAttrDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerAttrDAO.java
index 8dff203..99b9014 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerAttrDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerAttrDAO.java
@@ -78,7 +78,7 @@ public class JPADerAttrDAO extends AbstractDAO<DerAttr<?>, Long> implements DerA
     @SuppressWarnings("unchecked")
     public <T extends DerAttr<?>> void delete(final T derAttr) {
         if (derAttr.getOwner() != null) {
-            ((Any<?, T, ?>) derAttr.getOwner()).remove(derAttr);
+            ((Any<?, T>) derAttr.getOwner()).remove(derAttr);
         }
 
         entityManager().remove(derAttr);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
index 3905d92..0650ee9 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
@@ -32,10 +32,12 @@ import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 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.policy.AccountPolicy;
 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.Policy;
+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.Provision;
@@ -43,6 +45,7 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAMappingItem;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAMapping;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAProvision;
 import org.apache.syncope.core.provisioning.api.ConnectorRegistry;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
@@ -67,6 +70,9 @@ public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource, String
     private PolicyDAO policyDAO;
 
     @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
     private ConnectorRegistry connRegistry;
 
     @Override
@@ -74,6 +80,11 @@ public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource, String
         return entityManager().find(JPAExternalResource.class, name);
     }
 
+    @Override
+    public Provision findProvision(final Long key) {
+        return entityManager().find(JPAProvision.class, key);
+    }
+
     private StringBuilder getByPolicyQuery(final PolicyType type) {
         StringBuilder query = new StringBuilder("SELECT e FROM ").
                 append(JPAExternalResource.class.getSimpleName()).
@@ -203,13 +214,6 @@ public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource, String
             policy.remove(resource);
         }
 
-        if (resource.getConnector() != null && resource.getConnector().getResources() != null
-                && !resource.getConnector().getResources().isEmpty()) {
-
-            resource.getConnector().getResources().remove(resource);
-        }
-        resource.setConnector(null);
-
         for (Provision provision : resource.getProvisions()) {
             for (MappingItem item : provision.getMapping().getItems()) {
                 item.setMapping(null);
@@ -217,7 +221,18 @@ public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource, String
             provision.getMapping().getItems().clear();
             provision.setMapping(null);
             provision.setResource(null);
+
+            for (VirSchema schema : virSchemaDAO.findByProvision(provision)) {
+                virSchemaDAO.delete(schema.getKey());
+            }
+        }
+
+        if (resource.getConnector() != null && resource.getConnector().getResources() != null
+                && !resource.getConnector().getResources().isEmpty()) {
+
+            resource.getConnector().getResources().remove(resource);
         }
+        resource.setConnector(null);
 
         entityManager().remove(resource);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index 652c1f7..4c29c90 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -203,7 +203,7 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     }
 
     private void populateTransitiveResources(
-            final Group group, final Any<?, ?, ?> any, final Map<Long, PropagationByResource> result) {
+            final Group group, final Any<?, ?> any, final Map<Long, PropagationByResource> result) {
 
         PropagationByResource propByRes = new PropagationByResource();
         for (ExternalResource resource : group.getResources()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrDAO.java
index d21d1f3..cec3d5b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrDAO.java
@@ -68,7 +68,7 @@ public class JPAPlainAttrDAO extends AbstractDAO<PlainAttr<?>, Long> implements
     @SuppressWarnings("unchecked")
     public <T extends PlainAttr<?>> void delete(final T plainAttr) {
         if (plainAttr.getOwner() != null) {
-            ((Any<T, ?, ?>) plainAttr.getOwner()).remove(plainAttr);
+            ((Any<T, ?>) plainAttr.getOwner()).remove(plainAttr);
         }
 
         entityManager().remove(plainAttr);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
index 312d6fc..60f3786 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.util.List;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrValueDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
@@ -99,7 +100,11 @@ public class JPAPlainAttrValueDAO extends AbstractDAO<PlainAttrValue, Long> impl
     @Override
     public <T extends PlainAttrValue> void delete(final T attrValue) {
         if (attrValue.getAttr() != null) {
-            attrValue.getAttr().remove(attrValue);
+            if (attrValue instanceof PlainAttrUniqueValue) {
+                attrValue.getAttr().setUniqueValue(null);
+            } else {
+                attrValue.getAttr().remove(attrValue);
+            }
         }
 
         entityManager().remove(attrValue);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java
deleted file mode 100644
index 2c8b99f..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirAttrDAO.java
+++ /dev/null
@@ -1,86 +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.persistence.jpa.dao;
-
-import java.util.List;
-import javax.persistence.TypedQuery;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
-import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractVirAttr;
-import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public class JPAVirAttrDAO extends AbstractDAO<VirAttr<?>, Long> implements VirAttrDAO {
-
-    public <T extends VirAttr<?>> Class<? extends AbstractVirAttr<?>> getJPAEntityReference(
-            final Class<T> reference) {
-
-        return GVirAttr.class.isAssignableFrom(reference)
-                ? JPAGVirAttr.class
-                : AVirAttr.class.isAssignableFrom(reference)
-                        ? JPAAVirAttr.class
-                        : UVirAttr.class.isAssignableFrom(reference)
-                                ? JPAUVirAttr.class
-                                : null;
-    }
-
-    @Override
-    public <T extends VirAttr<?>> T find(final Long key, final Class<T> reference) {
-        return reference.cast(entityManager().find(getJPAEntityReference(reference), key));
-    }
-
-    @Override
-    public <T extends VirAttr<?>> List<T> findAll(final Class<T> reference) {
-        TypedQuery<T> query = entityManager().createQuery(
-                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
-        return query.getResultList();
-    }
-
-    @Override
-    public <T extends VirAttr<?>> T save(final T virAttr) {
-        return entityManager().merge(virAttr);
-    }
-
-    @Override
-    public <T extends VirAttr<?>> void delete(final Long key, final Class<T> reference) {
-        T virAttr = find(key, reference);
-        if (virAttr == null) {
-            return;
-        }
-
-        delete(virAttr);
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public <T extends VirAttr<?>> void delete(final T virAttr) {
-        if (virAttr.getOwner() != null) {
-            ((Any<?, ?, T>) virAttr.getOwner()).remove(virAttr);
-        }
-
-        entityManager().remove(virAttr);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
index 46a06f6..d4bce14 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -18,17 +18,18 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.util.Collections;
 import java.util.List;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 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.VirAttr;
+import org.apache.syncope.core.persistence.api.entity.Attr;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
 import org.apache.syncope.core.persistence.jpa.entity.JPAVirSchema;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -38,9 +39,6 @@ import org.springframework.stereotype.Repository;
 public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements VirSchemaDAO {
 
     @Autowired
-    private VirAttrDAO virAttrDAO;
-
-    @Autowired
     private ExternalResourceDAO resourceDAO;
 
     @Override
@@ -61,6 +59,18 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V
     }
 
     @Override
+    public List<VirSchema> findByProvision(final Provision provision) {
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").
+                append(JPAVirSchema.class.getSimpleName()).
+                append(" e WHERE e.provision=:provision");
+
+        TypedQuery<VirSchema> query = entityManager().createQuery(queryString.toString(), VirSchema.class);
+        query.setParameter("provision", provision);
+
+        return query.getResultList();
+    }
+
+    @Override
     public List<VirSchema> findAll() {
         TypedQuery<VirSchema> query = entityManager().createQuery(
                 "SELECT e FROM " + JPAVirSchema.class.getSimpleName() + " e", VirSchema.class);
@@ -68,15 +78,8 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V
     }
 
     @Override
-    public <T extends VirAttr<?>> List<T> findAttrs(final VirSchema schema, final Class<T> reference) {
-        final StringBuilder queryString = new StringBuilder("SELECT e FROM ").
-                append(((JPAVirAttrDAO) virAttrDAO).getJPAEntityReference(reference).getSimpleName()).
-                append(" e WHERE e.schema=:schema");
-
-        TypedQuery<T> query = entityManager().createQuery(queryString.toString(), reference);
-        query.setParameter("schema", schema);
-
-        return query.getResultList();
+    public <T extends Attr<VirSchema, ?>> List<T> findAttrs(final VirSchema schema, final Class<T> reference) {
+        return Collections.emptyList();
     }
 
     @Override
@@ -95,10 +98,6 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V
         for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
             AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
 
-            for (VirAttr<?> attr : findAttrs(schema, anyUtils.virAttrClass())) {
-                virAttrDAO.delete(attr.getKey(), anyUtils.virAttrClass());
-            }
-
             resourceDAO.deleteMapping(key, anyUtils.virIntMappingType());
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
index 2e344b0..041c54f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
@@ -39,7 +39,6 @@ import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 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.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -49,9 +48,9 @@ import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 
 @MappedSuperclass
-public abstract class AbstractAny<P extends PlainAttr<?>, D extends DerAttr<?>, V extends VirAttr<?>>
+public abstract class AbstractAny<P extends PlainAttr<?>, D extends DerAttr<?>>
         extends AbstractAnnotatedEntity<Long>
-        implements Any<P, D, V> {
+        implements Any<P, D> {
 
     private static final long serialVersionUID = -2666540708092702810L;
 
@@ -127,18 +126,6 @@ public abstract class AbstractAny<P extends PlainAttr<?>, D extends DerAttr<?>,
         });
     }
 
-    @Override
-    public V getVirAttr(final String virSchemaName) {
-        return CollectionUtils.find(getVirAttrs(), new Predicate<V>() {
-
-            @Override
-            public boolean evaluate(final V virAttr) {
-                return virAttr != null && virAttr.getSchema() != null
-                        && virSchemaName.equals(virAttr.getSchema().getKey());
-            }
-        });
-    }
-
     protected abstract List<JPAExternalResource> internalGetResources();
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
index ec37649..694b18f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
@@ -28,7 +28,7 @@ import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Schema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 
-public abstract class AbstractAttr<S extends Schema, O extends Any<?, ?, ?>>
+public abstract class AbstractAttr<S extends Schema, O extends Any<?, ?>>
         extends AbstractEntity<Long> implements Attr<S, O> {
 
     private static final long serialVersionUID = -7722134717360731874L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
index 4500a4e..59f390d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
@@ -30,7 +30,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 
 @MappedSuperclass
-public abstract class AbstractDerAttr<O extends Any<?, ?, ?>>
+public abstract class AbstractDerAttr<O extends Any<?, ?>>
         extends AbstractAttr<DerSchema, O> implements DerAttr<O> {
 
     private static final long serialVersionUID = 4740924251090424771L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDynMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDynMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDynMembership.java
index c5404e9..c7110d5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDynMembership.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDynMembership.java
@@ -24,7 +24,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DynMembership;
 
 @MappedSuperclass
-public abstract class AbstractDynMembership<A extends Any<?, ?, ?>>
+public abstract class AbstractDynMembership<A extends Any<?, ?>>
         extends AbstractEntity<Long> implements DynMembership<A> {
 
     private static final long serialVersionUID = 921821654690948787L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttr.java
index 4bab427..fdd257e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttr.java
@@ -37,7 +37,7 @@ import org.apache.syncope.core.persistence.jpa.validation.entity.PlainAttrCheck;
 
 @MappedSuperclass
 @PlainAttrCheck
-public abstract class AbstractPlainAttr<O extends Any<?, ?, ?>>
+public abstract class AbstractPlainAttr<O extends Any<?, ?>>
         extends AbstractAttr<PlainSchema, O> implements PlainAttr<O> {
 
     private static final long serialVersionUID = -9115431608821806124L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractPlainAttrValue.java
----------------------------------------------------------------------
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 424e6a2..7032df6 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
@@ -32,11 +32,11 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
-import org.apache.syncope.core.misc.DataFormat;
 import org.apache.syncope.core.persistence.jpa.validation.entity.PlainAttrValueCheck;
 import org.apache.syncope.core.misc.security.Encryptor;
 
@@ -153,7 +153,7 @@ public abstract class AbstractPlainAttrValue extends AbstractEntity<Long> implem
                 try {
                     this.setLongValue(schema.getConversionPattern() == null
                             ? Long.valueOf(value)
-                            : DataFormat.parseNumber(value, schema.getConversionPattern()).longValue());
+                            : FormatUtils.parseNumber(value, schema.getConversionPattern()).longValue());
                 } catch (Exception pe) {
                     exception = pe;
                 }
@@ -163,7 +163,7 @@ public abstract class AbstractPlainAttrValue extends AbstractEntity<Long> implem
                 try {
                     this.setDoubleValue(schema.getConversionPattern() == null
                             ? Double.valueOf(value)
-                            : DataFormat.parseNumber(value, schema.getConversionPattern()).doubleValue());
+                            : FormatUtils.parseNumber(value, schema.getConversionPattern()).doubleValue());
                 } catch (Exception pe) {
                     exception = pe;
                 }
@@ -172,8 +172,8 @@ public abstract class AbstractPlainAttrValue extends AbstractEntity<Long> implem
             case Date:
                 try {
                     this.setDateValue(schema.getConversionPattern() == null
-                            ? DataFormat.parseDate(value)
-                            : new Date(DataFormat.parseDate(value, schema.getConversionPattern()).getTime()));
+                            ? FormatUtils.parseDate(value)
+                            : new Date(FormatUtils.parseDate(value, schema.getConversionPattern()).getTime()));
                 } catch (Exception pe) {
                     exception = pe;
                 }
@@ -246,21 +246,21 @@ public abstract class AbstractPlainAttrValue extends AbstractEntity<Long> implem
                 result = getAttr() == null || getAttr().getSchema() == null
                         || getAttr().getSchema().getConversionPattern() == null
                                 ? getLongValue().toString()
-                                : DataFormat.format(getLongValue(), getAttr().getSchema().getConversionPattern());
+                                : FormatUtils.format(getLongValue(), getAttr().getSchema().getConversionPattern());
                 break;
 
             case Double:
                 result = getAttr() == null || getAttr().getSchema() == null
                         || getAttr().getSchema().getConversionPattern() == null
                                 ? getDoubleValue().toString()
-                                : DataFormat.format(getDoubleValue(), getAttr().getSchema().getConversionPattern());
+                                : FormatUtils.format(getDoubleValue(), getAttr().getSchema().getConversionPattern());
                 break;
 
             case Date:
                 result = getAttr() == null || getAttr().getSchema() == null
                         || getAttr().getSchema().getConversionPattern() == null
-                                ? DataFormat.format(getDateValue())
-                                : DataFormat.format(getDateValue(), false, getAttr().getSchema().
+                                ? FormatUtils.format(getDateValue())
+                                : FormatUtils.format(getDateValue(), false, getAttr().getSchema().
                                         getConversionPattern());
                 break;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
deleted file mode 100644
index aebc8da..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
+++ /dev/null
@@ -1,71 +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.persistence.jpa.entity;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.persistence.Column;
-import javax.persistence.FetchType;
-import javax.persistence.ManyToOne;
-import javax.persistence.MappedSuperclass;
-import javax.persistence.Transient;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-import org.apache.syncope.core.persistence.api.entity.VirSchema;
-
-@MappedSuperclass
-public abstract class AbstractVirAttr<O extends Any<?, ?, ?>>
-        extends AbstractAttr<VirSchema, O> implements VirAttr<O> {
-
-    private static final long serialVersionUID = 5023204776925954907L;
-
-    @Transient
-    protected List<String> values = new ArrayList<>();
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    @Column(name = "schema_name")
-    private JPAVirSchema schema;
-
-    @Override
-    public List<String> getValues() {
-        return values;
-    }
-
-    @Override
-    public boolean add(final String value) {
-        return !values.contains(value) && values.add(value);
-    }
-
-    @Override
-    public boolean remove(final String value) {
-        return values.remove(value);
-    }
-
-    @Override
-    public VirSchema getSchema() {
-        return schema;
-    }
-
-    @Override
-    public void setSchema(final VirSchema schema) {
-        checkType(schema, JPAVirSchema.class);
-        this.schema = (JPAVirSchema) schema;
-        checkSchema(this.schema);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
index 4e8044d..c63a401 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AnnotatedEntityListener.java
@@ -33,10 +33,10 @@ public class AnnotatedEntityListener {
     @PrePersist
     @PreUpdate
     public void setSysInfo(final AnnotatedEntity<?> entity) {
-        final String username = AuthContextUtils.getUsername();
+        String username = AuthContextUtils.getUsername();
         LOG.debug("Set system properties for '{}'", entity);
 
-        final Date now = new Date();
+        Date now = new Date();
 
         if (entity.getCreationDate() == null) {
             LOG.debug("Set creation date '{}' and creator '{}' for '{}'", now, username, entity);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
index 645c60c..7de2fbe 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
@@ -29,24 +29,20 @@ import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
 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.VirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrValue;
-import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAnyObject;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrValue;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrValue;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 
 @SuppressWarnings({ "unchecked", "rawtypes" })
@@ -64,7 +60,7 @@ public class JPAAnyUtils implements AnyUtils {
     }
 
     @Override
-    public <T extends Any<?, ?, ?>> Class<T> anyClass() {
+    public <T extends Any<?, ?>> Class<T> anyClass() {
         Class result;
 
         switch (anyTypeKind) {
@@ -266,52 +262,6 @@ public class JPAAnyUtils implements AnyUtils {
     }
 
     @Override
-    public <T extends VirAttr<?>> Class<T> virAttrClass() {
-        Class result = null;
-
-        switch (anyTypeKind) {
-            case USER:
-                result = JPAUVirAttr.class;
-                break;
-
-            case GROUP:
-                result = JPAGVirAttr.class;
-                break;
-
-            case ANY_OBJECT:
-                result = JPAAVirAttr.class;
-                break;
-
-            default:
-        }
-
-        return result;
-    }
-
-    @Override
-    public <T extends VirAttr<?>> T newVirAttr() {
-        T result = null;
-
-        switch (anyTypeKind) {
-            case USER:
-                result = (T) new JPAUVirAttr();
-                break;
-
-            case GROUP:
-                result = (T) new JPAGVirAttr();
-                break;
-
-            case ANY_OBJECT:
-                result = (T) new JPAAVirAttr();
-                break;
-
-            default:
-        }
-
-        return result;
-    }
-
-    @Override
     public IntMappingType plainIntMappingType() {
         IntMappingType result = null;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtilsFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtilsFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtilsFactory.java
index f68b3f9..38e08b4 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtilsFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtilsFactory.java
@@ -41,7 +41,7 @@ public class JPAAnyUtilsFactory implements AnyUtilsFactory {
     }
 
     @Override
-    public AnyUtils getInstance(final Any<?, ?, ?> any) {
+    public AnyUtils getInstance(final Any<?, ?> any) {
         AnyTypeKind type = null;
         if (any instanceof User) {
             type = AnyTypeKind.USER;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index 4c3b816..372e062 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -64,7 +64,6 @@ import org.apache.syncope.core.persistence.api.entity.group.GDerAttr;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
 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;
@@ -85,7 +84,6 @@ import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
-import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADynGroupMembership;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAMembership;
@@ -102,7 +100,6 @@ import org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrValue;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAMapping;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAMappingItem;
@@ -122,7 +119,6 @@ import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAURelationship;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 import org.springframework.stereotype.Component;
 
@@ -202,8 +198,6 @@ public class JPAEntityFactory implements EntityFactory {
             result = (T) new JPAUDerAttr();
         } else if (reference.equals(VirSchema.class)) {
             result = (T) new JPAVirSchema();
-        } else if (reference.equals(UVirAttr.class)) {
-            result = (T) new JPAUVirAttr();
         } else if (reference.equals(Mapping.class)) {
             result = (T) new JPAMapping();
         } else if (reference.equals(MappingItem.class)) {
@@ -216,8 +210,6 @@ public class JPAEntityFactory implements EntityFactory {
             result = (T) new JPAGPlainAttrUniqueValue();
         } else if (reference.equals(GDerAttr.class)) {
             result = (T) new JPAGDerAttr();
-        } else if (reference.equals(GVirAttr.class)) {
-            result = (T) new JPAGVirAttr();
         } else if (reference.equals(CPlainAttr.class)) {
             result = (T) new JPACPlainAttr();
         } else if (reference.equals(CPlainAttrValue.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
index 6c1dd73..b984bb3 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
@@ -18,18 +18,28 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import java.util.Collections;
+import java.util.List;
 import javax.persistence.Basic;
 import javax.persistence.Cacheable;
+import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
+import javax.persistence.ManyToOne;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
+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.Provision;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAProvision;
 import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaNameCheck;
 
 @Entity
@@ -53,6 +63,13 @@ public class JPAVirSchema extends AbstractEntity<String> implements VirSchema {
     @Max(1)
     private Integer readonly;
 
+    @Column(nullable = false)
+    @ManyToOne
+    private JPAProvision provision;
+
+    @Column(nullable = false)
+    private String extAttrName;
+
     public JPAVirSchema() {
         super();
 
@@ -109,4 +126,134 @@ public class JPAVirSchema extends AbstractEntity<String> implements VirSchema {
     public void setReadonly(final boolean readonly) {
         this.readonly = getBooleanAsInteger(readonly);
     }
+
+    @Override
+    public Provision getProvision() {
+        return provision;
+    }
+
+    @Override
+    public void setProvision(final Provision provision) {
+        checkType(provision, JPAProvision.class);
+        this.provision = (JPAProvision) provision;
+    }
+
+    @Override
+    public String getExtAttrName() {
+        return extAttrName;
+    }
+
+    @Override
+    public void setExtAttrName(final String extAttrName) {
+        this.extAttrName = extAttrName;
+    }
+
+    @Override
+    public MappingItem asLinkingMappingItem() {
+        return new MappingItem() {
+
+            private static final long serialVersionUID = 327455459536715529L;
+
+            @Override
+            public Long getKey() {
+                return -1L;
+            }
+
+            @Override
+            public Mapping getMapping() {
+                return getProvision().getMapping();
+            }
+
+            @Override
+            public void setMapping(final Mapping mapping) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public String getExtAttrName() {
+                return JPAVirSchema.this.getExtAttrName();
+            }
+
+            @Override
+            public void setExtAttrName(final String extAttrName) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public String getIntAttrName() {
+                return JPAVirSchema.this.getKey();
+            }
+
+            @Override
+            public void setIntAttrName(final String intAttrName) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public IntMappingType getIntMappingType() {
+                switch (getProvision().getAnyType().getKind()) {
+                    case ANY_OBJECT:
+                        return IntMappingType.AnyObjectVirtualSchema;
+
+                    case GROUP:
+                        return IntMappingType.GroupVirtualSchema;
+
+                    case USER:
+                    default:
+                        return IntMappingType.UserVirtualSchema;
+                }
+            }
+
+            @Override
+            public void setIntMappingType(final IntMappingType intMappingType) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public String getMandatoryCondition() {
+                return JPAVirSchema.this.getMandatoryCondition();
+            }
+
+            @Override
+            public void setMandatoryCondition(final String condition) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public MappingPurpose getPurpose() {
+                return JPAVirSchema.this.isReadonly() ? MappingPurpose.SYNCHRONIZATION : MappingPurpose.BOTH;
+            }
+
+            @Override
+            public void setPurpose(final MappingPurpose purpose) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public boolean isConnObjectKey() {
+                return false;
+            }
+
+            @Override
+            public void setConnObjectKey(final boolean connObjectKey) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public boolean isPassword() {
+                return false;
+            }
+
+            @Override
+            public void setPassword(final boolean password) {
+                // RO instance, nothing to do
+            }
+
+            @Override
+            public List<String> getMappingItemTransformerClassNames() {
+                return Collections.emptyList();
+            }
+        };
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
index 25cc5eb..01be6a8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
@@ -60,7 +60,7 @@ public class JPAAPlainAttrUniqueValue extends AbstractPlainAttrValue implements
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPAAPlainAttr.class);
         this.attribute = (JPAAPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
index 73c962c..0c9e598 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
@@ -57,7 +57,7 @@ public class JPAAPlainAttrValue extends AbstractPlainAttrValue implements APlain
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPAAPlainAttr.class);
         this.attribute = (JPAAPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
deleted file mode 100644
index 62e2ea5..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
+++ /dev/null
@@ -1,59 +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.persistence.jpa.entity.anyobject;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractVirAttr;
-
-@Entity
-@Table(name = JPAAVirAttr.TABLE)
-public class JPAAVirAttr extends AbstractVirAttr<AnyObject> implements AVirAttr {
-
-    private static final long serialVersionUID = -4935990254545760827L;
-
-    public static final String TABLE = "AVirAttr";
-
-    @Id
-    private Long id;
-
-    @ManyToOne
-    private JPAAnyObject owner;
-
-    @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
-    public AnyObject getOwner() {
-        return owner;
-    }
-
-    @Override
-    public void setOwner(final AnyObject owner) {
-        checkType(owner, JPAAnyObject.class);
-        this.owner = (JPAAnyObject) owner;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index 3e9feda..9d69735 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -42,7 +42,6 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.ADerAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractAny;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyType;
@@ -52,7 +51,7 @@ import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResour
 @Entity
 @Table(name = JPAAnyObject.TABLE)
 @Cacheable
-public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> implements AnyObject {
+public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr> implements AnyObject {
 
     private static final long serialVersionUID = 9063766472970643492L;
 
@@ -72,10 +71,6 @@ public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> im
     @Valid
     private List<JPAADerAttr> derAttrs = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
-    @Valid
-    private List<JPAAVirAttr> virAttrs = new ArrayList<>();
-
     @ManyToMany(fetch = FetchType.EAGER)
     @JoinTable(joinColumns =
             @JoinColumn(name = "anyObject_id"),
@@ -149,23 +144,6 @@ public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> im
     }
 
     @Override
-    public boolean add(final AVirAttr attr) {
-        checkType(attr, JPAAVirAttr.class);
-        return virAttrs.add((JPAAVirAttr) attr);
-    }
-
-    @Override
-    public boolean remove(final AVirAttr attr) {
-        checkType(attr, JPAAVirAttr.class);
-        return virAttrs.remove((JPAAVirAttr) attr);
-    }
-
-    @Override
-    public List<? extends AVirAttr> getVirAttrs() {
-        return virAttrs;
-    }
-
-    @Override
     protected List<JPAExternalResource> internalGetResources() {
         return resources;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
index 4783911..fea5af4 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
@@ -60,7 +60,7 @@ public class JPACPlainAttrUniqueValue extends AbstractPlainAttrValue implements
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPACPlainAttr.class);
         this.attribute = (JPACPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
index 2761a84..5b7d2b3 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
@@ -57,7 +57,7 @@ public class JPACPlainAttrValue extends AbstractPlainAttrValue implements CPlain
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPACPlainAttr.class);
         this.attribute = (JPACPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
index 2b44253..ac5616a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
@@ -37,7 +37,6 @@ import org.apache.syncope.core.persistence.api.entity.DerAttr;
 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.Realm;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.conf.Conf;
@@ -120,26 +119,6 @@ public class JPAConf extends AbstractAnnotatedEntity<Long> implements Conf {
     }
 
     @Override
-    public boolean add(final VirAttr<?> attr) {
-        return false;
-    }
-
-    @Override
-    public boolean remove(final VirAttr<?> virAttr) {
-        return false;
-    }
-
-    @Override
-    public VirAttr<?> getVirAttr(final String virSchemaName) {
-        return null;
-    }
-
-    @Override
-    public List<? extends VirAttr<?>> getVirAttrs() {
-        return Collections.emptyList();
-    }
-
-    @Override
     public boolean add(final ExternalResource resource) {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrUniqueValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrUniqueValue.java
index 3efae7c..a5c1b90 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrUniqueValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrUniqueValue.java
@@ -60,7 +60,7 @@ public class JPAGPlainAttrUniqueValue extends AbstractPlainAttrValue implements
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPAGPlainAttr.class);
         this.attribute = (JPAGPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
index ed93477..e5d0830 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
@@ -57,7 +57,7 @@ public class JPAGPlainAttrValue extends AbstractPlainAttrValue implements GPlain
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPAGPlainAttr.class);
         this.attribute = (JPAGPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
deleted file mode 100644
index 47b8886..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
+++ /dev/null
@@ -1,59 +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.persistence.jpa.entity.group;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractVirAttr;
-
-@Entity
-@Table(name = JPAGVirAttr.TABLE)
-public class JPAGVirAttr extends AbstractVirAttr<Group> implements GVirAttr {
-
-    private static final long serialVersionUID = -1747430556914428649L;
-
-    public static final String TABLE = "GVirAttr";
-
-    @Id
-    private Long id;
-
-    @ManyToOne
-    private JPAGroup owner;
-
-    @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
-    public Group getOwner() {
-        return owner;
-    }
-
-    @Override
-    public void setOwner(final Group owner) {
-        checkType(owner, JPAGroup.class);
-        this.owner = (JPAGroup) owner;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
index 2913dc6..2fb84b5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
@@ -44,7 +44,6 @@ import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.group.GDerAttr;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
 import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
@@ -61,7 +60,7 @@ import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 @Table(name = JPAGroup.TABLE)
 @Cacheable
 @GroupCheck
-public class JPAGroup extends AbstractAny<GPlainAttr, GDerAttr, GVirAttr> implements Group {
+public class JPAGroup extends AbstractAny<GPlainAttr, GDerAttr> implements Group {
 
     private static final long serialVersionUID = -5281258853142421875L;
 
@@ -88,10 +87,6 @@ public class JPAGroup extends AbstractAny<GPlainAttr, GDerAttr, GVirAttr> implem
     @Valid
     private List<JPAGDerAttr> derAttrs = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
-    @Valid
-    private List<JPAGVirAttr> virAttrs = new ArrayList<>();
-
     @ManyToMany(fetch = FetchType.EAGER)
     @JoinTable(joinColumns =
             @JoinColumn(name = "group_id"),
@@ -205,23 +200,6 @@ public class JPAGroup extends AbstractAny<GPlainAttr, GDerAttr, GVirAttr> implem
     }
 
     @Override
-    public boolean add(final GVirAttr attr) {
-        checkType(attr, JPAGVirAttr.class);
-        return virAttrs.add((JPAGVirAttr) attr);
-    }
-
-    @Override
-    public boolean remove(final GVirAttr attr) {
-        checkType(attr, JPAGVirAttr.class);
-        return virAttrs.remove((JPAGVirAttr) attr);
-    }
-
-    @Override
-    public List<? extends GVirAttr> getVirAttrs() {
-        return virAttrs;
-    }
-
-    @Override
     public ADynGroupMembership getADynMembership() {
         return aDynMembership;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
index 2066f6f..2d7af3c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.Cacheable;
 import javax.persistence.CascadeType;
+import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
@@ -48,12 +49,10 @@ public class JPAMapping extends AbstractEntity<Long> implements Mapping {
     @Id
     private Long id;
 
+    @Column(nullable = false)
     @OneToOne
     private JPAProvision provision;
 
-    /**
-     * Attribute mappings.
-     */
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "mapping")
     private List<JPAMappingItem> items = new ArrayList<>();
 
@@ -79,17 +78,6 @@ public class JPAMapping extends AbstractEntity<Long> implements Mapping {
     }
 
     @Override
-    public void setConnObjectKeyItem(final MappingItem item) {
-        checkType(item, JPAMappingItem.class);
-        this.addConnObjectKeyItem((JPAMappingItem) item);
-    }
-
-    @Override
-    public List<? extends MappingItem> getItems() {
-        return items;
-    }
-
-    @Override
     public boolean add(final MappingItem item) {
         checkType(item, JPAMappingItem.class);
         return items.contains((JPAMappingItem) item) || items.add((JPAMappingItem) item);
@@ -102,6 +90,11 @@ public class JPAMapping extends AbstractEntity<Long> implements Mapping {
     }
 
     @Override
+    public List<? extends MappingItem> getItems() {
+        return items;
+    }
+
+    @Override
     public MappingItem getConnObjectKeyItem() {
         return CollectionUtils.find(getItems(), new Predicate<MappingItem>() {
 
@@ -112,6 +105,12 @@ public class JPAMapping extends AbstractEntity<Long> implements Mapping {
         });
     }
 
+    @Override
+    public void setConnObjectKeyItem(final MappingItem item) {
+        checkType(item, JPAMappingItem.class);
+        this.addConnObjectKeyItem((JPAMappingItem) item);
+    }
+
     protected boolean addConnObjectKeyItem(final MappingItem connObjectKeyItem) {
         if (IntMappingType.UserVirtualSchema == connObjectKeyItem.getIntMappingType()
                 || IntMappingType.GroupVirtualSchema == connObjectKeyItem.getIntMappingType()

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
index 8e13879..3906dfd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAProvision.java
@@ -131,5 +131,4 @@ public class JPAProvision extends AbstractEntity<Long> implements Provision {
         checkType(mapping, JPAMapping.class);
         this.mapping = (JPAMapping) mapping;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
index 2bdd0f3..9882752 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPropagationTask.java
@@ -75,6 +75,8 @@ public class JPAPropagationTask extends AbstractTask implements PropagationTask
     @Enumerated(EnumType.STRING)
     private AnyTypeKind anyTypeKind;
 
+    private String anyType;
+
     private Long anyKey;
 
     public JPAPropagationTask() {
@@ -167,6 +169,16 @@ public class JPAPropagationTask extends AbstractTask implements PropagationTask
     }
 
     @Override
+    public String getAnyType() {
+        return anyType;
+    }
+
+    @Override
+    public void setAnyType(final String anyType) {
+        this.anyType = anyType;
+    }
+
+    @Override
     public Long getAnyKey() {
         return anyKey;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
index 566739d..86dfdfa 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrUniqueValue.java
@@ -60,7 +60,7 @@ public class JPAUPlainAttrUniqueValue extends AbstractPlainAttrValue implements
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPAUPlainAttr.class);
         this.attribute = (JPAUPlainAttr) attr;
     }


[05/10] syncope git commit: [SYNCOPE-709] Refactoring completed

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
index 73645b4..2eca97c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
@@ -57,7 +57,7 @@ public class JPAUPlainAttrValue extends AbstractPlainAttrValue implements UPlain
     }
 
     @Override
-    public void setAttr(final PlainAttr attr) {
+    public void setAttr(final PlainAttr<?> attr) {
         checkType(attr, JPAUPlainAttr.class);
         this.attribute = (JPAUPlainAttr) attr;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
deleted file mode 100644
index a6931ce..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
+++ /dev/null
@@ -1,59 +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.persistence.jpa.entity.user;
-
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractVirAttr;
-
-@Entity
-@Table(name = JPAUVirAttr.TABLE)
-public class JPAUVirAttr extends AbstractVirAttr<User> implements UVirAttr {
-
-    private static final long serialVersionUID = 2943450934283989741L;
-
-    public static final String TABLE = "UVirAttr";
-
-    @Id
-    private Long id;
-
-    @ManyToOne
-    private JPAUser owner;
-
-    @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
-    public User getOwner() {
-        return owner;
-    }
-
-    @Override
-    public void setOwner(final User owner) {
-        checkType(owner, JPAUser.class);
-        this.owner = (JPAUser) owner;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index 74335ec..9ba4fea 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -54,7 +54,6 @@ import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.entity.user.SecurityQuestion;
 import org.apache.syncope.core.persistence.api.entity.user.UDerAttr;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
 import org.apache.syncope.core.persistence.jpa.entity.JPASecurityQuestion;
@@ -75,7 +74,7 @@ import org.apache.syncope.core.persistence.jpa.entity.JPARole;
 @Entity
 @Table(name = JPAUser.TABLE)
 @Cacheable
-public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> implements User {
+public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr> implements User {
 
     private static final long serialVersionUID = -3905046855521446823L;
 
@@ -105,10 +104,6 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme
     @Valid
     private List<JPAUDerAttr> derAttrs = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
-    @Valid
-    private List<JPAUVirAttr> virAttrs = new ArrayList<>();
-
     private String workflowId;
 
     @Column(nullable = true)
@@ -322,23 +317,6 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme
     }
 
     @Override
-    public boolean add(final UVirAttr attr) {
-        checkType(attr, JPAUVirAttr.class);
-        return virAttrs.add((JPAUVirAttr) attr);
-    }
-
-    @Override
-    public boolean remove(final UVirAttr attr) {
-        checkType(attr, JPAUVirAttr.class);
-        return virAttrs.remove((JPAUVirAttr) attr);
-    }
-
-    @Override
-    public List<? extends UVirAttr> getVirAttrs() {
-        return virAttrs;
-    }
-
-    @Override
     public String getWorkflowId() {
         return workflowId;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
index fb5a0a9..e7f3a85 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
@@ -25,7 +25,12 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+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.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -39,7 +44,7 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
     private boolean isValid(final MappingItem item, final ConstraintValidatorContext context) {
         if (StringUtils.isBlank(item.getExtAttrName())) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + ".extAttrName is null")).
+                    getTemplate(EntityViolationType.InvalidMapping, item + " - extAttrName is null")).
                     addPropertyNode("extAttrName").addConstraintViolation();
 
             return false;
@@ -47,7 +52,7 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
 
         if (StringUtils.isBlank(item.getIntAttrName())) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + ".intAttrName is null")).
+                    getTemplate(EntityViolationType.InvalidMapping, item + " - intAttrName is null")).
                     addPropertyNode("intAttrName").addConstraintViolation();
 
             return false;
@@ -55,12 +60,46 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
 
         if (item.getPurpose() == null) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + ".purpose is null")).
+                    getTemplate(EntityViolationType.InvalidMapping, item + " - purpose is null")).
                     addPropertyNode("purpose").addConstraintViolation();
 
             return false;
         }
 
+        if (item.getIntMappingType() == IntMappingType.AnyObjectVirtualSchema
+                || item.getIntMappingType() == IntMappingType.GroupVirtualSchema
+                || item.getIntMappingType() == IntMappingType.UserVirtualSchema) {
+
+            if (item.getPurpose() != MappingPurpose.PROPAGATION) {
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidMapping,
+                                " - only " + MappingPurpose.PROPAGATION.name() + " allowed for virtual")).
+                        addPropertyNode("purpose").addConstraintViolation();
+
+                return false;
+            }
+
+            if (item.getMapping() == null) {
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidMapping,
+                                " - need to explicitly set mapping for further checks")).
+                        addPropertyNode("mapping").addConstraintViolation();
+
+                return false;
+            }
+
+            VirSchema schema = ApplicationContextProvider.getBeanFactory().getBean(VirSchemaDAO.class).
+                    find(item.getIntAttrName());
+            if (schema != null && schema.getProvision().equals(item.getMapping().getProvision())) {
+                context.buildConstraintViolationWithTemplate(
+                        getTemplate(EntityViolationType.InvalidMapping,
+                                " - no need to map virtual schema on linking resource")).
+                        addPropertyNode("intAttrName").addConstraintViolation();
+
+                return false;
+            }
+        }
+
         return true;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrCheck.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrCheck.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrCheck.java
index d5d546b..2613a22 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrCheck.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrCheck.java
@@ -33,7 +33,7 @@ import javax.validation.Payload;
 @Documented
 public @interface PlainAttrCheck {
 
-    String message() default "{org.apache.syncope.syncope.validation.attr}";
+    String message() default "{org.apache.syncope.core.persistence.validation.attr}";
 
     Class<?>[] groups() default {};
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValidator.java
index 5dc7f55..f2c3c86 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValidator.java
@@ -43,7 +43,7 @@ public class PlainAttrValidator extends AbstractValidator<PlainAttrCheck, PlainA
 
             if (!isValid) {
                 LOG.error("Invalid values for attribute " + object + ": " + "schema=" + object.getSchema().getKey()
-                        + ", " + "values={}", object.getValuesAsStrings());
+                        + ", values={}", object.getValuesAsStrings());
 
                 context.disableDefaultConstraintViolation();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
index 02c8c8b..5ddee8c 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
@@ -337,31 +337,6 @@ under the License.
     </attributes>
   </entity>
 
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-
   <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAAnyTemplateRealm">
     <attributes>
       <id name="id">

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
index 02c8c8b..5ddee8c 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
@@ -337,31 +337,6 @@ under the License.
     </attributes>
   </entity>
 
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-
   <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAAnyTemplateRealm">
     <attributes>
       <id name="id">

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
index b5c54b6..f4f2b07 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
@@ -384,31 +384,6 @@ under the License.
       </id>
     </attributes>
   </entity>
-
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
-  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
-    <attributes>
-      <id name="id">
-        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
-        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
-      </id>
-    </attributes>
-  </entity>
   
   <entity class="org.apache.syncope.core.persistence.jpa.entity.JPAAnyTemplateRealm">
     <attributes>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/main/resources/indexes.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/indexes.xml b/core/persistence-jpa/src/main/resources/indexes.xml
index f5ae8f7..a2d4c62 100644
--- a/core/persistence-jpa/src/main/resources/indexes.xml
+++ b/core/persistence-jpa/src/main/resources/indexes.xml
@@ -68,9 +68,5 @@ under the License.
   <entry key="GDerAttr_owner_id_index">CREATE INDEX GDerAttr_owner_id_index on GDerAttr(owner_id)</entry>
   <entry key="ADerAttr_owner_id_index">CREATE INDEX ADerAttr_owner_id_index on ADerAttr(owner_id)</entry>
 
-  <entry key="UVirAttr_owner_id_index">CREATE INDEX UVirAttr_owner_id_index on UVirAttr(owner_id)</entry>
-  <entry key="GVirAttr_owner_id_index">CREATE INDEX GVirAttr_owner_id_index on GVirAttr(owner_id)</entry>
-  <entry key="AVirAttr_owner_id_index">CREATE INDEX AVirAttr_owner_id_index on AVirAttr(owner_id)</entry>
-
   <entry key="Task_executedIndex">CREATE INDEX Task_executedIndex ON Task(executed)</entry>
 </properties>

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
index fe53386..3cea9ab 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
@@ -118,7 +118,6 @@ public class PlainAttrTest extends AbstractTest {
         user.add(attribute);
 
         Exception thrown = null;
-
         try {
             attribute.add("A", anyUtilsFactory.getInstance(AnyTypeKind.USER));
         } catch (ValidationException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
index bdfd645..0fc2a3e 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
@@ -260,6 +260,52 @@ public class ResourceTest extends AbstractTest {
     }
 
     @Test
+    public void saveVirtualMapping() {
+        ExternalResource resource = entityFactory.newEntity(ExternalResource.class);
+        resource.setKey("ws-target-resource-virtual-mapping");
+        resource.setPropagationPriority(2);
+        resource.setPropagationPrimary(true);
+
+        Provision provision = entityFactory.newEntity(Provision.class);
+        provision.setAnyType(anyTypeDAO.findUser());
+        provision.setObjectClass(ObjectClass.ACCOUNT);
+        provision.setResource(resource);
+        resource.add(provision);
+
+        Mapping mapping = entityFactory.newEntity(Mapping.class);
+        mapping.setProvision(provision);
+        provision.setMapping(mapping);
+
+        MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
+        connObjectKey.setExtAttrName("username");
+        connObjectKey.setIntAttrName("fullname");
+        connObjectKey.setIntMappingType(IntMappingType.UserKey);
+        connObjectKey.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(connObjectKey);
+
+        MappingItem virtualMapItem = entityFactory.newEntity(MappingItem.class);
+        virtualMapItem.setIntMappingType(IntMappingType.UserVirtualSchema);
+        virtualMapItem.setIntAttrName("virtualReadOnly");
+        virtualMapItem.setExtAttrName("TEST");
+        virtualMapItem.setPurpose(MappingPurpose.BOTH);
+        virtualMapItem.setMapping(mapping);
+        mapping.add(virtualMapItem);
+
+        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        try {
+            resourceDAO.save(resource);
+            fail();
+        } catch (InvalidEntityException e) {
+            assertNotNull(e);
+        }
+
+        virtualMapItem.setPurpose(MappingPurpose.PROPAGATION);
+        resourceDAO.save(resource);
+    }
+
+    @Test
     public void saveWithGroupMappingType() {
         ExternalResource resource = entityFactory.newEntity(ExternalResource.class);
         resource.setKey("ws-target-resource-basic-save-invalid");

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
index 7377475..f39f06f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/TaskTest.java
@@ -113,6 +113,7 @@ public class TaskTest extends AbstractTest {
         PropagationTask task = entityFactory.newEntity(PropagationTask.class);
         task.setResource(resource);
         task.setAnyTypeKind(AnyTypeKind.USER);
+        task.setAnyType(AnyTypeKind.USER.name());
         task.setOperation(ResourceOperation.CREATE);
         task.setConnObjectKey("one@two.com");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirAttrTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirAttrTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirAttrTest.java
deleted file mode 100644
index fd13cd6..0000000
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirAttrTest.java
+++ /dev/null
@@ -1,118 +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.persistence.jpa.inner;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.util.List;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
-import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
-import org.apache.syncope.core.persistence.api.entity.VirSchema;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.persistence.jpa.AbstractTest;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-@Transactional("Master")
-public class VirAttrTest extends AbstractTest {
-
-    @Autowired
-    private VirAttrDAO virAttrDAO;
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private GroupDAO groupDAO;
-
-    @Autowired
-    private VirSchemaDAO virSchemaDAO;
-
-    @Test
-    public void findAll() {
-        List<UVirAttr> list = virAttrDAO.findAll(UVirAttr.class);
-        assertEquals("did not get expected number of derived attributes ", 1, list.size());
-    }
-
-    @Test
-    public void findById() {
-        UVirAttr attribute = virAttrDAO.find(100L, UVirAttr.class);
-        assertNotNull("did not find expected attribute schema", attribute);
-    }
-
-    @Test
-    public void saveUVirAttribute() {
-        VirSchema virSchema = virSchemaDAO.find("virtualdata");
-        assertNotNull(virSchema);
-
-        User owner = userDAO.find(3L);
-        assertNotNull("did not get expected user", owner);
-
-        UVirAttr virAttr = entityFactory.newEntity(UVirAttr.class);
-        virAttr.setOwner(owner);
-        virAttr.setSchema(virSchema);
-
-        virAttr = virAttrDAO.save(virAttr);
-
-        UVirAttr actual = virAttrDAO.find(virAttr.getKey(), UVirAttr.class);
-        assertNotNull("expected save to work", actual);
-        assertEquals(virAttr, actual);
-    }
-
-    @Test
-    public void saveGVirAttribute() {
-        VirSchema virSchema = virSchemaDAO.find("rvirtualdata");
-        assertNotNull(virSchema);
-
-        Group owner = groupDAO.find(3L);
-        assertNotNull("did not get expected membership", owner);
-
-        GVirAttr virAttr = entityFactory.newEntity(GVirAttr.class);
-        virAttr.setOwner(owner);
-        virAttr.setSchema(virSchema);
-
-        virAttr = virAttrDAO.save(virAttr);
-
-        GVirAttr actual = virAttrDAO.find(virAttr.getKey(), GVirAttr.class);
-        assertNotNull("expected save to work", actual);
-        assertEquals(virAttr, actual);
-    }
-
-    @Test
-    public void delete() {
-        UVirAttr attribute = virAttrDAO.find(100L, UVirAttr.class);
-        String attributeSchemaName = attribute.getSchema().getKey();
-
-        virAttrDAO.delete(attribute.getKey(), UVirAttr.class);
-
-        UVirAttr actual = virAttrDAO.find(1000L, UVirAttr.class);
-        assertNull("delete did not work", actual);
-
-        VirSchema attributeSchema = virSchemaDAO.find(attributeSchemaName);
-        assertNotNull("user virtual attribute schema deleted " + "when deleting values", attributeSchema);
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
index 10970d1..66bd6cb 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
@@ -43,7 +43,7 @@ public class VirSchemaTest extends AbstractTest {
     @Test
     public void findAll() {
         List<VirSchema> list = virSchemaDAO.findAll();
-        assertEquals(4, list.size());
+        assertEquals(3, list.size());
     }
 
     @Test
@@ -54,15 +54,17 @@ public class VirSchemaTest extends AbstractTest {
 
     @Test
     public void save() {
-        VirSchema virtualAttributeSchema = entityFactory.newEntity(VirSchema.class);
-        virtualAttributeSchema.setKey("virtual");
-        virtualAttributeSchema.setReadonly(true);
+        VirSchema virSchema = entityFactory.newEntity(VirSchema.class);
+        virSchema.setKey("virtual");
+        virSchema.setReadonly(true);
+        virSchema.setExtAttrName("EXT_ATTR");
 
-        virSchemaDAO.save(virtualAttributeSchema);
+        virSchemaDAO.save(virSchema);
 
         VirSchema actual = virSchemaDAO.find("virtual");
         assertNotNull("expected save to work", actual);
         assertTrue(actual.isReadonly());
+        assertEquals("EXT_ATTR", actual.getExtAttrName());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
index 5628c29..2a8a090 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
@@ -38,8 +38,10 @@ import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 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.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
+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.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
@@ -75,6 +77,9 @@ public class ResourceTest extends AbstractTest {
     @Autowired
     private PolicyDAO policyDAO;
 
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
     @Test
     public void createWithPasswordPolicy() {
         final String resourceName = "resourceWithPasswordPolicy";
@@ -269,7 +274,11 @@ public class ResourceTest extends AbstractTest {
             itemKeys.add(item.getKey());
         }
 
-        ldap.remove(ldap.getProvision(anyTypeDAO.findGroup()));
+        Provision groupProvision = ldap.getProvision(anyTypeDAO.findGroup());
+        ldap.remove(groupProvision);
+        for (VirSchema schema : virSchemaDAO.findByProvision(groupProvision)) {
+            virSchemaDAO.delete(schema.getKey());
+        }
 
         // need to avoid any class not defined in this Maven module
         ldap.getPropagationActionsClassNames().clear();
@@ -277,8 +286,8 @@ public class ResourceTest extends AbstractTest {
         resourceDAO.save(ldap);
         resourceDAO.flush();
 
-        for (Long itemId : itemKeys) {
-            assertNull(entityManager().find(JPAMappingItem.class, itemId));
+        for (Long itemKey : itemKeys) {
+            assertNull(entityManager().find(JPAMappingItem.class, itemKey));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
index 2b3d6c7..53f88d8 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
@@ -92,6 +92,7 @@ public class TaskTest extends AbstractTest {
         PropagationTask task = entityFactory.newEntity(PropagationTask.class);
         task.setResource(resource);
         task.setAnyTypeKind(AnyTypeKind.USER);
+        task.setAnyType(AnyTypeKind.USER.name());
         task.setOperation(ResourceOperation.CREATE);
         task.setConnObjectKey("one@two.com");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
new file mode 100644
index 0000000..bd68313
--- /dev/null
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.outer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+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.persistence.jpa.AbstractTest;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional("Master")
+public class VirSchemaTest extends AbstractTest {
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Test
+    public void deal() {
+        Provision provision = resourceDAO.findProvision(15L);
+        assertNotNull(provision);
+        assertTrue(virSchemaDAO.findByProvision(provision).isEmpty());
+
+        VirSchema virSchema = entityFactory.newEntity(VirSchema.class);
+        virSchema.setKey("vSchema");
+        virSchema.setReadonly(true);
+        virSchema.setExtAttrName("EXT_ATTR");
+        virSchema.setProvision(provision);
+
+        virSchemaDAO.save(virSchema);
+        virSchemaDAO.flush();
+
+        virSchema = virSchemaDAO.find("vSchema");
+        assertNotNull("expected save to work", virSchema);
+        assertTrue(virSchema.isReadonly());
+        assertEquals("EXT_ATTR", virSchema.getExtAttrName());
+
+        provision = resourceDAO.findProvision(15L);
+        assertNotNull(provision);
+        assertFalse(virSchemaDAO.findByProvision(provision).isEmpty());
+        assertTrue(virSchemaDAO.findByProvision(provision).contains(virSchema));
+
+        MappingItem item = virSchema.asLinkingMappingItem();
+        assertNotNull(item);
+        assertEquals(IntMappingType.UserVirtualSchema, item.getIntMappingType());
+        assertEquals(virSchema.getKey(), item.getIntAttrName());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 7ee8002..96e606f 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -326,9 +326,6 @@ under the License.
   <DerSchema name="cn" expression="surname + ', ' + firstname" anyTypeClass_name="minimal user"/>
   <DerSchema name="noschema" expression="surname + ', ' + notfound" anyTypeClass_name="other"/>
 
-  <VirSchema name="virtualdata" anyTypeClass_name="minimal user"/>
-  <VirSchema name="virtualReadOnly" READONLY="1"  anyTypeClass_name="minimal user"/>
-
   <PlainSchema name="icon" type="String" anyTypeClass_name="minimal group"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>                
   <PlainSchema name="show" type="Boolean" anyTypeClass_name="minimal group"
@@ -347,8 +344,6 @@ under the License.
   <DerSchema name="rderToBePropagated" expression="rderived_sx + '-' + rderived_dx"
              anyTypeClass_name="minimal group"/>
 
-  <VirSchema name="rvirtualdata" anyTypeClass_name="minimal group"/>
-
   <DerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx"  anyTypeClass_name="minimal group"/>
 
   <PlainSchema name="subscriptionDate" type="Date" anyTypeClass_name="generic membership"
@@ -364,8 +359,6 @@ under the License.
   <DerSchema name="mderiveddata" expression="mderived_sx + '-' + mderived_dx"/>
   <DerSchema name="mderToBePropagated" expression="mderived_sx + '-' + mderived_dx" 
              anyTypeClass_name="generic membership"/>
-
-  <VirSchema name="mvirtualdata"/>
         
   <PlainSchema name="model" type="String" anyTypeClass_name="minimal printer"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
@@ -444,8 +437,6 @@ under the License.
   <UPlainAttrValue id="36" attribute_id="125" stringValue="vivaldi@syncope.org"/>
   <UPlainAttr id="126" owner_id="3" schema_name="type"/>
   <UPlainAttrValue id="37" attribute_id="126" stringValue="F"/>
-    
-  <UVirAttr id="100" schema_name="virtualdata" owner_id="3"/>
   
   <UDerAttr id="100" schema_name="cn" owner_id="3"/>
   <UDerAttr id="101" schema_name="cn" owner_id="1"/>
@@ -485,8 +476,6 @@ under the License.
 
   <GDerAttr id="103" owner_id="1" schema_name="rderToBePropagated"/>    
 
-  <GVirAttr id="98" owner_id="4" schema_name="rvirtualdata"/>
-
   <ConnInstance id="100" displayName="ConnInstance100"
                 location="${connid.location}"
                 bundleName="net.tirasa.connid.bundles.soap"
@@ -763,7 +752,7 @@ under the License.
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="110" extAttrName="name" mapping_id="1"
                intAttrName="virtualdata" intMappingType="UserVirtualSchema" mandatoryCondition="type == 'F'"
-               connObjectKey="0" password="0" purpose="BOTH"/>
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="111" extAttrName="fullname" mapping_id="1"
                intAttrName="cn" intMappingType="UserDerivedSchema" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="BOTH"/>
@@ -892,9 +881,6 @@ under the License.
   <MappingItem id="318" connObjectKey="0" password="0" mapping_id="11"
                extAttrName="mail" intAttrName="userId" intMappingType="UserPlainSchema"
                mandatoryCondition="false" purpose="BOTH"/>
-  <MappingItem id="319" connObjectKey="0" password="0" mapping_id="11"
-               extAttrName="givenname" intAttrName="virtualReadOnly" intMappingType="UserVirtualSchema"
-               mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="320" connObjectKey="0" password="0" mapping_id="11"
                extAttrName="registeredAddress" intAttrName="obscure" intMappingType="UserPlainSchema"
                mandatoryCondition="false" purpose="BOTH"/>
@@ -902,6 +888,9 @@ under the License.
                extAttrName="jpegPhoto" intAttrName="photo" intMappingType="UserPlainSchema"
                mandatoryCondition="false" purpose="BOTH"/>
         
+  <VirSchema name="virtualReadOnly" READONLY="1" anyTypeClass_name="minimal user"
+             provision_id="11" extAttrName="givenname"/>
+
   <Provision id="20" resource_name="resource-ldap" anyType_name="GROUP" objectClass="__GROUP__"/>
   <Mapping id="20" provision_id="20"
            connObjectLink="&apos;cn=&apos; + name + &apos;,ou=groups,o=isp&apos;"/>
@@ -914,10 +903,9 @@ under the License.
   <MappingItem id="3" connObjectKey="0" password="0" mapping_id="20"
                extAttrName="description" intAttrName="title" intMappingType="GroupPlainSchema"
                mandatoryCondition="false" purpose="BOTH"/>
-  <MappingItem id="4" extAttrName="businessCategory" mapping_id="20"
-               intAttrName="rvirtualdata" intMappingType="GroupVirtualSchema" mandatoryCondition="false"
-               connObjectKey="0" password="0" purpose="BOTH"/>
   
+  <VirSchema name="rvirtualdata" anyTypeClass_name="minimal group" provision_id="20" extAttrName="businessCategory"/>
+
   <Provision id="16" resource_name="resource-db-sync" anyType_name="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="16" provision_id="16"/>
   <MappingItem id="322" connObjectKey="0" mapping_id="16"
@@ -944,10 +932,9 @@ under the License.
   <MappingItem id="331" mapping_id="17" connObjectKey="1" password="0"
                extAttrName="id" intMappingType="UserKey" 
                mandatoryCondition="true" purpose="BOTH"/>
-  <MappingItem id="332" mapping_id="17" connObjectKey="0" password="0" 
-               extAttrName="USERNAME" intAttrName="virtualdata" intMappingType="UserVirtualSchema"
-               mandatoryCondition="false" purpose="BOTH"/>
                 
+  <VirSchema name="virtualdata" anyTypeClass_name="minimal user" provision_id="17" extAttrName="USERNAME"/>
+  
   <Provision id="18" resource_name="ws-target-resource-timeout" anyType_name="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="18" provision_id="18"/>
   <MappingItem id="333" mapping_id="18" connObjectKey="1" password="0"

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/Connector.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/Connector.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/Connector.java
index 1be141f..ce8adba 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/Connector.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/Connector.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.api;
 
-import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import org.apache.syncope.common.lib.types.ResourceOperation;
@@ -59,10 +59,11 @@ public interface Connector {
      * @param propagationAttempted if creation is actually performed (based on connector instance's capabilities)
      * @return Uid for created object
      */
-    Uid create(ObjectClass objectClass,
+    Uid create(
+            ObjectClass objectClass,
             Set<Attribute> attrs,
             OperationOptions options,
-            Set<String> propagationAttempted);
+            Boolean[] propagationAttempted);
 
     /**
      * Update user / group on a connector instance.
@@ -71,14 +72,15 @@ public interface Connector {
      * @param uid user to be updated
      * @param attrs attributes for update
      * @param options ConnId's OperationOptions
-     * @param propagationAttempted if update is actually performed (based on connector instance's capabilities)
+     * @param propagationAttempted if creation is actually performed (based on connector instance's capabilities)
      * @return Uid for updated object
      */
-    Uid update(ObjectClass objectClass,
+    Uid update(
+            ObjectClass objectClass,
             Uid uid,
             Set<Attribute> attrs,
             OperationOptions options,
-            Set<String> propagationAttempted);
+            Boolean[] propagationAttempted);
 
     /**
      * Delete user / group on a connector instance.
@@ -88,8 +90,11 @@ public interface Connector {
      * @param options ConnId's OperationOptions
      * @param propagationAttempted if deletion is actually performed (based on connector instance's capabilities)
      */
-    void delete(ObjectClass objectClass,
-            Uid uid, OperationOptions options, Set<String> propagationAttempted);
+    void delete(
+            ObjectClass objectClass,
+            Uid uid,
+            OperationOptions options,
+            Boolean[] propagationAttempted);
 
     /**
      * Fetches all remote objects (for use during full reconciliation).
@@ -169,6 +174,7 @@ public interface Connector {
      * query results
      * @param orderBy the sort keys which should be used for ordering the {@link ConnectorObject} returned by
      * search request
+     * @param mapItems mapping items
      */
     void search(
             ObjectClass objectClass,
@@ -176,7 +182,8 @@ public interface Connector {
             ResultsHandler handler,
             int pageSize,
             String pagedResultsCookie,
-            List<OrderByClause> orderBy);
+            List<OrderByClause> orderBy,
+            Iterator<? extends MappingItem> mapItems);
 
     /**
      * Read attribute for a given connector object.
@@ -238,5 +245,5 @@ public interface Connector {
      * @return options for requesting all mapped connector attributes
      * @see OperationOptions
      */
-    OperationOptions getOperationOptions(Collection<? extends MappingItem> mapItems);
+    OperationOptions getOperationOptions(Iterator<? extends MappingItem> mapItems);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
index 95e751e..2e31204 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
@@ -18,56 +18,32 @@
  */
 package org.apache.syncope.core.provisioning.api;
 
-import java.util.Collection;
-import org.apache.syncope.common.lib.patch.AttrPatch;
-import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
-import org.apache.syncope.common.lib.types.PropagationByResource;
+import java.util.List;
+import java.util.Map;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 
 public interface VirAttrHandler {
 
     /**
-     * Create and add virtual attributes to any.
+     * Query external resource (or cache, if configured) associated to the given any for values associated to the given
+     * virtual schema.
      *
-     * @param any any
-     * @param vAttrs virtual attributes to be added.
-     */
-    void createVirtual(Any any, Collection<AttrTO> vAttrs);
-
-    /**
-     * Update virtual attributes to any.
-     *
-     * @param any
-     * @param vAttrs virtual attributes to be updated.
-     * @return operations to be performed on external resources for virtual attributes changes
-     */
-    PropagationByResource updateVirtual(Any any, Collection<AttrPatch> vAttrs);
-
-    /**
-     * Update virtual attributes to any identified by the given {@code key}.
-     *
-     * @param key any key
-     * @param anyTypeKind type kind
-     * @param vAttrs virtual attributes to be updated.
-     * @return operations to be performed on external resources for virtual attributes changes
+     * @param any any object
+     * @param schema virtual schema
+     * @return virtual attribute values, either for local cache or external resource, if resource is owned by the given
+     * any and associated to the given virtual schema; empty list otherwise.
      */
-    PropagationByResource updateVirtual(Long key, AnyTypeKind anyTypeKind, Collection<AttrPatch> vAttrs);
-
-    VirSchema getVirSchema(String virSchemaName);
+    List<String> getValues(Any<?, ?> any, VirSchema schema);
 
     /**
-     * Query connected external resources for values to populated virtual attributes associated with the given owner.
+     * Query external resources (or cache, if configured) associated to the given any for values associated to all
+     * {@link VirSchema} instances in the {@link org.apache.syncope.core.persistence.api.entity.AnyTypeClass}
+     * associated to the given any.
      *
      * @param any any object
+     * @return virtual attribute values, either for local cache or external resources
      */
-    void retrieveVirAttrValues(Any<?, ?, ?> any);
-
-    void updateOnResourcesIfMappingMatches(
-            Any<?, ?, ?> any, String schemaKey, Iterable<? extends ExternalResource> resources,
-            IntMappingType mappingType, PropagationByResource propByRes);
+    Map<VirSchema, List<String>> getValues(Any<?, ?> any);
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValue.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValue.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValue.java
index 3288432..93b9c63 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValue.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/cache/VirAttrCacheValue.java
@@ -18,12 +18,10 @@
  */
 package org.apache.syncope.core.provisioning.api.cache;
 
-import java.util.Collections;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
+import java.util.List;
 
 /**
  * Cache entry value.
@@ -33,7 +31,7 @@ public class VirAttrCacheValue {
     /**
      * Virtual attribute values.
      */
-    private final Map<String, Set<String>> values;
+    private final List<String> values;
 
     /**
      * Entry creation date.
@@ -48,11 +46,17 @@ public class VirAttrCacheValue {
     public VirAttrCacheValue() {
         this.creationDate = new Date();
         this.lastAccessDate = new Date();
-        this.values = new HashMap<>();
+        this.values = new ArrayList<>();
     }
 
-    public void setResourceValues(final String resourceName, final Set<String> cached) {
-        this.values.put(resourceName, cached);
+    public void setValues(final Collection<Object> values) {
+        this.values.clear();
+
+        if (values != null) {
+            for (Object value : values) {
+                this.values.add(value.toString());
+            }
+        }
     }
 
     public Date getCreationDate() {
@@ -63,18 +67,8 @@ public class VirAttrCacheValue {
         creationDate = new Date(0);
     }
 
-    public Set<String> getValues(final String resourceName) {
-        return values.get(resourceName);
-    }
-
-    public Set<String> getValues() {
-        final Set<String> res = new HashSet<>();
-
-        for (Set<String> value : values.values()) {
-            res.addAll(value);
-        }
-
-        return Collections.unmodifiableSet(res);
+    public List<String> getValues() {
+        return values;
     }
 
     public Date getLastAccessDate() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
index ef9baf2..dd87d19 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationManager.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.provisioning.api.propagation;
 import java.util.Collection;
 import java.util.List;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -75,7 +74,7 @@ public interface PropagationManager {
      * @param changePwd whether password should be included for propagation attributes or not
      * @param enable whether any object should be enabled or not, may be null to leave unchanged
      * @param propByRes operation to be performed per resource
-     * @param vAttrs virtual attributes patches
+     * @param vAttrs virtual attributes to be set
      * @param noPropResourceNames external resource names not to be considered for propagation
      * @return list of propagation tasks
      */
@@ -85,7 +84,7 @@ public interface PropagationManager {
             boolean changePwd,
             Boolean enable,
             PropagationByResource propByRes,
-            Collection<AttrPatch> vAttrs,
+            Collection<AttrTO> vAttrs,
             Collection<String> noPropResourceNames);
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/sync/PushActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/sync/PushActions.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/sync/PushActions.java
index 8f34331..c06a05f 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/sync/PushActions.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/sync/PushActions.java
@@ -37,7 +37,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeAssign(
+    <A extends Any<?, ?>> A beforeAssign(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -50,7 +50,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeProvision(
+    <A extends Any<?, ?>> A beforeProvision(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -63,7 +63,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeUpdate(
+    <A extends Any<?, ?>> A beforeUpdate(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -76,7 +76,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeLink(
+    <A extends Any<?, ?>> A beforeLink(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -89,7 +89,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeUnlink(
+    <A extends Any<?, ?>> A beforeUnlink(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -102,7 +102,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeUnassign(
+    <A extends Any<?, ?>> A beforeUnassign(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -115,7 +115,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeDeprovision(
+    <A extends Any<?, ?>> A beforeDeprovision(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -128,7 +128,7 @@ public interface PushActions extends ProvisioningActions {
      * @return any.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> A beforeDelete(
+    <A extends Any<?, ?>> A beforeDelete(
             ProvisioningProfile<?, ?> profile,
             A any) throws JobExecutionException;
 
@@ -142,7 +142,7 @@ public interface PushActions extends ProvisioningActions {
      * @param error error being reported
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> void onError(
+    <A extends Any<?, ?>> void onError(
             ProvisioningProfile<?, ?> profile,
             A any,
             ProvisioningResult result,
@@ -157,7 +157,7 @@ public interface PushActions extends ProvisioningActions {
      * @param result operation result.
      * @throws JobExecutionException in case of generic failure
      */
-    <A extends Any<?, ?, ?>> void after(
+    <A extends Any<?, ?>> void after(
             ProvisioningProfile<?, ?> profile,
             A any,
             ProvisioningResult result) throws JobExecutionException;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
index a28f44e..6c2be32 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
@@ -21,8 +21,8 @@ package org.apache.syncope.core.provisioning.java;
 import java.io.File;
 import java.net.URI;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Future;
@@ -31,6 +31,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
+import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
 import org.apache.syncope.core.provisioning.api.ConnIdBundleManager;
@@ -168,12 +169,12 @@ public class ConnectorFacadeProxy implements Connector {
             final ObjectClass objectClass,
             final Set<Attribute> attrs,
             final OperationOptions options,
-            final Set<String> propagationAttempted) {
+            final Boolean[] propagationAttempted) {
 
         Uid result = null;
 
         if (activeConnInstance.getCapabilities().contains(ConnectorCapability.CREATE)) {
-            propagationAttempted.add("create");
+            propagationAttempted[0] = true;
 
             Future<Uid> future = asyncFacade.create(connector, objectClass, attrs, options);
             try {
@@ -203,12 +204,12 @@ public class ConnectorFacadeProxy implements Connector {
             final Uid uid,
             final Set<Attribute> attrs,
             final OperationOptions options,
-            final Set<String> propagationAttempted) {
+            final Boolean[] propagationAttempted) {
 
         Uid result = null;
 
         if (activeConnInstance.getCapabilities().contains(ConnectorCapability.UPDATE)) {
-            propagationAttempted.add("update");
+            propagationAttempted[0] = true;
 
             Future<Uid> future = asyncFacade.update(connector, objectClass, uid, attrs, options);
 
@@ -239,10 +240,10 @@ public class ConnectorFacadeProxy implements Connector {
             final ObjectClass objectClass,
             final Uid uid,
             final OperationOptions options,
-            final Set<String> propagationAttempted) {
+            final Boolean[] propagationAttempted) {
 
         if (activeConnInstance.getCapabilities().contains(ConnectorCapability.DELETE)) {
-            propagationAttempted.add("delete");
+            propagationAttempted[0] = true;
 
             Future<Uid> future = asyncFacade.delete(connector, objectClass, uid, options);
 
@@ -544,7 +545,8 @@ public class ConnectorFacadeProxy implements Connector {
             final ResultsHandler handler,
             final int pageSize,
             final String pagedResultsCookie,
-            final List<OrderByClause> orderBy) {
+            final List<OrderByClause> orderBy,
+            final Iterator<? extends MappingItem> mapItems) {
 
         OperationOptionsBuilder builder = new OperationOptionsBuilder().setPageSize(pageSize);
         if (pagedResultsCookie != null) {
@@ -558,6 +560,8 @@ public class ConnectorFacadeProxy implements Connector {
             }
         }, new ArrayList<SortKey>(orderBy.size())));
 
+        builder.setAttributesToGet(getOperationOptions(mapItems).getAttributesToGet());
+
         search(objectClass, filter, handler, builder.build());
     }
 
@@ -567,7 +571,7 @@ public class ConnectorFacadeProxy implements Connector {
     }
 
     @Override
-    public OperationOptions getOperationOptions(final Collection<? extends MappingItem> mapItems) {
+    public OperationOptions getOperationOptions(final Iterator<? extends MappingItem> mapItems) {
         // -------------------------------------
         // Ask just for mapped attributes
         // -------------------------------------
@@ -578,8 +582,11 @@ public class ConnectorFacadeProxy implements Connector {
         attrsToGet.add(Uid.NAME);
         attrsToGet.add(OperationalAttributes.ENABLE_NAME);
 
-        for (MappingItem item : mapItems) {
-            attrsToGet.add(item.getExtAttrName());
+        while (mapItems.hasNext()) {
+            MappingItem mapItem = mapItems.next();
+            if (mapItem.getPurpose() != MappingPurpose.NONE) {
+                attrsToGet.add(mapItem.getExtAttrName());
+            }
         }
 
         builder.setAttributesToGet(attrsToGet);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
index d332e23..ffecdb9 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
@@ -105,17 +105,6 @@ public class DefaultAnyObjectProvisioningManager implements AnyObjectProvisionin
 
         WorkflowResult<Long> updated = awfAdapter.update(anyObjectPatch);
 
-        // SYNCOPE-459: take care of user virtual attributes ...
-        PropagationByResource propByResVirAttr = virtAttrHandler.updateVirtual(
-                updated.getResult(),
-                AnyTypeKind.ANY_OBJECT,
-                anyObjectPatch.getVirAttrs());
-        if (updated.getPropByRes() == null) {
-            updated.setPropByRes(propByResVirAttr);
-        } else {
-            updated.getPropByRes().merge(propByResVirAttr);
-        }
-
         List<PropagationTask> tasks = propagationManager.getUpdateTasks(
                 AnyTypeKind.ANY_OBJECT,
                 updated.getResult(),
@@ -124,7 +113,6 @@ public class DefaultAnyObjectProvisioningManager implements AnyObjectProvisionin
                 updated.getPropByRes(),
                 anyObjectPatch.getVirAttrs(),
                 excludedResources);
-
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
index 0fff2a3..9e3d566 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
@@ -137,17 +137,6 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
 
         WorkflowResult<Long> updated = gwfAdapter.update(groupPatch);
 
-        // SYNCOPE-459: take care of user virtual attributes ...
-        PropagationByResource propByResVirAttr = virtAttrHandler.updateVirtual(
-                updated.getResult(),
-                AnyTypeKind.GROUP,
-                groupPatch.getVirAttrs());
-        if (updated.getPropByRes() == null) {
-            updated.setPropByRes(propByResVirAttr);
-        } else {
-            updated.getPropByRes().merge(propByResVirAttr);
-        }
-
         List<PropagationTask> tasks = propagationManager.getUpdateTasks(
                 AnyTypeKind.GROUP,
                 updated.getResult(),
@@ -156,7 +145,6 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
                 updated.getPropByRes(),
                 groupPatch.getVirAttrs(),
                 excludedResources);
-
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
index a59337c..5424486 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
@@ -119,28 +119,14 @@ public class DefaultUserProvisioningManager implements UserProvisioningManager {
     public Pair<Long, List<PropagationStatus>> update(final UserPatch userPatch) {
         WorkflowResult<Pair<UserPatch, Boolean>> updated = uwfAdapter.update(userPatch);
 
-        // SYNCOPE-459: take care of user virtual attributes ...
-        PropagationByResource propByResVirAttr = virtAttrHandler.updateVirtual(
-                updated.getResult().getKey().getKey(),
-                AnyTypeKind.USER,
-                userPatch.getVirAttrs());
-        if (updated.getPropByRes() == null) {
-            updated.setPropByRes(propByResVirAttr);
-        } else {
-            updated.getPropByRes().merge(propByResVirAttr);
-        }
-
         List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(updated);
-
-        PropagationReporter propagationReporter = ApplicationContextProvider.getBeanFactory().
-                getBean(PropagationReporter.class);
-        if (!tasks.isEmpty()) {
-            try {
-                taskExecutor.execute(tasks, propagationReporter);
-            } catch (PropagationException e) {
-                LOG.error("Error propagation primary resource", e);
-                propagationReporter.onPrimaryResourceFailure(tasks);
-            }
+        PropagationReporter propagationReporter =
+                ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
+        try {
+            taskExecutor.execute(tasks, propagationReporter);
+        } catch (PropagationException e) {
+            LOG.error("Error propagation primary resource", e);
+            propagationReporter.onPrimaryResourceFailure(tasks);
         }
 
         return new ImmutablePair<>(updated.getResult().getKey().getKey(), propagationReporter.getStatuses());
@@ -291,7 +277,6 @@ public class DefaultUserProvisioningManager implements UserProvisioningManager {
                 propByRes,
                 null,
                 null);
-
         PropagationReporter propReporter =
                 ApplicationContextProvider.getBeanFactory().getBean(PropagationReporter.class);
         try {
@@ -302,7 +287,6 @@ public class DefaultUserProvisioningManager implements UserProvisioningManager {
         }
 
         return propReporter.getStatuses();
-
     }
 
     @Override


[07/10] syncope git commit: [SYNCOPE-709] Refactoring completed

Posted by il...@apache.org.
[SYNCOPE-709] Refactoring completed


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

Branch: refs/heads/master
Commit: 9cd92305562916453bf2aee42bbc3b6d1b07e5cd
Parents: ef28d8e
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Oct 22 11:41:00 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Oct 22 11:41:00 2015 +0200

----------------------------------------------------------------------
 .../syncope/common/lib/AnyOperations.java       |  26 +-
 .../syncope/common/lib/patch/AnyPatch.java      |   5 +-
 .../org/apache/syncope/common/lib/to/AnyTO.java |   5 +-
 .../syncope/common/lib/to/ProvisionTO.java      |  18 +
 .../syncope/common/lib/to/VirSchemaTO.java      |  20 ++
 .../common/lib/types/PropagationByResource.java |  11 +
 .../syncope/core/logic/ResourceLogic.java       |  36 +-
 .../core/logic/report/StaticReportlet.java      |   4 +-
 .../core/logic/report/UserReportlet.java        |   8 +-
 .../apache/syncope/core/misc/DataFormat.java    | 117 ------
 .../apache/syncope/core/misc/FormatUtils.java   | 117 ++++++
 .../apache/syncope/core/misc/MappingUtils.java  | 172 +++------
 .../syncope/core/misc/jexl/JexlUtils.java       |  35 +-
 .../core/persistence/api/dao/AnyDAO.java        |   2 +-
 .../core/persistence/api/dao/AnySearchDAO.java  |  10 +-
 .../api/dao/ExternalResourceDAO.java            |   5 +-
 .../core/persistence/api/dao/VirAttrDAO.java    |  35 --
 .../core/persistence/api/dao/VirSchemaDAO.java  |   8 +-
 .../core/persistence/api/entity/Any.java        |  10 +-
 .../core/persistence/api/entity/AnyUtils.java   |   6 +-
 .../persistence/api/entity/AnyUtilsFactory.java |   2 +-
 .../core/persistence/api/entity/Attr.java       |   2 +-
 .../core/persistence/api/entity/DerAttr.java    |   2 +-
 .../api/entity/DynGroupMembership.java          |   2 +-
 .../persistence/api/entity/DynMembership.java   |   2 +-
 .../core/persistence/api/entity/Membership.java |   2 +-
 .../core/persistence/api/entity/PlainAttr.java  |   2 +-
 .../persistence/api/entity/Relationship.java    |   2 +-
 .../core/persistence/api/entity/VirAttr.java    |  30 --
 .../core/persistence/api/entity/VirSchema.java  |  13 +
 .../api/entity/anyobject/AVirAttr.java          |  25 --
 .../api/entity/anyobject/AnyObject.java         |   2 +-
 .../core/persistence/api/entity/conf/Conf.java  |   3 +-
 .../persistence/api/entity/group/GVirAttr.java  |  25 --
 .../persistence/api/entity/group/Group.java     |  14 +-
 .../api/entity/task/PropagationTask.java        |   4 +
 .../persistence/api/entity/user/UVirAttr.java   |  25 --
 .../core/persistence/api/entity/user/User.java  |  14 +-
 .../jpa/content/ContentLoaderHandler.java       |   4 +-
 .../jpa/content/XMLContentExporter.java         |  10 +-
 .../persistence/jpa/dao/AbstractAnyDAO.java     |  11 +-
 .../persistence/jpa/dao/JPAAnySearchDAO.java    |  12 +-
 .../core/persistence/jpa/dao/JPADerAttrDAO.java |   2 +-
 .../jpa/dao/JPAExternalResourceDAO.java         |  29 +-
 .../core/persistence/jpa/dao/JPAGroupDAO.java   |   2 +-
 .../persistence/jpa/dao/JPAPlainAttrDAO.java    |   2 +-
 .../jpa/dao/JPAPlainAttrValueDAO.java           |   7 +-
 .../core/persistence/jpa/dao/JPAVirAttrDAO.java |  86 -----
 .../persistence/jpa/dao/JPAVirSchemaDAO.java    |  35 +-
 .../persistence/jpa/entity/AbstractAny.java     |  17 +-
 .../persistence/jpa/entity/AbstractAttr.java    |   2 +-
 .../persistence/jpa/entity/AbstractDerAttr.java |   2 +-
 .../jpa/entity/AbstractDynMembership.java       |   2 +-
 .../jpa/entity/AbstractPlainAttr.java           |   2 +-
 .../jpa/entity/AbstractPlainAttrValue.java      |  18 +-
 .../persistence/jpa/entity/AbstractVirAttr.java |  71 ----
 .../jpa/entity/AnnotatedEntityListener.java     |   4 +-
 .../persistence/jpa/entity/JPAAnyUtils.java     |  52 +--
 .../jpa/entity/JPAAnyUtilsFactory.java          |   2 +-
 .../jpa/entity/JPAEntityFactory.java            |   8 -
 .../persistence/jpa/entity/JPAVirSchema.java    | 147 ++++++++
 .../anyobject/JPAAPlainAttrUniqueValue.java     |   2 +-
 .../entity/anyobject/JPAAPlainAttrValue.java    |   2 +-
 .../jpa/entity/anyobject/JPAAVirAttr.java       |  59 ---
 .../jpa/entity/anyobject/JPAAnyObject.java      |  24 +-
 .../entity/conf/JPACPlainAttrUniqueValue.java   |   2 +-
 .../jpa/entity/conf/JPACPlainAttrValue.java     |   2 +-
 .../persistence/jpa/entity/conf/JPAConf.java    |  21 --
 .../entity/group/JPAGPlainAttrUniqueValue.java  |   2 +-
 .../jpa/entity/group/JPAGPlainAttrValue.java    |   2 +-
 .../jpa/entity/group/JPAGVirAttr.java           |  59 ---
 .../persistence/jpa/entity/group/JPAGroup.java  |  24 +-
 .../jpa/entity/resource/JPAMapping.java         |  27 +-
 .../jpa/entity/resource/JPAProvision.java       |   1 -
 .../jpa/entity/task/JPAPropagationTask.java     |  12 +
 .../entity/user/JPAUPlainAttrUniqueValue.java   |   2 +-
 .../jpa/entity/user/JPAUPlainAttrValue.java     |   2 +-
 .../jpa/entity/user/JPAUVirAttr.java            |  59 ---
 .../persistence/jpa/entity/user/JPAUser.java    |  24 +-
 .../entity/ExternalResourceValidator.java       |  45 ++-
 .../jpa/validation/entity/PlainAttrCheck.java   |   2 +-
 .../validation/entity/PlainAttrValidator.java   |   2 +-
 .../resources/META-INF/spring-orm-oracle.xml    |  25 --
 .../resources/META-INF/spring-orm-sqlserver.xml |  25 --
 .../src/main/resources/META-INF/spring-orm.xml  |  25 --
 .../src/main/resources/indexes.xml              |   4 -
 .../persistence/jpa/inner/PlainAttrTest.java    |   1 -
 .../persistence/jpa/inner/ResourceTest.java     |  46 +++
 .../core/persistence/jpa/inner/TaskTest.java    |   1 +
 .../core/persistence/jpa/inner/VirAttrTest.java | 118 ------
 .../persistence/jpa/inner/VirSchemaTest.java    |  12 +-
 .../persistence/jpa/outer/ResourceTest.java     |  15 +-
 .../core/persistence/jpa/outer/TaskTest.java    |   1 +
 .../persistence/jpa/outer/VirSchemaTest.java    |  76 ++++
 .../test/resources/domains/MasterContent.xml    |  29 +-
 .../core/provisioning/api/Connector.java        |  27 +-
 .../core/provisioning/api/VirAttrHandler.java   |  52 +--
 .../api/cache/VirAttrCacheValue.java            |  36 +-
 .../api/propagation/PropagationManager.java     |   5 +-
 .../core/provisioning/api/sync/PushActions.java |  20 +-
 .../provisioning/java/ConnectorFacadeProxy.java |  29 +-
 .../DefaultAnyObjectProvisioningManager.java    |  12 -
 .../java/DefaultGroupProvisioningManager.java   |  12 -
 .../java/DefaultUserProvisioningManager.java    |  30 +-
 .../provisioning/java/VirAttrHandlerImpl.java   | 356 ++++---------------
 .../java/data/AbstractAnyDataBinder.java        | 138 +++----
 .../java/data/AnyObjectDataBinderImpl.java      |  11 +-
 .../java/data/GroupDataBinderImpl.java          |  11 +-
 .../java/data/ResourceDataBinderImpl.java       |  48 ++-
 .../java/data/SchemaDataBinderImpl.java         |  16 +-
 .../java/data/UserDataBinderImpl.java           |  11 +-
 .../core/provisioning/java/job/TaskJob.java     |   4 +-
 .../notification/NotificationManagerImpl.java   |  26 +-
 .../AbstractPropagationTaskExecutor.java        |  89 +++--
 .../propagation/PropagationManagerImpl.java     | 248 +++++++------
 .../java/sync/AbstractPushResultHandler.java    |  57 +--
 .../java/sync/AbstractSyncResultHandler.java    |  42 ++-
 .../java/sync/AbstractSyncopeResultHandler.java |   2 +-
 .../sync/AnyObjectPushResultHandlerImpl.java    |   4 +-
 .../sync/AnyObjectSyncResultHandlerImpl.java    |   2 +-
 .../java/sync/DefaultPushActions.java           |  16 +-
 .../java/sync/GroupPushResultHandlerImpl.java   |   4 +-
 .../java/sync/GroupSyncResultHandlerImpl.java   |   2 +-
 .../provisioning/java/sync/PushJobDelegate.java |   4 +-
 .../provisioning/java/sync/SyncJobDelegate.java |  31 +-
 .../core/provisioning/java/sync/SyncUtils.java  |  12 +-
 .../java/sync/UserPushResultHandlerImpl.java    |   6 +-
 .../java/sync/UserSyncResultHandlerImpl.java    |   2 +-
 .../rest/cxf/ThreadLocalCleanupListener.java    |   4 +-
 .../rest/cxf/service/AbstractAnyService.java    |   9 +-
 .../processor/AnyObjectUpdateProcessor.java     |  13 -
 .../camel/processor/GroupUpdateProcessor.java   |  13 -
 .../processor/UserUpdateInSyncProcessor.java    |   6 +-
 .../camel/processor/UserUpdateProcessor.java    |  27 +-
 fit/console-reference/pom.xml                   |  81 +----
 fit/core-reference/pom.xml                      |  16 +-
 .../syncope/fit/core/reference/GroupITCase.java |  26 +-
 .../core/reference/PropagationTaskITCase.java   |   8 -
 .../fit/core/reference/SyncTaskITCase.java      |  20 +-
 .../syncope/fit/core/reference/UserITCase.java  |  53 +--
 .../fit/core/reference/VirAttrITCase.java       | 329 +++++++++--------
 .../fit/core/reference/VirSchemaITCase.java     |  41 ++-
 142 files changed, 1609 insertions(+), 2503 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java b/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
index e1f9f88..0e5bec3 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
@@ -150,29 +150,8 @@ public final class AnyOperations {
         }
 
         // 5. virtual attributes
-        updatedAttrs = updated.getVirAttrMap();
-        originalAttrs = original.getVirAttrMap();
-
         result.getVirAttrs().clear();
-
-        if (!incremental) {
-            CollectionUtils.forAllDo(CollectionUtils.subtract(originalAttrs.keySet(), updatedAttrs.keySet()),
-                    new Closure<String>() {
-
-                        @Override
-                        public void execute(final String schema) {
-                            result.getVirAttrs().add(new AttrPatch.Builder().
-                                    operation(PatchOperation.DELETE).
-                                    attrTO(new AttrTO.Builder().schema(schema).build()).
-                                    build());
-                        }
-                    });
-        }
-
-        for (AttrTO attrTO : updatedAttrs.values()) {
-            AttrPatch patch = new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).attrTO(attrTO).build();
-            result.getVirAttrs().add(patch);
-        }
+        result.getVirAttrs().addAll(updated.getVirAttrs());
 
         // 6. resources
         result.getResources().clear();
@@ -188,7 +167,6 @@ public final class AnyOperations {
             result.getResources().add(
                     new StringPatchItem.Builder().operation(PatchOperation.ADD_REPLACE).value(resource).build());
         }
-
     }
 
     /**
@@ -450,7 +428,7 @@ public final class AnyOperations {
 
         // 4. virtual attributes
         result.getVirAttrs().clear();
-        result.getVirAttrs().addAll(AnyOperations.patch(to.getVirAttrMap(), patch.getVirAttrs()));
+        result.getVirAttrs().addAll(patch.getVirAttrs());
 
         // 5. resources
         for (StringPatchItem resourcePatch : patch.getResources()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
index e4b9e87..a6c4323 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
@@ -27,6 +27,7 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.to.AttrTO;
 
 @XmlType
 public abstract class AnyPatch extends AbstractBaseBean {
@@ -43,7 +44,7 @@ public abstract class AnyPatch extends AbstractBaseBean {
 
     private final Set<AttrPatch> derAttrs = new HashSet<>();
 
-    private final Set<AttrPatch> virAttrs = new HashSet<>();
+    private final Set<AttrTO> virAttrs = new HashSet<>();
 
     private final Set<StringPatchItem> resources = new HashSet<>();
 
@@ -88,7 +89,7 @@ public abstract class AnyPatch extends AbstractBaseBean {
     @XmlElementWrapper(name = "virAttrs")
     @XmlElement(name = "attribute")
     @JsonProperty("virAttrs")
-    public Set<AttrPatch> getVirAttrs() {
+    public Set<AttrTO> getVirAttrs() {
         return virAttrs;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index 56b1c44..7911d7d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -25,7 +25,6 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -53,9 +52,9 @@ public abstract class AnyTO extends ConnObjectTO {
 
     private final List<String> auxClasses = new ArrayList<>();
 
-    private final Set<AttrTO> derAttrs = new LinkedHashSet<>();
+    private final Set<AttrTO> derAttrs = new HashSet<>();
 
-    private final Set<AttrTO> virAttrs = new LinkedHashSet<>();
+    private final Set<AttrTO> virAttrs = new HashSet<>();
 
     private final Set<String> resources = new HashSet<>();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
index c4ff740..b25053d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ProvisionTO.java
@@ -18,8 +18,17 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 
+@XmlRootElement(name = "provision")
+@XmlType
 public class ProvisionTO extends AbstractBaseBean {
 
     private static final long serialVersionUID = 8298910216218007927L;
@@ -34,6 +43,8 @@ public class ProvisionTO extends AbstractBaseBean {
 
     private MappingTO mapping;
 
+    private List<String> virSchemas = new ArrayList<>();
+
     public long getKey() {
         return key;
     }
@@ -74,4 +85,11 @@ public class ProvisionTO extends AbstractBaseBean {
         this.mapping = mapping;
     }
 
+    @XmlElementWrapper(name = "virSchemas")
+    @XmlElement(name = "virSchema")
+    @JsonProperty("virSchemas")
+    public List<String> getVirSchemas() {
+        return virSchemas;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/common/lib/src/main/java/org/apache/syncope/common/lib/to/VirSchemaTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/VirSchemaTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/VirSchemaTO.java
index 1a9d3bd..8c3df1b 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/VirSchemaTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/VirSchemaTO.java
@@ -27,6 +27,10 @@ public class VirSchemaTO extends AbstractSchemaTO {
 
     private boolean readonly;
 
+    private long provision;
+
+    private String extAttrName;
+
     public boolean isReadonly() {
         return readonly;
     }
@@ -35,4 +39,20 @@ public class VirSchemaTO extends AbstractSchemaTO {
         this.readonly = readonly;
     }
 
+    public long getProvision() {
+        return provision;
+    }
+
+    public void setProvision(final long provision) {
+        this.provision = provision;
+    }
+
+    public String getExtAttrName() {
+        return extAttrName;
+    }
+
+    public void setExtAttrName(final String extAttrName) {
+        this.extAttrName = extAttrName;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationByResource.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationByResource.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationByResource.java
index bf35bb3..3e35fec 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationByResource.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/PropagationByResource.java
@@ -263,6 +263,17 @@ public class PropagationByResource implements Serializable {
         return result;
     }
 
+    public Map<String, ResourceOperation> asMap() {
+        Map<String, ResourceOperation> result = new HashMap<>();
+        for (ResourceOperation operation : ResourceOperation.values()) {
+            for (String resourceName : get(operation)) {
+                result.put(resourceName, operation);
+            }
+        }
+
+        return result;
+    }
+
     /**
      * Set resources for a given resource operation type.
      *

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index c3ce0c6..44a5aa8 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -20,9 +20,12 @@ package org.apache.syncope.core.logic;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IteratorUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.ArrayUtils;
@@ -51,9 +54,11 @@ import org.apache.syncope.core.misc.ConnObjectUtils;
 import org.apache.syncope.core.misc.MappingUtils;
 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.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 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.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -86,6 +91,9 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
     private GroupDAO groupDAO;
 
     @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
     private ResourceDataBinder binder;
 
     @Autowired
@@ -205,7 +213,8 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
     public ConnObjectTO readConnObject(final String key, final String anyTypeKey, final Long anyKey) {
         Triple<ExternalResource, AnyType, Provision> init = connObjectInit(key, anyTypeKey);
 
-        Any<?, ?, ?> any = init.getMiddle().getKind() == AnyTypeKind.USER
+        // 1. find any
+        Any<?, ?> any = init.getMiddle().getKind() == AnyTypeKind.USER
                 ? userDAO.find(anyKey)
                 : init.getMiddle().getKind() == AnyTypeKind.ANY_OBJECT
                         ? anyObjectDAO.find(anyKey)
@@ -213,6 +222,8 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
         if (any == null) {
             throw new NotFoundException(init.getMiddle() + " " + anyKey);
         }
+
+        // 2. build connObjectKeyItem
         MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(init.getRight());
         if (connObjectKeyItem == null) {
             throw new NotFoundException(
@@ -220,17 +231,28 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
         }
         String connObjectKeyValue = mappingUtils.getConnObjectKeyValue(any, init.getRight());
 
+        // 3. determine attributes to query
+        Set<MappingItem> linkinMappingItems = new HashSet<>();
+        for (VirSchema virSchema : virSchemaDAO.findByProvision(init.getRight())) {
+            linkinMappingItems.add(virSchema.asLinkingMappingItem());
+        }
+        Iterator<MappingItem> mapItems = IteratorUtils.chainedIterator(
+                init.getRight().getMapping().getItems().iterator(),
+                linkinMappingItems.iterator());
+
+        // 4. read from the underlying connector
         Connector connector = connFactory.getConnector(init.getLeft());
         ConnectorObject connectorObject = connector.getObject(
                 init.getRight().getObjectClass(),
                 new Uid(connObjectKeyValue),
-                connector.getOperationOptions(MappingUtils.getBothMappingItems(init.getRight())));
+                connector.getOperationOptions(mapItems));
         if (connectorObject == null) {
             throw new NotFoundException(
                     "Object " + connObjectKeyValue + " with class " + init.getRight().getObjectClass()
                     + " not found on resource " + key);
         }
 
+        // 5. build result
         Set<Attribute> attributes = connectorObject.getAttributes();
         if (AttributeUtil.find(Uid.NAME, attributes) == null) {
             attributes.add(connectorObject.getUid());
@@ -251,6 +273,14 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
 
         Connector connector = connFactory.getConnector(init.getLeft());
 
+        Set<MappingItem> linkinMappingItems = new HashSet<>();
+        for (VirSchema virSchema : virSchemaDAO.findByProvision(init.getRight())) {
+            linkinMappingItems.add(virSchema.asLinkingMappingItem());
+        }
+        Iterator<MappingItem> mapItems = IteratorUtils.chainedIterator(
+                init.getRight().getMapping().getItems().iterator(),
+                linkinMappingItems.iterator());
+
         final SearchResult[] searchResult = new SearchResult[1];
         final List<ConnObjectTO> connObjects = new ArrayList<>();
         connector.search(init.getRight().getObjectClass(), null, new SearchResultsHandler() {
@@ -265,7 +295,7 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
                 connObjects.add(connObjectUtils.getConnObjectTO(connectorObject));
                 return true;
             }
-        }, size, pagedResultsCookie, orderBy);
+        }, size, pagedResultsCookie, orderBy, mapItems);
 
         return ImmutablePair.of(searchResult[0], connObjects);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
index b7db39f..0e785b1 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/StaticReportlet.java
@@ -21,7 +21,7 @@ package org.apache.syncope.core.logic.report;
 import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.report.StaticReportletConf;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.springframework.util.StringUtils;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
@@ -101,7 +101,7 @@ public class StaticReportlet extends AbstractReportlet {
 
         if (this.conf.getDateField() != null) {
             handler.startElement("", "", "date", null);
-            String printed = DataFormat.format(this.conf.getDateField());
+            String printed = FormatUtils.format(this.conf.getDateField());
             handler.characters(printed.toCharArray(), 0, printed.length());
             handler.endElement("", "", "date");
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
index c11ca05..3eb96b3 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
@@ -38,7 +38,7 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
@@ -231,21 +231,21 @@ public class UserReportlet extends AbstractReportlet {
                         type = ReportXMLConst.XSD_DATETIME;
                         value = user.getCreationDate() == null
                                 ? ""
-                                : DataFormat.format(user.getCreationDate());
+                                : FormatUtils.format(user.getCreationDate());
                         break;
 
                     case lastLoginDate:
                         type = ReportXMLConst.XSD_DATETIME;
                         value = user.getLastLoginDate() == null
                                 ? ""
-                                : DataFormat.format(user.getLastLoginDate());
+                                : FormatUtils.format(user.getLastLoginDate());
                         break;
 
                     case changePwdDate:
                         type = ReportXMLConst.XSD_DATETIME;
                         value = user.getChangePwdDate() == null
                                 ? ""
-                                : DataFormat.format(user.getChangePwdDate());
+                                : FormatUtils.format(user.getChangePwdDate());
                         break;
 
                     case passwordHistorySize:

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/misc/src/main/java/org/apache/syncope/core/misc/DataFormat.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/DataFormat.java b/core/misc/src/main/java/org/apache/syncope/core/misc/DataFormat.java
deleted file mode 100644
index fded378..0000000
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/DataFormat.java
+++ /dev/null
@@ -1,117 +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.misc;
-
-import java.text.DecimalFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import org.apache.commons.lang3.time.DateUtils;
-import org.apache.syncope.common.lib.SyncopeConstants;
-
-/**
- * Utility class for parsing / formatting date and numbers.
- */
-public final class DataFormat {
-
-    private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
-
-        @Override
-        protected SimpleDateFormat initialValue() {
-            SimpleDateFormat sdf = new SimpleDateFormat();
-            sdf.applyPattern(SyncopeConstants.DEFAULT_DATE_PATTERN);
-            return sdf;
-        }
-    };
-
-    private static final ThreadLocal<DecimalFormat> DECIMAL_FORMAT = new ThreadLocal<DecimalFormat>() {
-
-        @Override
-        protected DecimalFormat initialValue() {
-            return new DecimalFormat();
-        }
-    };
-
-    public static String format(final Date date) {
-        return format(date, true);
-    }
-
-    public static String format(final Date date, final boolean lenient) {
-        return format(date, lenient, null);
-    }
-
-    public static String format(final Date date, final boolean lenient, final String conversionPattern) {
-        SimpleDateFormat sdf = DATE_FORMAT.get();
-        if (conversionPattern != null) {
-            sdf.applyPattern(conversionPattern);
-        }
-        sdf.setLenient(lenient);
-        return sdf.format(date);
-    }
-
-    public static String format(final long number) {
-        return format(number, null);
-    }
-
-    public static String format(final long number, final String conversionPattern) {
-        DecimalFormat df = DECIMAL_FORMAT.get();
-        if (conversionPattern != null) {
-            df.applyPattern(conversionPattern);
-        }
-        return df.format(number);
-    }
-
-    public static String format(final double number) {
-        return format(number, null);
-    }
-
-    public static String format(final double number, final String conversionPattern) {
-        DecimalFormat df = DECIMAL_FORMAT.get();
-        if (conversionPattern != null) {
-            df.applyPattern(conversionPattern);
-        }
-        return df.format(number);
-    }
-
-    public static Date parseDate(final String source) throws ParseException {
-        return DateUtils.parseDate(source, SyncopeConstants.DATE_PATTERNS);
-    }
-
-    public static Date parseDate(final String source, final String conversionPattern) throws ParseException {
-        SimpleDateFormat sdf = DATE_FORMAT.get();
-        sdf.applyPattern(conversionPattern);
-        sdf.setLenient(false);
-        return sdf.parse(source);
-    }
-
-    public static Number parseNumber(final String source, final String conversionPattern) throws ParseException {
-        DecimalFormat df = DECIMAL_FORMAT.get();
-        df.applyPattern(conversionPattern);
-        return df.parse(source);
-    }
-
-    public static void clear() {
-        DATE_FORMAT.remove();
-        DECIMAL_FORMAT.remove();
-    }
-
-    private DataFormat() {
-        // private empty constructor
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/misc/src/main/java/org/apache/syncope/core/misc/FormatUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/FormatUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/FormatUtils.java
new file mode 100644
index 0000000..0b06906
--- /dev/null
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/FormatUtils.java
@@ -0,0 +1,117 @@
+/*
+ * 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.misc;
+
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateUtils;
+import org.apache.syncope.common.lib.SyncopeConstants;
+
+/**
+ * Utility class for parsing / formatting date and numbers.
+ */
+public final class FormatUtils {
+
+    private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+        @Override
+        protected SimpleDateFormat initialValue() {
+            SimpleDateFormat sdf = new SimpleDateFormat();
+            sdf.applyPattern(SyncopeConstants.DEFAULT_DATE_PATTERN);
+            return sdf;
+        }
+    };
+
+    private static final ThreadLocal<DecimalFormat> DECIMAL_FORMAT = new ThreadLocal<DecimalFormat>() {
+
+        @Override
+        protected DecimalFormat initialValue() {
+            return new DecimalFormat();
+        }
+    };
+
+    public static String format(final Date date) {
+        return format(date, true);
+    }
+
+    public static String format(final Date date, final boolean lenient) {
+        return format(date, lenient, null);
+    }
+
+    public static String format(final Date date, final boolean lenient, final String conversionPattern) {
+        SimpleDateFormat sdf = DATE_FORMAT.get();
+        if (conversionPattern != null) {
+            sdf.applyPattern(conversionPattern);
+        }
+        sdf.setLenient(lenient);
+        return sdf.format(date);
+    }
+
+    public static String format(final long number) {
+        return format(number, null);
+    }
+
+    public static String format(final long number, final String conversionPattern) {
+        DecimalFormat df = DECIMAL_FORMAT.get();
+        if (conversionPattern != null) {
+            df.applyPattern(conversionPattern);
+        }
+        return df.format(number);
+    }
+
+    public static String format(final double number) {
+        return format(number, null);
+    }
+
+    public static String format(final double number, final String conversionPattern) {
+        DecimalFormat df = DECIMAL_FORMAT.get();
+        if (conversionPattern != null) {
+            df.applyPattern(conversionPattern);
+        }
+        return df.format(number);
+    }
+
+    public static Date parseDate(final String source) throws ParseException {
+        return DateUtils.parseDate(source, SyncopeConstants.DATE_PATTERNS);
+    }
+
+    public static Date parseDate(final String source, final String conversionPattern) throws ParseException {
+        SimpleDateFormat sdf = DATE_FORMAT.get();
+        sdf.applyPattern(conversionPattern);
+        sdf.setLenient(false);
+        return sdf.parse(source);
+    }
+
+    public static Number parseNumber(final String source, final String conversionPattern) throws ParseException {
+        DecimalFormat df = DECIMAL_FORMAT.get();
+        df.applyPattern(conversionPattern);
+        return df.parse(source);
+    }
+
+    public static void clear() {
+        DATE_FORMAT.remove();
+        DECIMAL_FORMAT.remove();
+    }
+
+    private FormatUtils() {
+        // private empty constructor
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
index 085f07d..54a4428 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
@@ -19,15 +19,11 @@
 package org.apache.syncope.core.misc;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
-import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.jexl2.JexlContext;
 import org.apache.commons.jexl2.MapContext;
 import org.apache.commons.lang3.ClassUtils;
@@ -35,7 +31,6 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
@@ -53,7 +48,6 @@ 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.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
@@ -70,6 +64,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 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.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
@@ -122,42 +117,6 @@ public class MappingUtils {
     @Autowired
     private AnyUtilsFactory anyUtilsFactory;
 
-    public static <T extends MappingItem> Collection<T> getMatchingMappingItems(
-            final Collection<T> items, final IntMappingType type) {
-
-        return CollectionUtils.select(items, new Predicate<T>() {
-
-            @Override
-            public boolean evaluate(final T item) {
-                return item.getIntMappingType() == type;
-            }
-        });
-    }
-
-    public static <T extends MappingItem> Collection<T> getMatchingMappingItems(
-            final Collection<T> items, final String intAttrName, final IntMappingType type) {
-
-        return CollectionUtils.select(items, new Predicate<T>() {
-
-            @Override
-            public boolean evaluate(final T item) {
-                return item.getIntMappingType() == type && intAttrName.equals(item.getIntAttrName());
-            }
-        });
-    }
-
-    public static <T extends MappingItem> Collection<T> getMatchingMappingItems(
-            final Collection<T> items, final String intAttrName) {
-
-        return CollectionUtils.select(items, new Predicate<T>() {
-
-            @Override
-            public boolean evaluate(final T item) {
-                return intAttrName.equals(item.getIntAttrName());
-            }
-        });
-    }
-
     public static MappingItem getConnObjectKeyItem(final Provision provision) {
         Mapping mapping = null;
         if (provision != null) {
@@ -241,7 +200,7 @@ public class MappingUtils {
      * @param connObjectKey connector object key
      * @return the value to be propagated as __NAME__
      */
-    public static Name evaluateNAME(final Any<?, ?, ?> any, final Provision provision, final String connObjectKey) {
+    public static Name evaluateNAME(final Any<?, ?> any, final Provision provision, final String connObjectKey) {
         if (StringUtils.isBlank(connObjectKey)) {
             // LOG error but avoid to throw exception: leave it to the external resource
             LOG.error("Missing ConnObjectKey for '{}': ", provision.getResource());
@@ -302,17 +261,15 @@ public class MappingUtils {
      * @param any given any object
      * @param password clear-text password
      * @param changePwd whether password should be included for propagation attributes or not
-     * @param vAttrs virtual attributes to be managed
      * @param enable whether any object must be enabled or not
      * @param provision provision information
      * @return connObjectLink + prepared attributes
      */
     @Transactional(readOnly = true)
     public Pair<String, Set<Attribute>> prepareAttrs(
-            final Any<?, ?, ?> any,
+            final Any<?, ?> any,
             final String password,
             final boolean changePwd,
-            final Map<String, AttrPatch> vAttrs,
             final Boolean enable,
             final Provision provision) {
 
@@ -322,19 +279,11 @@ public class MappingUtils {
         Set<Attribute> attributes = new HashSet<>();
         String connObjectKey = null;
 
-        for (MappingItem mapping : getMappingItems(provision, MappingPurpose.PROPAGATION)) {
-            LOG.debug("Processing schema {}", mapping.getIntAttrName());
+        for (MappingItem mappingItem : getMappingItems(provision, MappingPurpose.PROPAGATION)) {
+            LOG.debug("Processing schema {}", mappingItem.getIntAttrName());
 
             try {
-                if (mapping.getIntMappingType() == IntMappingType.UserVirtualSchema
-                        || mapping.getIntMappingType() == IntMappingType.GroupVirtualSchema
-                        || mapping.getIntMappingType() == IntMappingType.AnyObjectVirtualSchema) {
-
-                    LOG.debug("Expire entry cache {}-{}", any.getKey(), mapping.getIntAttrName());
-                    virAttrCache.expire(any.getType().getKey(), any.getKey(), mapping.getIntAttrName());
-                }
-
-                Pair<String, Attribute> preparedAttr = prepareAttr(provision, mapping, any, password, vAttrs);
+                Pair<String, Attribute> preparedAttr = prepareAttr(provision, mappingItem, any, password);
 
                 if (preparedAttr != null && preparedAttr.getKey() != null) {
                     connObjectKey = preparedAttr.getKey();
@@ -355,7 +304,7 @@ public class MappingUtils {
                     }
                 }
             } catch (Exception e) {
-                LOG.debug("Attribute '{}' processing failed", mapping.getIntAttrName(), e);
+                LOG.debug("Attribute '{}' processing failed", mappingItem.getIntAttrName(), e);
             }
         }
 
@@ -387,15 +336,12 @@ public class MappingUtils {
      * @param mapItem mapping item for the given attribute
      * @param any any object
      * @param password clear-text password
-     * @param vAttrs virtual attributes to be managed
      * @return connObjectLink + prepared attribute
      */
     private Pair<String, Attribute> prepareAttr(
-            final Provision provision, final MappingItem mapItem,
-            final Any<?, ?, ?> any, final String password,
-            final Map<String, AttrPatch> vAttrs) {
+            final Provision provision, final MappingItem mapItem, final Any<?, ?> any, final String password) {
 
-        List<Any<?, ?, ?>> anys = new ArrayList<>();
+        List<Any<?, ?>> anys = new ArrayList<>();
 
         switch (mapItem.getIntMappingType().getAnyTypeKind()) {
             case USER:
@@ -407,7 +353,6 @@ public class MappingUtils {
             case GROUP:
                 if (any instanceof User) {
                     for (Group group : userDAO.findAllGroups((User) any)) {
-                        virAttrHandler.retrieveVirAttrValues(group);
                         anys.add(group);
                     }
                 } else if (any instanceof Group) {
@@ -424,8 +369,6 @@ public class MappingUtils {
             default:
         }
 
-        List<PlainAttrValue> values = getIntValues(provision, mapItem, anys, vAttrs);
-
         Schema schema = null;
         boolean readOnlyVirSchema = false;
         AttrSchemaType schemaType;
@@ -453,6 +396,8 @@ public class MappingUtils {
 
         String extAttrName = mapItem.getExtAttrName();
 
+        List<PlainAttrValue> values = getIntValues(provision, mapItem, anys);
+
         LOG.debug("Define mapping for: "
                 + "\n* ExtAttrName " + extAttrName
                 + "\n* is connObjectKey " + mapItem.isConnObjectKey()
@@ -501,8 +446,7 @@ public class MappingUtils {
                     result = null;
                 } else {
                     result = new ImmutablePair<>(
-                            null,
-                            AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
+                            null, AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
                 }
             } else {
                 if ((schema != null && schema.isMultivalue())
@@ -510,8 +454,7 @@ public class MappingUtils {
                         != mapItem.getIntMappingType().getAnyTypeKind()) {
 
                     result = new ImmutablePair<>(
-                            null,
-                            AttributeBuilder.build(extAttrName, objValues));
+                            null, AttributeBuilder.build(extAttrName, objValues));
                 } else {
                     result = new ImmutablePair<>(
                             null, objValues.isEmpty()
@@ -524,9 +467,8 @@ public class MappingUtils {
         return result;
     }
 
-    private String getGroupOwnerValue(final Provision provision, final Any<?, ?, ?> any) {
-        Pair<String, Attribute> preparedAttr = prepareAttr(
-                provision, getConnObjectKeyItem(provision), any, null, Collections.<String, AttrPatch>emptyMap());
+    private String getGroupOwnerValue(final Provision provision, final Any<?, ?> any) {
+        Pair<String, Attribute> preparedAttr = prepareAttr(provision, getConnObjectKeyItem(provision), any, null);
         String connObjectKey = preparedAttr.getKey();
 
         return evaluateNAME(any, provision, connObjectKey).getNameValue();
@@ -538,12 +480,11 @@ public class MappingUtils {
      * @param provision provision information
      * @param mappingItem mapping item
      * @param anys any objects
-     * @param vAttrs virtual attributes to be managed
      * @return attribute values.
      */
     @Transactional(readOnly = true)
     public List<PlainAttrValue> getIntValues(final Provision provision,
-            final MappingItem mappingItem, final List<Any<?, ?, ?>> anys, final Map<String, AttrPatch> vAttrs) {
+            final MappingItem mappingItem, final List<Any<?, ?>> anys) {
 
         LOG.debug("Get attributes for '{}' and mapping type '{}'", anys, mappingItem.getIntMappingType());
 
@@ -554,7 +495,7 @@ public class MappingUtils {
             case UserPlainSchema:
             case GroupPlainSchema:
             case AnyObjectPlainSchema:
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     PlainAttr<?> attr = any.getPlainAttr(mappingItem.getIntAttrName());
                     if (attr != null) {
                         if (attr.getUniqueValue() != null) {
@@ -579,46 +520,10 @@ public class MappingUtils {
 
                 break;
 
-            case UserVirtualSchema:
-            case GroupVirtualSchema:
-            case AnyObjectVirtualSchema:
-                // virtual attributes don't get transformed
-                transform = false;
-
-                for (Any<?, ?, ?> any : anys) {
-                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                    VirAttr<?> attr = any.getVirAttr(mappingItem.getIntAttrName());
-                    if (attr != null) {
-                        if (vAttrs != null) {
-                            if (vAttrs.containsKey(mappingItem.getIntAttrName())) {
-                                attr.getValues().clear();
-                                attr.getValues().addAll(
-                                        vAttrs.get(mappingItem.getIntAttrName()).getAttrTO().getValues());
-                            } else {
-                                throw new IllegalArgumentException("Don't need to update virtual attribute '"
-                                        + mappingItem.getIntAttrName() + "'");
-                            }
-                        }
-                        for (String value : attr.getValues()) {
-                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                            attrValue.setStringValue(value);
-                            values.add(attrValue);
-                        }
-                    }
-
-                    LOG.debug("Retrieved {} virtual attribute {}"
-                            + "\n* IntAttrName {}"
-                            + "\n* IntMappingType {}"
-                            + "\n* Attribute values {}",
-                            any.getClass().getSimpleName(),
-                            attr, mappingItem.getIntAttrName(), mappingItem.getIntMappingType(), values);
-                }
-                break;
-
             case UserDerivedSchema:
             case GroupDerivedSchema:
             case AnyObjectDerivedSchema:
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
                     DerAttr<?> attr = any.getDerAttr(mappingItem.getIntAttrName());
                     if (attr != null) {
@@ -635,10 +540,39 @@ public class MappingUtils {
                 }
                 break;
 
+            case UserVirtualSchema:
+            case GroupVirtualSchema:
+            case AnyObjectVirtualSchema:
+                // virtual attributes don't get transformed
+                transform = false;
+
+                VirSchema virSchema = virSchemaDAO.find(mappingItem.getIntAttrName());
+                if (virSchema != null) {
+                    for (Any<?, ?> any : anys) {
+                        LOG.debug("Expire entry cache {}-{}", any.getKey(), mappingItem.getIntAttrName());
+                        virAttrCache.expire(any.getType().getKey(), any.getKey(), mappingItem.getIntAttrName());
+
+                        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+                        for (String value : virAttrHandler.getValues(any, virSchema)) {
+                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                            attrValue.setStringValue(value);
+                            values.add(attrValue);
+                        }
+
+                        LOG.debug("Retrieved values for {}"
+                                + "\n* IntAttrName {}"
+                                + "\n* IntMappingType {}"
+                                + "\n* Attribute values {}",
+                                virSchema.getKey(), mappingItem.getIntAttrName(), mappingItem.getIntMappingType(),
+                                values);
+                    }
+                }
+                break;
+
             case UserKey:
             case GroupKey:
             case AnyObjectKey:
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
                     PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
                     attrValue.setStringValue(any.getKey().toString());
@@ -647,7 +581,7 @@ public class MappingUtils {
                 break;
 
             case Username:
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     if (any instanceof User) {
                         UPlainAttrValue attrValue = entityFactory.newEntity(UPlainAttrValue.class);
                         attrValue.setStringValue(((User) any).getUsername());
@@ -657,7 +591,7 @@ public class MappingUtils {
                 break;
 
             case GroupName:
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     if (any instanceof Group) {
                         GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
                         attrValue.setStringValue(((Group) any).getName());
@@ -674,7 +608,7 @@ public class MappingUtils {
                         ? null
                         : provision.getMapping();
 
-                for (Any<?, ?, ?> any : anys) {
+                for (Any<?, ?> any : anys) {
                     if (any instanceof Group) {
                         Group group = (Group) any;
                         String groupOwnerValue = null;
@@ -720,9 +654,9 @@ public class MappingUtils {
      * @return connObjectKey internal value
      */
     @Transactional(readOnly = true)
-    public String getConnObjectKeyValue(final Any<?, ?, ?> any, final Provision provision) {
+    public String getConnObjectKeyValue(final Any<?, ?> any, final Provision provision) {
         List<PlainAttrValue> values = getIntValues(provision, provision.getMapping().getConnObjectKeyItem(),
-                Collections.<Any<?, ?, ?>>singletonList(any), null);
+                Collections.<Any<?, ?>>singletonList(any));
         return values == null || values.isEmpty()
                 ? null
                 : values.get(0).getValueAsString();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
index 443bbae..3afe6e5 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
@@ -35,8 +35,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-import org.apache.syncope.core.misc.DataFormat;
+import org.apache.syncope.core.misc.FormatUtils;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.slf4j.Logger;
@@ -126,7 +125,7 @@ public final class JexlUtils {
                         context.set(fieldName, fieldValue == null
                                 ? StringUtils.EMPTY
                                 : (type.equals(Date.class)
-                                        ? DataFormat.format((Date) fieldValue, false)
+                                        ? FormatUtils.format((Date) fieldValue, false)
                                         : fieldValue));
 
                         LOG.debug("Add field {} with value {}", fieldName, fieldValue);
@@ -140,7 +139,7 @@ public final class JexlUtils {
         }
 
         if (object instanceof Any) {
-            Any<?, ?, ?> any = (Any<?, ?, ?>) object;
+            Any<?, ?> any = (Any<?, ?>) object;
             if (any.getRealm() != null) {
                 context.set("realm", any.getRealm().getName());
             }
@@ -195,40 +194,16 @@ public final class JexlUtils {
         return context;
     }
 
-    public static JexlContext addVirAttrsToContext(final Collection<? extends VirAttr> virAttrs,
-            final JexlContext jexlContext) {
-
-        JexlContext context = jexlContext == null
-                ? new MapContext()
-                : jexlContext;
-
-        for (VirAttr<?> virAttr : virAttrs) {
-            if (virAttr.getSchema() != null) {
-                List<String> attrValues = virAttr.getValues();
-                String expressionValue = attrValues.isEmpty()
-                        ? StringUtils.EMPTY
-                        : attrValues.get(0);
-
-                LOG.debug("Add virtual attribute {} with value {}", virAttr.getSchema().getKey(), expressionValue);
-
-                context.set(virAttr.getSchema().getKey(), expressionValue);
-            }
-        }
-
-        return context;
-    }
-
-    public static boolean evaluateMandatoryCondition(final String mandatoryCondition, final Any<?, ?, ?> any) {
+    public static boolean evaluateMandatoryCondition(final String mandatoryCondition, final Any<?, ?> any) {
         JexlContext jexlContext = new MapContext();
         addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
         addDerAttrsToContext(any.getDerAttrs(), any.getPlainAttrs(), jexlContext);
-        addVirAttrsToContext(any.getVirAttrs(), jexlContext);
 
         return Boolean.parseBoolean(evaluate(mandatoryCondition, jexlContext));
     }
 
     public static String evaluate(final String expression,
-            final Any<?, ?, ?> any, final Collection<? extends PlainAttr<?>> attributes) {
+            final Any<?, ?> any, final Collection<? extends PlainAttr<?>> attributes) {
 
         JexlContext jexlContext = new MapContext();
         JexlUtils.addPlainAttrsToContext(attributes, jexlContext);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
----------------------------------------------------------------------
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 86c97e3..bfda35f 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
@@ -25,7 +25,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 
-public interface AnyDAO<A extends Any<?, ?, ?>> extends DAO<A, Long> {
+public interface AnyDAO<A extends Any<?, ?>> extends DAO<A, Long> {
 
     A authFind(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
index f53dff6..00471e0 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnySearchDAO.java
@@ -25,7 +25,7 @@ import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.Any;
 
-public interface AnySearchDAO extends DAO<Any<?, ?, ?>, Long> {
+public interface AnySearchDAO extends DAO<Any<?, ?>, Long> {
 
     /**
      * @param adminRealms realms for which the caller owns the proper entitlement(s)
@@ -42,7 +42,7 @@ public interface AnySearchDAO extends DAO<Any<?, ?, ?>, Long> {
      * @param <T> any
      * @return the list of any objects matching the given search condition
      */
-    <T extends Any<?, ?, ?>> List<T> search(
+    <T extends Any<?, ?>> List<T> search(
             Set<String> adminRealms, SearchCond searchCondition, AnyTypeKind kind);
 
     /**
@@ -53,7 +53,7 @@ public interface AnySearchDAO extends DAO<Any<?, ?, ?>, Long> {
      * @param <T> any
      * @return the list of any objects matching the given search condition
      */
-    <T extends Any<?, ?, ?>> List<T> search(
+    <T extends Any<?, ?>> List<T> search(
             Set<String> adminRealms, SearchCond searchCondition, List<OrderByClause> orderBy, AnyTypeKind kind);
 
     /**
@@ -66,7 +66,7 @@ public interface AnySearchDAO extends DAO<Any<?, ?, ?>, Long> {
      * @param <T> any
      * @return the list of any objects matching the given search condition (in the given page)
      */
-    <T extends Any<?, ?, ?>> List<T> search(
+    <T extends Any<?, ?>> List<T> search(
             Set<String> adminRealms, SearchCond searchCondition, int page, int itemsPerPage,
             List<OrderByClause> orderBy, AnyTypeKind kind);
 
@@ -79,5 +79,5 @@ public interface AnySearchDAO extends DAO<Any<?, ?, ?>, Long> {
      * @param <T> any
      * @return true if any matches searchCondition
      */
-    <T extends Any<?, ?, ?>> boolean matches(T any, SearchCond searchCondition, AnyTypeKind kind);
+    <T extends Any<?, ?>> boolean matches(T any, SearchCond searchCondition, AnyTypeKind kind);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
index a72937c..aeabe23 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
@@ -21,13 +21,16 @@ package org.apache.syncope.core.persistence.api.dao;
 import java.util.List;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.PolicyType;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.Policy;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 
 public interface ExternalResourceDAO extends DAO<ExternalResource, String> {
 
     ExternalResource find(String key);
 
+    Provision findProvision(Long key);
+
     List<ExternalResource> findByPolicy(Policy policy);
 
     List<ExternalResource> findWithoutPolicy(PolicyType type);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirAttrDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirAttrDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirAttrDAO.java
deleted file mode 100644
index b62cb87..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirAttrDAO.java
+++ /dev/null
@@ -1,35 +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.persistence.api.dao;
-
-import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-
-public interface VirAttrDAO extends DAO<VirAttr<?>, Long> {
-
-    <T extends VirAttr<?>> T find(Long key, Class<T> reference);
-
-    <T extends VirAttr<?>> List<T> findAll(Class<T> reference);
-
-    <T extends VirAttr<?>> T save(T virtualAttribute);
-
-    <T extends VirAttr<?>> void delete(Long key, Class<T> reference);
-
-    <T extends VirAttr<?>> void delete(T virAttr);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirSchemaDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirSchemaDAO.java
index 2bcd81c..9479428 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirSchemaDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/VirSchemaDAO.java
@@ -18,8 +18,12 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Attr;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 
-public interface VirSchemaDAO extends SchemaDAO<VirSchema, VirAttr<?>> {
+public interface VirSchemaDAO extends SchemaDAO<VirSchema, Attr<VirSchema, ?>> {
+
+    List<VirSchema> findByProvision(Provision provision);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
index 0384db7..f56485e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
@@ -22,7 +22,7 @@ import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import java.util.List;
 import java.util.Set;
 
-public interface Any<P extends PlainAttr<?>, D extends DerAttr<?>, V extends VirAttr<?>> extends AnnotatedEntity<Long> {
+public interface Any<P extends PlainAttr<?>, D extends DerAttr<?>> extends AnnotatedEntity<Long> {
 
     AnyType getType();
 
@@ -56,14 +56,6 @@ public interface Any<P extends PlainAttr<?>, D extends DerAttr<?>, V extends Vir
 
     List<? extends D> getDerAttrs();
 
-    boolean add(V virAttr);
-
-    boolean remove(V virAttr);
-
-    V getVirAttr(String virSchemaName);
-
-    List<? extends V> getVirAttrs();
-
     boolean add(ExternalResource resource);
 
     boolean remove(ExternalResource resource);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
index 8c64086..702e7a6 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
@@ -26,7 +26,7 @@ public interface AnyUtils {
 
     AnyTypeKind getAnyTypeKind();
 
-    <T extends Any<?, ?, ?>> Class<T> anyClass();
+    <T extends Any<?, ?>> Class<T> anyClass();
 
     <T extends PlainAttr<?>> Class<T> plainAttrClass();
 
@@ -44,10 +44,6 @@ public interface AnyUtils {
 
     <T extends DerAttr<?>> T newDerAttr();
 
-    <T extends VirAttr<?>> Class<T> virAttrClass();
-
-    <T extends VirAttr<?>> T newVirAttr();
-
     IntMappingType plainIntMappingType();
 
     IntMappingType derIntMappingType();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtilsFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtilsFactory.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtilsFactory.java
index 2e2a49e..d64e7e1 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtilsFactory.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtilsFactory.java
@@ -26,5 +26,5 @@ public interface AnyUtilsFactory {
 
     AnyUtils getInstance(String anyTypeKind);
 
-    AnyUtils getInstance(Any<?, ?, ?> any);
+    AnyUtils getInstance(Any<?, ?> any);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Attr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Attr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Attr.java
index 2be01e9..500b835 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Attr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Attr.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-public interface Attr<S extends Schema, O extends Any<?, ?, ?>> extends Entity<Long> {
+public interface Attr<S extends Schema, O extends Any<?, ?>> extends Entity<Long> {
 
     O getOwner();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DerAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DerAttr.java
index 9eb3b7a..ff15a4a 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DerAttr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DerAttr.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.Collection;
 
-public interface DerAttr<O extends Any<?, ?, ?>> extends Attr<DerSchema, O> {
+public interface DerAttr<O extends Any<?, ?>> extends Attr<DerSchema, O> {
 
     String getValue(Collection<? extends PlainAttr<?>> attrs);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynGroupMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynGroupMembership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynGroupMembership.java
index b01fe70..ebb7cf8 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynGroupMembership.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynGroupMembership.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 
-public interface DynGroupMembership<A extends Any<?, ?, ?>> extends DynMembership<A> {
+public interface DynGroupMembership<A extends Any<?, ?>> extends DynMembership<A> {
 
     Group getGroup();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
index ba0a62f..24c6309 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/DynMembership.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.List;
 
-public interface DynMembership<A extends Any<?, ?, ?>> extends Entity<Long> {
+public interface DynMembership<A extends Any<?, ?>> extends Entity<Long> {
 
     String getFIQLCond();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
index 55ac640..9d1466c 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Membership.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 
-public interface Membership<L extends Any<?, ?, ?>> extends Relationship<L, Group> {
+public interface Membership<L extends Any<?, ?>> extends Relationship<L, Group> {
 
     @Override
     MembershipType getType();

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttr.java
index b149851..8d8a7c1 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/PlainAttr.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.List;
 
-public interface PlainAttr<O extends Any<?, ?, ?>> extends Attr<PlainSchema, O> {
+public interface PlainAttr<O extends Any<?, ?>> extends Attr<PlainSchema, O> {
 
     void add(String value, AnyUtils anyUtils);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
index 0549714..b87563e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Relationship.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
-public interface Relationship<L extends Any<?, ?, ?>, R extends Any<?, ?, ?>> extends Entity<Long> {
+public interface Relationship<L extends Any<?, ?>, R extends Any<?, ?>> extends Entity<Long> {
 
     RelationshipType getType();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirAttr.java
deleted file mode 100644
index 7761d93..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirAttr.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.api.entity;
-
-import java.util.List;
-
-public interface VirAttr<O extends Any<?, ?, ?>> extends Attr<VirSchema, O> {
-
-    List<String> getValues();
-
-    boolean add(String value);
-
-    boolean remove(String value);
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirSchema.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirSchema.java
index 8b796c4..65cc11d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirSchema.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/VirSchema.java
@@ -18,7 +18,20 @@
  */
 package org.apache.syncope.core.persistence.api.entity;
 
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+
 public interface VirSchema extends Schema {
 
     void setReadonly(boolean readonly);
+
+    Provision getProvision();
+
+    void setProvision(Provision provision);
+
+    String getExtAttrName();
+
+    void setExtAttrName(String extAttrName);
+
+    MappingItem asLinkingMappingItem();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AVirAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AVirAttr.java
deleted file mode 100644
index be86c59..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AVirAttr.java
+++ /dev/null
@@ -1,25 +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.persistence.api.entity.anyobject;
-
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-
-public interface AVirAttr extends VirAttr<AnyObject> {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
index 2094269..1e10257 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
@@ -23,7 +23,7 @@ import java.util.List;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 
-public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
+public interface AnyObject extends Any<APlainAttr, ADerAttr> {
 
     boolean add(ARelationship relationship);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/conf/Conf.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/conf/Conf.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/conf/Conf.java
index 2b6e424..f4ca14d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/conf/Conf.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/conf/Conf.java
@@ -21,9 +21,8 @@ package org.apache.syncope.core.persistence.api.entity.conf;
 import java.util.List;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 
-public interface Conf extends Any<CPlainAttr, DerAttr<?>, VirAttr<?>> {
+public interface Conf extends Any<CPlainAttr, DerAttr<?>> {
 
     void setKey(Long key);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/GVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/GVirAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/GVirAttr.java
deleted file mode 100644
index 1847794..0000000
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/GVirAttr.java
+++ /dev/null
@@ -1,25 +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.persistence.api.entity.group;
-
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-
-public interface GVirAttr extends VirAttr<Group> {
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/Group.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/Group.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/Group.java
index cb6008e..0afddba 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/Group.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/group/Group.java
@@ -25,7 +25,7 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembers
 import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 
-public interface Group extends Any<GPlainAttr, GDerAttr, GVirAttr> {
+public interface Group extends Any<GPlainAttr, GDerAttr> {
 
     String getName();
 
@@ -63,18 +63,6 @@ public interface Group extends Any<GPlainAttr, GDerAttr, GVirAttr> {
     @Override
     List<? extends GDerAttr> getDerAttrs();
 
-    @Override
-    boolean add(GVirAttr attr);
-
-    @Override
-    boolean remove(GVirAttr virAttr);
-
-    @Override
-    GVirAttr getVirAttr(String virSchemaName);
-
-    @Override
-    List<? extends GVirAttr> getVirAttrs();
-
     ADynGroupMembership getADynMembership();
 
     void setADynMembership(ADynGroupMembership aDynMembership);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9cd92305/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PropagationTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PropagationTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PropagationTask.java
index db9e5a3..2d19436 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PropagationTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/PropagationTask.java
@@ -54,6 +54,10 @@ public interface PropagationTask extends Task {
 
     void setAnyTypeKind(AnyTypeKind anyTypeKind);
 
+    String getAnyType();
+
+    void setAnyType(String anyType);
+
     ExternalResource getResource();
 
     void setResource(ExternalResource resource);