syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [06/22] syncope git commit: [SYNCOPE-694] Implementation completed
Date Mon, 21 Sep 2015 14:50:57 GMT
http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultSyncActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultSyncActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultSyncActions.java
index 668584b..455a799 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultSyncActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/DefaultSyncActions.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.java.sync;
 
-import org.apache.syncope.common.lib.mod.AnyMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.core.provisioning.api.sync.SyncActions;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningProfile;
@@ -36,11 +36,11 @@ public abstract class DefaultSyncActions implements SyncActions {
     }
 
     @Override
-    public <A extends AnyTO, M extends AnyMod> SyncDelta beforeUpdate(
+    public <A extends AnyTO, P extends AnyPatch> SyncDelta beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final A any,
-            final M anyMod) throws JobExecutionException {
+            final P anyMod) throws JobExecutionException {
 
         return delta;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/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 df26d58..44a034b 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
@@ -21,10 +21,12 @@ package org.apache.syncope.core.provisioning.java.sync;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+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.core.persistence.api.entity.Any;
@@ -77,35 +79,41 @@ public class GroupPushResultHandlerImpl extends AbstractPushResultHandler implem
 
     @Override
     protected Any<?, ?, ?> link(final Any<?, ?, ?> sbj, final Boolean unlink) {
-        GroupMod groupMod = new GroupMod();
-        groupMod.setKey(sbj.getKey());
+        GroupPatch groupPatch = new GroupPatch();
+        groupPatch.setKey(sbj.getKey());
 
-        if (unlink) {
-            groupMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
-        } else {
-            groupMod.getResourcesToAdd().add(profile.getTask().getResource().getKey());
-        }
+        groupPatch.getResources().add(new StringPatchItem.Builder().
+                operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
+                value(profile.getTask().getResource().getKey()).build());
 
-        gwfAdapter.update(groupMod);
+        gwfAdapter.update(groupPatch);
 
         return groupDAO.authFind(sbj.getKey());
     }
 
     @Override
     protected Any<?, ?, ?> unassign(final Any<?, ?, ?> sbj) {
-        GroupMod groupMod = new GroupMod();
-        groupMod.setKey(sbj.getKey());
-        groupMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
-        gwfAdapter.update(groupMod);
+        GroupPatch groupPatch = new GroupPatch();
+        groupPatch.setKey(sbj.getKey());
+        groupPatch.getResources().add(new StringPatchItem.Builder().
+                operation(PatchOperation.DELETE).
+                value(profile.getTask().getResource().getKey()).build());
+
+        gwfAdapter.update(groupPatch);
+
         return deprovision(sbj);
     }
 
     @Override
     protected Any<?, ?, ?> assign(final Any<?, ?, ?> sbj, final Boolean enabled) {
-        GroupMod groupMod = new GroupMod();
-        groupMod.setKey(sbj.getKey());
-        groupMod.getResourcesToAdd().add(profile.getTask().getResource().getKey());
-        gwfAdapter.update(groupMod);
+        GroupPatch groupPatch = new GroupPatch();
+        groupPatch.setKey(sbj.getKey());
+        groupPatch.getResources().add(new StringPatchItem.Builder().
+                operation(PatchOperation.ADD_REPLACE).
+                value(profile.getTask().getResource().getKey()).build());
+
+        gwfAdapter.update(groupPatch);
+
         return provision(sbj, enabled);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/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 860e10b..8c11184 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
@@ -22,13 +22,15 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.apache.syncope.common.lib.mod.AnyMod;
-import org.apache.syncope.common.lib.mod.AttrMod;
-import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.AttrPatch;
+import org.apache.syncope.common.lib.patch.GroupPatch;
+import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
 import org.apache.syncope.core.provisioning.api.sync.GroupSyncResultHandler;
@@ -81,34 +83,33 @@ public class GroupSyncResultHandlerImpl extends AbstractSyncResultHandler implem
             final ProvisioningResult result,
             final boolean unlink) {
 
-        GroupMod groupMod = new GroupMod();
-        groupMod.setKey(before.getKey());
+        GroupPatch groupPatch = new GroupPatch();
+        groupPatch.setKey(before.getKey());
+        groupPatch.getResources().add(new StringPatchItem.Builder().
+                operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
+                value(profile.getTask().getResource().getKey()).build());
 
-        if (unlink) {
-            groupMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
-        } else {
-            groupMod.getResourcesToAdd().add(profile.getTask().getResource().getKey());
-        }
-
-        return groupDataBinder.getGroupTO(gwfAdapter.update(groupMod).getResult());
+        return groupDataBinder.getGroupTO(gwfAdapter.update(groupPatch).getResult());
     }
 
     @Override
     protected AnyTO doUpdate(
             final AnyTO before,
-            final AnyMod anyMod,
+            final AnyPatch anyPatch,
             final SyncDelta delta,
             final ProvisioningResult result) {
 
-        GroupMod groupMod = GroupMod.class.cast(anyMod);
+        GroupPatch groupPatch = GroupPatch.class.cast(anyPatch);
 
-        Map.Entry<Long, List<PropagationStatus>> updated = groupProvisioningManager.update(groupMod);
+        Map.Entry<Long, List<PropagationStatus>> updated = groupProvisioningManager.update(groupPatch);
 
         // moved after group provisioning manager
         String groupOwner = null;
-        for (AttrMod attrMod : groupMod.getPlainAttrsToUpdate()) {
-            if (attrMod.getSchema().isEmpty() && !attrMod.getValuesToBeAdded().isEmpty()) {
-                groupOwner = attrMod.getValuesToBeAdded().iterator().next();
+        for (AttrPatch attrPatch : groupPatch.getPlainAttrs()) {
+            if (attrPatch.getOperation() == PatchOperation.ADD_REPLACE && attrPatch.getAttrTO() != null
+                    && attrPatch.getAttrTO().getSchema().isEmpty() && !attrPatch.getAttrTO().getValues().isEmpty()) {
+
+                groupOwner = attrPatch.getAttrTO().getValues().get(0);
             }
         }
         if (groupOwner != null) {
@@ -127,9 +128,11 @@ public class GroupSyncResultHandlerImpl extends AbstractSyncResultHandler implem
         taskExecutor.execute(propagationManager.getGroupDeleteTasks(key, profile.getTask().getResource().getKey()));
 
         if (unlink) {
-            GroupMod groupMod = new GroupMod();
-            groupMod.setKey(key);
-            groupMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
+            GroupPatch groupPatch = new GroupPatch();
+            groupPatch.setKey(key);
+            groupPatch.getResources().add(new StringPatchItem.Builder().
+                    operation(PatchOperation.DELETE).
+                    value(profile.getTask().getResource().getKey()).build());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
index cf4fb17..430d06d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
@@ -25,13 +25,16 @@ import java.util.Map;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.mod.AnyMod;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.MembershipPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
+import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
@@ -129,9 +132,9 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
      * {@inheritDoc}
      */
     @Override
-    public <A extends AnyTO, M extends AnyMod> SyncDelta beforeUpdate(
+    public <A extends AnyTO, M extends AnyPatch> SyncDelta beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
-            final SyncDelta delta, final A any, final M anyMod) throws JobExecutionException {
+            final SyncDelta delta, final A any, final M anyPatch) throws JobExecutionException {
 
         if (any instanceof GroupTO) {
             // search for all users assigned to given group
@@ -146,27 +149,32 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
             }
         }
 
-        return super.beforeUpdate(profile, delta, any, anyMod);
+        return super.beforeUpdate(profile, delta, any, anyPatch);
     }
 
     /**
-     * Build UserMod for adding membership to given user, for given group.
+     * Build UserPatch for adding membership to given user, for given group.
      *
      * @param userKey user to be assigned membership to given group
      * @param groupTO group for adding membership
-     * @return UserMod for user update
+     * @return UserPatch for user update
      */
-    protected UserMod getUserMod(final Long userKey, final GroupTO groupTO) {
-        UserMod userMod = new UserMod();
+    protected UserPatch getUserPatch(final Long userKey, final GroupTO groupTO) {
+        UserPatch userPatch = new UserPatch();
         // no actual modification takes place when user has already the group assigned
         if (membersBeforeGroupUpdate.containsKey(userKey)) {
             membersBeforeGroupUpdate.remove(userKey);
         } else {
-            userMod.setKey(userKey);
-            userMod.getMembershipsToAdd().add(groupTO.getKey());
+            userPatch.setKey(userKey);
+
+            userPatch.getMemberships().add(
+                    new MembershipPatch.Builder().
+                    operation(PatchOperation.ADD_REPLACE).
+                    membershipTO(new MembershipTO.Builder().group(groupTO.getKey(), null).build()).
+                    build());
         }
 
-        return userMod;
+        return userPatch;
     }
 
     /**
@@ -200,20 +208,20 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
     /**
      * Perform actual modifications (i.e. membership add / remove) for the given group on the given resource.
      *
-     * @param userMod modifications to perform on the user
+     * @param userPatch modifications to perform on the user
      * @param resourceName resource to be propagated for changes
      */
-    protected void userUpdate(final UserMod userMod, final String resourceName) {
-        if (userMod.getKey() == 0) {
+    protected void userUpdate(final UserPatch userPatch, final String resourceName) {
+        if (userPatch.getKey() == 0) {
             return;
         }
 
         Result result;
 
-        WorkflowResult<Pair<UserMod, Boolean>> updated = null;
+        WorkflowResult<Pair<UserPatch, Boolean>> updated = null;
 
         try {
-            updated = uwfAdapter.update(userMod);
+            updated = uwfAdapter.update(userPatch);
 
             List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(
                     updated, false, Collections.singleton(resourceName));
@@ -222,10 +230,10 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
             result = Result.SUCCESS;
         } catch (PropagationException e) {
             result = Result.FAILURE;
-            LOG.error("Could not propagate {}", userMod, e);
+            LOG.error("Could not propagate {}", userPatch, e);
         } catch (Exception e) {
             result = Result.FAILURE;
-            LOG.error("Could not perform update {}", userMod, e);
+            LOG.error("Could not perform update {}", userPatch, e);
         }
 
         notificationManager.createTasks(
@@ -236,7 +244,7 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
                 result,
                 null, // searching for before object is too much expensive ... 
                 updated == null ? null : updated.getResult().getKey(),
-                userMod,
+                userPatch,
                 resourceName);
 
         auditManager.audit(
@@ -247,7 +255,7 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
                 result,
                 null, // searching for before object is too much expensive ... 
                 updated == null ? null : updated.getResult().getKey(),
-                userMod,
+                userPatch,
                 resourceName);
     }
 
@@ -274,17 +282,23 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
                     profile.getTask().getResource(),
                     profile.getConnector());
             if (userKey != null) {
-                UserMod userMod = getUserMod(userKey, groupTO);
-                userUpdate(userMod, resource.getKey());
+                UserPatch userPatch = getUserPatch(userKey, groupTO);
+                userUpdate(userPatch, resource.getKey());
             }
         }
 
         // finally remove any residual membership that was present before group update but not any more
         for (Map.Entry<Long, Long> member : membersBeforeGroupUpdate.entrySet()) {
-            UserMod userMod = new UserMod();
-            userMod.setKey(member.getKey());
-            userMod.getMembershipsToRemove().add(member.getValue());
-            userUpdate(userMod, resource.getKey());
+            UserPatch userPatch = new UserPatch();
+            userPatch.setKey(member.getKey());
+
+            userPatch.getMemberships().add(
+                    new MembershipPatch.Builder().
+                    operation(PatchOperation.DELETE).
+                    membershipTO(new MembershipTO.Builder().group(groupTO.getKey(), null).build()).
+                    build());
+
+            userUpdate(userPatch, resource.getKey());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPPasswordSyncActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPPasswordSyncActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPPasswordSyncActions.java
index b35e42f..c58537e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPPasswordSyncActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPPasswordSyncActions.java
@@ -18,8 +18,9 @@
  */
 package org.apache.syncope.core.provisioning.java.sync;
 
-import org.apache.syncope.common.lib.mod.AnyMod;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.PasswordPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -68,15 +69,15 @@ public class LDAPPasswordSyncActions extends DefaultSyncActions {
 
     @Transactional(readOnly = true)
     @Override
-    public <A extends AnyTO, M extends AnyMod> SyncDelta beforeUpdate(
+    public <A extends AnyTO, M extends AnyPatch> SyncDelta beforeUpdate(
             final ProvisioningProfile<?, ?> profile,
             final SyncDelta delta,
             final A any,
-            final M anyMod) throws JobExecutionException {
+            final M anyPatch) throws JobExecutionException {
 
-        if (anyMod instanceof UserMod) {
-            String modPassword = ((UserMod) anyMod).getPassword();
-            parseEncodedPassword(modPassword);
+        if (anyPatch instanceof UserPatch) {
+            PasswordPatch modPassword = ((UserPatch) anyPatch).getPassword();
+            parseEncodedPassword(modPassword == null ? null : modPassword.getValue());
         }
 
         return delta;

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/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 e4a436f..12d1eb6 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
@@ -21,10 +21,12 @@ package org.apache.syncope.core.provisioning.java.sync;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.StringPatchItem;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+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.core.persistence.api.entity.Any;
@@ -80,35 +82,39 @@ public class UserPushResultHandlerImpl extends AbstractPushResultHandler impleme
 
     @Override
     protected Any<?, ?, ?> link(final Any<?, ?, ?> sbj, final Boolean unlink) {
-        UserMod userMod = new UserMod();
-        userMod.setKey(sbj.getKey());
+        UserPatch userPatch = new UserPatch();
+        userPatch.setKey(sbj.getKey());
+        userPatch.getResources().add(new StringPatchItem.Builder().
+                operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
+                value(profile.getTask().getResource().getKey()).build());
 
-        if (unlink) {
-            userMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
-        } else {
-            userMod.getResourcesToAdd().add(profile.getTask().getResource().getKey());
-        }
-
-        uwfAdapter.update(userMod);
+        uwfAdapter.update(userPatch);
 
-        return userDAO.authFind(userMod.getKey());
+        return userDAO.authFind(userPatch.getKey());
     }
 
     @Override
     protected Any<?, ?, ?> unassign(final Any<?, ?, ?> sbj) {
-        UserMod userMod = new UserMod();
-        userMod.setKey(sbj.getKey());
-        userMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
-        uwfAdapter.update(userMod);
+        UserPatch userPatch = new UserPatch();
+        userPatch.setKey(sbj.getKey());
+        userPatch.getResources().add(new StringPatchItem.Builder().
+                operation(PatchOperation.DELETE).
+                value(profile.getTask().getResource().getKey()).build());
+
+        uwfAdapter.update(userPatch);
+
         return deprovision(sbj);
     }
 
     @Override
     protected Any<?, ?, ?> assign(final Any<?, ?, ?> sbj, final Boolean enabled) {
-        UserMod userMod = new UserMod();
-        userMod.setKey(sbj.getKey());
-        userMod.getResourcesToAdd().add(profile.getTask().getResource().getKey());
-        uwfAdapter.update(userMod);
+        UserPatch userPatch = new UserPatch();
+        userPatch.setKey(sbj.getKey());
+        userPatch.getResources().add(new StringPatchItem.Builder().
+                operation(PatchOperation.ADD_REPLACE).
+                value(profile.getTask().getResource().getKey()).build());
+        uwfAdapter.update(userPatch);
+
         return provision(sbj, enabled);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/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 20a3673..5205c0d 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
@@ -21,12 +21,14 @@ package org.apache.syncope.core.provisioning.java.sync;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import org.apache.syncope.common.lib.mod.AnyMod;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.StringPatchItem;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
 import org.apache.syncope.core.provisioning.api.sync.UserSyncResultHandler;
@@ -74,29 +76,26 @@ public class UserSyncResultHandlerImpl extends AbstractSyncResultHandler impleme
             final ProvisioningResult result,
             final boolean unlink) {
 
-        UserMod userMod = new UserMod();
-        userMod.setKey(before.getKey());
+        UserPatch userPatch = new UserPatch();
+        userPatch.setKey(before.getKey());
+        userPatch.getResources().add(new StringPatchItem.Builder().
+                operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
+                value(profile.getTask().getResource().getKey()).build());
 
-        if (unlink) {
-            userMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
-        } else {
-            userMod.getResourcesToAdd().add(profile.getTask().getResource().getKey());
-        }
-
-        return userDataBinder.getUserTO(uwfAdapter.update(userMod).getResult().getKey().getKey());
+        return userDataBinder.getUserTO(uwfAdapter.update(userPatch).getResult().getKey().getKey());
     }
 
     @Override
     protected AnyTO doUpdate(
             final AnyTO before,
-            final AnyMod anyMod,
+            final AnyPatch anyPatch,
             final SyncDelta delta,
             final ProvisioningResult result) {
 
-        UserMod userMod = UserMod.class.cast(anyMod);
+        UserPatch userPatch = UserPatch.class.cast(anyPatch);
         Boolean enabled = syncUtilities.readEnabled(delta.getObject(), profile.getTask());
 
-        Map.Entry<Long, List<PropagationStatus>> updated = userProvisioningManager.update(userMod, before.getKey(),
+        Map.Entry<Long, List<PropagationStatus>> updated = userProvisioningManager.update(userPatch, before.getKey(),
                 result, enabled, Collections.singleton(profile.getTask().getResource().getKey()));
 
         return userDataBinder.getUserTO(updated.getKey());
@@ -111,9 +110,11 @@ public class UserSyncResultHandlerImpl extends AbstractSyncResultHandler impleme
                 key, Collections.singleton(profile.getTask().getResource().getKey())));
 
         if (unlink) {
-            UserMod userMod = new UserMod();
-            userMod.setKey(key);
-            userMod.getResourcesToRemove().add(profile.getTask().getResource().getKey());
+            UserPatch userPatch = new UserPatch();
+            userPatch.setKey(key);
+            userPatch.getResources().add(new StringPatchItem.Builder().
+                    operation(PatchOperation.DELETE).
+                    value(profile.getTask().getResource().getKey()).build());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
index 2de8989..fff8469 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
@@ -90,7 +90,7 @@ public class RestServiceExceptionMapper implements ExceptionMapper<Exception>, R
 
     @Override
     public Response toResponse(final Exception ex) {
-        LOG.error("Exception thrown by REST method: " + ex.getMessage(), ex);
+        LOG.error("Exception thrown", ex);
 
         ResponseBuilder builder;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/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 d54dbca..9fb9252 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
@@ -18,24 +18,24 @@
  */
 package org.apache.syncope.core.rest.cxf.service;
 
-import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.mod.AnyMod;
-import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
-import org.apache.syncope.common.lib.mod.StatusMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
+import org.apache.syncope.common.lib.patch.AssociationPatch;
+import org.apache.syncope.common.lib.patch.DeassociationPatch;
+import org.apache.syncope.common.lib.patch.StatusPatch;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.BulkAction;
 import org.apache.syncope.common.lib.to.BulkActionResult;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.types.ResourceAssociationAction;
-import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
-import org.apache.syncope.common.lib.wrap.ResourceKey;
-import org.apache.syncope.common.rest.api.CollectionWrapper;
+import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
+import org.apache.syncope.common.lib.types.StatusPatchType;
 import org.apache.syncope.common.rest.api.beans.AnyListQuery;
 import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
 import org.apache.syncope.common.rest.api.service.AnyService;
@@ -43,11 +43,11 @@ import org.apache.syncope.core.logic.AbstractAnyLogic;
 import org.apache.syncope.core.logic.UserLogic;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 
-public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
+public abstract class AbstractAnyService<TO extends AnyTO, P extends AnyPatch>
         extends AbstractServiceImpl
-        implements AnyService<TO, MOD> {
+        implements AnyService<TO, P> {
 
-    protected abstract AbstractAnyLogic<TO, MOD> getAnyLogic();
+    protected abstract AbstractAnyLogic<TO, P> getAnyLogic();
 
     @Override
     public TO read(final Long key) {
@@ -107,12 +107,23 @@ public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
     }
 
     @Override
-    public Response update(final MOD anyMod) {
-        TO any = getAnyLogic().read(anyMod.getKey());
+    public Response update(final P anyPatch) {
+        TO any = getAnyLogic().read(anyPatch.getKey());
 
         checkETag(any.getETagValue());
 
-        TO updated = getAnyLogic().update(anyMod);
+        TO updated = getAnyLogic().update(anyPatch);
+        return modificationResponse(updated);
+    }
+
+    @Override
+    public Response update(final TO anyTO) {
+        TO before = getAnyLogic().read(anyTO.getKey());
+
+        checkETag(before.getETagValue());
+
+        @SuppressWarnings("unchecked")
+        TO updated = getAnyLogic().update((P) AnyOperations.diff(anyTO, before, false));
         return modificationResponse(updated);
     }
 
@@ -127,37 +138,35 @@ public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
     }
 
     @Override
-    public Response deassociate(
-            final Long key, final ResourceDeassociationActionType type, final List<ResourceKey> resourceNames) {
-
-        TO any = getAnyLogic().read(key);
+    public Response deassociate(final DeassociationPatch patch) {
+        TO any = getAnyLogic().read(patch.getKey());
 
         checkETag(any.getETagValue());
 
         TO updated;
-        switch (type) {
+        switch (patch.getAction()) {
             case UNLINK:
-                updated = getAnyLogic().unlink(key, CollectionWrapper.unwrap(resourceNames));
+                updated = getAnyLogic().unlink(patch.getKey(), patch.getResources());
                 break;
 
             case UNASSIGN:
-                updated = getAnyLogic().unassign(key, CollectionWrapper.unwrap(resourceNames));
+                updated = getAnyLogic().unassign(patch.getKey(), patch.getResources());
                 break;
 
             case DEPROVISION:
-                updated = getAnyLogic().deprovision(key, CollectionWrapper.unwrap(resourceNames));
+                updated = getAnyLogic().deprovision(patch.getKey(), patch.getResources());
                 break;
 
             default:
-                updated = getAnyLogic().read(key);
+                updated = getAnyLogic().read(patch.getKey());
         }
 
         BulkActionResult result = new BulkActionResult();
 
-        if (type == ResourceDeassociationActionType.UNLINK) {
-            for (ResourceKey resourceName : resourceNames) {
-                result.getResults().put(resourceName.getElement(),
-                        updated.getResources().contains(resourceName.getElement())
+        if (patch.getAction() == ResourceDeassociationAction.UNLINK) {
+            for (String resource : patch.getResources()) {
+                result.getResults().put(resource,
+                        updated.getResources().contains(resource)
                                 ? BulkActionResult.Status.FAILURE
                                 : BulkActionResult.Status.SUCCESS);
             }
@@ -172,47 +181,45 @@ public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
     }
 
     @Override
-    public Response associate(
-            final Long key, final ResourceAssociationAction type, final ResourceAssociationMod associationMod) {
-
-        TO any = getAnyLogic().read(key);
+    public Response associate(final AssociationPatch patch) {
+        TO any = getAnyLogic().read(patch.getKey());
 
         checkETag(any.getETagValue());
 
         TO updated;
-        switch (type) {
+        switch (patch.getAction()) {
             case LINK:
                 updated = getAnyLogic().link(
-                        key,
-                        CollectionWrapper.unwrap(associationMod.getTargetResources()));
+                        patch.getKey(),
+                        patch.getResources());
                 break;
 
             case ASSIGN:
                 updated = getAnyLogic().assign(
-                        key,
-                        CollectionWrapper.unwrap(associationMod.getTargetResources()),
-                        associationMod.isChangePwd(),
-                        associationMod.getPassword());
+                        patch.getKey(),
+                        patch.getResources(),
+                        patch.getValue() != null,
+                        patch.getValue());
                 break;
 
             case PROVISION:
                 updated = getAnyLogic().provision(
-                        key,
-                        CollectionWrapper.unwrap(associationMod.getTargetResources()),
-                        associationMod.isChangePwd(),
-                        associationMod.getPassword());
+                        patch.getKey(),
+                        patch.getResources(),
+                        patch.getValue() != null,
+                        patch.getValue());
                 break;
 
             default:
-                updated = getAnyLogic().read(key);
+                updated = getAnyLogic().read(patch.getKey());
         }
 
         BulkActionResult result = new BulkActionResult();
 
-        if (type == ResourceAssociationAction.LINK) {
-            for (ResourceKey resourceName : associationMod.getTargetResources()) {
-                result.getResults().put(resourceName.getElement(),
-                        updated.getResources().contains(resourceName.getElement())
+        if (patch.getAction() == ResourceAssociationAction.LINK) {
+            for (String resource : patch.getResources()) {
+                result.getResults().put(resource,
+                        updated.getResources().contains(resource)
                                 ? BulkActionResult.Status.FAILURE
                                 : BulkActionResult.Status.SUCCESS);
             }
@@ -228,7 +235,7 @@ public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
 
     @Override
     public BulkActionResult bulk(final BulkAction bulkAction) {
-        AbstractAnyLogic<TO, MOD> logic = getAnyLogic();
+        AbstractAnyLogic<TO, P> logic = getAnyLogic();
 
         BulkActionResult result = new BulkActionResult();
 
@@ -249,12 +256,12 @@ public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
             case SUSPEND:
                 if (logic instanceof UserLogic) {
                     for (String key : bulkAction.getTargets()) {
-                        StatusMod statusMod = new StatusMod();
-                        statusMod.setKey(Long.valueOf(key));
-                        statusMod.setType(StatusMod.ModType.SUSPEND);
+                        StatusPatch statusPatch = new StatusPatch();
+                        statusPatch.setKey(Long.valueOf(key));
+                        statusPatch.setType(StatusPatchType.SUSPEND);
                         try {
                             result.getResults().put(
-                                    String.valueOf(((UserLogic) logic).status(statusMod).getKey()),
+                                    String.valueOf(((UserLogic) logic).status(statusPatch).getKey()),
                                     BulkActionResult.Status.SUCCESS);
                         } catch (Exception e) {
                             LOG.error("Error performing suspend for user {}", key, e);
@@ -266,12 +273,12 @@ public abstract class AbstractAnyService<TO extends AnyTO, MOD extends AnyMod>
 
             case REACTIVATE:
                 for (String key : bulkAction.getTargets()) {
-                    StatusMod statusMod = new StatusMod();
-                    statusMod.setKey(Long.valueOf(key));
-                    statusMod.setType(StatusMod.ModType.REACTIVATE);
+                    StatusPatch statusPatch = new StatusPatch();
+                    statusPatch.setKey(Long.valueOf(key));
+                    statusPatch.setType(StatusPatchType.REACTIVATE);
                     try {
                         result.getResults().put(
-                                String.valueOf(((UserLogic) logic).status(statusMod).getKey()),
+                                String.valueOf(((UserLogic) logic).status(statusPatch).getKey()),
                                 BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing reactivate for user {}", key, e);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
index 859d008..4a57cbd 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyObjectServiceImpl.java
@@ -22,7 +22,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.mod.AnyObjectMod;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.rest.api.beans.AnyListQuery;
@@ -33,13 +33,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
-public class AnyObjectServiceImpl extends AbstractAnyService<AnyObjectTO, AnyObjectMod> implements AnyObjectService {
+public class AnyObjectServiceImpl extends AbstractAnyService<AnyObjectTO, AnyObjectPatch> implements AnyObjectService {
 
     @Autowired
     private AnyObjectLogic logic;
 
     @Override
-    protected AbstractAnyLogic<AnyObjectTO, AnyObjectMod> getAnyLogic() {
+    protected AbstractAnyLogic<AnyObjectTO, AnyObjectPatch> getAnyLogic() {
         return logic;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
index 8f7b503..a970827 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
@@ -30,7 +30,6 @@ import org.apache.syncope.common.lib.to.ConnBundleTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
-import org.apache.syncope.common.lib.wrap.BooleanWrap;
 import org.apache.syncope.common.lib.wrap.ConnIdObjectClass;
 import org.apache.syncope.common.rest.api.CollectionWrapper;
 import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -117,10 +116,8 @@ public class ConnectorServiceImpl extends AbstractServiceImpl implements Connect
     }
 
     @Override
-    public BooleanWrap check(final ConnInstanceTO connInstanceTO) {
-        BooleanWrap result = new BooleanWrap();
-        result.setElement(logic.check(connInstanceTO));
-        return result;
+    public void check(final ConnInstanceTO connInstanceTO) {
+        logic.check(connInstanceTO);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
index 2d6c6e4..929b1fa 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.core.rest.cxf.service;
 
 import java.util.List;
-import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.patch.GroupPatch;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.rest.api.service.GroupService;
 import org.apache.syncope.core.logic.AbstractAnyLogic;
@@ -28,13 +28,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
-public class GroupServiceImpl extends AbstractAnyService<GroupTO, GroupMod> implements GroupService {
+public class GroupServiceImpl extends AbstractAnyService<GroupTO, GroupPatch> implements GroupService {
 
     @Autowired
     private GroupLogic logic;
 
     @Override
-    protected AbstractAnyLogic<GroupTO, GroupMod> getAnyLogic() {
+    protected AbstractAnyLogic<GroupTO, GroupPatch> getAnyLogic() {
         return logic;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
index 408fb04..2cc6476 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
@@ -35,9 +35,8 @@ import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.common.lib.to.PagedConnObjectTOResult;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
+import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
 import org.apache.syncope.common.lib.wrap.AnyKey;
-import org.apache.syncope.common.lib.wrap.BooleanWrap;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.beans.ConnObjectTOListQuery;
 import org.apache.syncope.common.rest.api.service.ResourceService;
@@ -130,15 +129,13 @@ public class ResourceServiceImpl extends AbstractServiceImpl implements Resource
     }
 
     @Override
-    public BooleanWrap check(final ResourceTO resourceTO) {
-        BooleanWrap result = new BooleanWrap();
-        result.setElement(logic.check(resourceTO));
-        return result;
+    public void check(final ResourceTO resourceTO) {
+        logic.check(resourceTO);
     }
 
     @Override
     public BulkActionResult bulkDeassociation(
-            final String key, final String anyTypeKey, final ResourceDeassociationActionType type,
+            final String key, final String anyTypeKey, final ResourceDeassociationAction type,
             final List<AnyKey> keys) {
 
         AbstractResourceAssociator<? extends AnyTO> associator = anyTypeKey.equalsIgnoreCase(AnyTypeKind.USER.name())

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
index b1fbc35..ea69e69 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserSelfServiceImpl.java
@@ -20,8 +20,9 @@ package org.apache.syncope.core.rest.cxf.service;
 
 import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -63,12 +64,18 @@ public class UserSelfServiceImpl extends AbstractServiceImpl implements UserSelf
     }
 
     @Override
-    public Response update(final UserMod userMod) {
-        UserTO updated = logic.selfUpdate(userMod);
+    public Response update(final UserPatch patch) {
+        UserTO updated = logic.selfUpdate(patch);
         return modificationResponse(updated);
     }
 
     @Override
+    public Response update(final UserTO user) {
+        Pair<String, UserTO> self = logic.readSelf();
+        return update(AnyOperations.diff(user, self.getValue(), false));
+    }
+
+    @Override
     public Response delete() {
         UserTO deleted = logic.selfDelete();
         return modificationResponse(deleted);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
index 2447697..1770b41 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
@@ -20,8 +20,8 @@ package org.apache.syncope.core.rest.cxf.service;
 
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.Response;
-import org.apache.syncope.common.lib.mod.StatusMod;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.StatusPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.UserService;
@@ -31,13 +31,13 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service
-public class UserServiceImpl extends AbstractAnyService<UserTO, UserMod> implements UserService {
+public class UserServiceImpl extends AbstractAnyService<UserTO, UserPatch> implements UserService {
 
     @Autowired
     private UserLogic logic;
 
     @Override
-    protected AbstractAnyLogic<UserTO, UserMod> getAnyLogic() {
+    protected AbstractAnyLogic<UserTO, UserPatch> getAnyLogic() {
         return logic;
     }
 
@@ -62,12 +62,12 @@ public class UserServiceImpl extends AbstractAnyService<UserTO, UserMod> impleme
     }
 
     @Override
-    public Response status(final StatusMod statusMod) {
-        UserTO user = logic.read(statusMod.getKey());
+    public Response status(final StatusPatch statusPatch) {
+        UserTO user = logic.read(statusPatch.getKey());
 
         checkETag(user.getETagValue());
 
-        UserTO updated = logic.status(statusMod);
+        UserTO updated = logic.status(statusPatch);
         return modificationResponse(updated);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
index db95d8d..6b4f838 100644
--- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
@@ -56,8 +56,8 @@ 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.SyncopeClientException;
-import org.apache.syncope.common.lib.mod.StatusMod;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.PasswordPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
@@ -100,7 +100,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
 
     public static final String ENABLED = "enabled";
 
-    public static final String USER_MOD = "userMod";
+    public static final String USER_PATCH = "userPatch";
 
     public static final String EMAIL_KIND = "emailKind";
 
@@ -320,24 +320,25 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     }
 
     @Override
-    protected WorkflowResult<Pair<UserMod, Boolean>> doUpdate(final User user, final UserMod userMod) {
-        Set<String> tasks = doExecuteTask(user, "update", Collections.singletonMap(USER_MOD, (Object) userMod));
+    protected WorkflowResult<Pair<UserPatch, Boolean>> doUpdate(final User user, final UserPatch userPatch) {
+        Set<String> tasks = doExecuteTask(user, "update", Collections.singletonMap(USER_PATCH, (Object) userPatch));
 
         updateStatus(user);
         User updated = userDAO.save(user);
 
         PropagationByResource propByRes = engine.getRuntimeService().getVariable(
                 user.getWorkflowId(), PROP_BY_RESOURCE, PropagationByResource.class);
-        UserMod updatedMod = engine.getRuntimeService().getVariable(
-                user.getWorkflowId(), USER_MOD, UserMod.class);
+        UserPatch updatedPatch = engine.getRuntimeService().getVariable(
+                user.getWorkflowId(), USER_PATCH, UserPatch.class);
 
-        saveForFormSubmit(updated, updatedMod.getPassword(), propByRes);
+        saveForFormSubmit(
+                updated, updatedPatch.getPassword() == null ? null : updatedPatch.getPassword().getValue(), propByRes);
 
         Boolean propagateEnable = engine.getRuntimeService().getVariable(
                 user.getWorkflowId(), PROPAGATE_ENABLE, Boolean.class);
 
-        return new WorkflowResult<Pair<UserMod, Boolean>>(
-                new ImmutablePair<>(updatedMod, propagateEnable), propByRes, tasks);
+        return new WorkflowResult<Pair<UserPatch, Boolean>>(
+                new ImmutablePair<>(updatedPatch, propagateEnable), propByRes, tasks);
     }
 
     @Override
@@ -793,7 +794,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     }
 
     @Override
-    public WorkflowResult<UserMod> submitForm(final WorkflowFormTO form) {
+    public WorkflowResult<UserPatch> submitForm(final WorkflowFormTO form) {
         String authUser = AuthContextUtils.getUsername();
         Pair<Task, TaskFormData> checked = checkTask(form.getTaskId(), authUser);
 
@@ -836,22 +837,17 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         // supports approval chains
         saveForFormSubmit(user, clearPassword, propByRes);
 
-        UserMod userMod = engine.getRuntimeService().getVariable(user.getWorkflowId(), USER_MOD, UserMod.class);
-        if (userMod == null) {
-            userMod = new UserMod();
-            userMod.setKey(updated.getKey());
-            userMod.setPassword(clearPassword);
+        UserPatch userPatch = engine.getRuntimeService().getVariable(user.getWorkflowId(), USER_PATCH, UserPatch.class);
+        if (userPatch == null) {
+            userPatch = new UserPatch();
+            userPatch.setKey(updated.getKey());
+            userPatch.setPassword(new PasswordPatch.Builder().onSyncope(true).value(clearPassword).build());
 
             if (propByRes != null) {
-                StatusMod st = new StatusMod();
-                userMod.setPwdPropRequest(st);
-                st.setOnSyncope(true);
-                for (String res : propByRes.get(ResourceOperation.CREATE)) {
-                    st.getResources().add(res);
-                }
+                userPatch.getPassword().getResources().addAll(propByRes.get(ResourceOperation.CREATE));
             }
         }
 
-        return new WorkflowResult<>(userMod, propByRes, postTasks);
+        return new WorkflowResult<>(userPatch, propByRes, postTasks);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/task/Update.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/task/Update.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/task/Update.java
index e4ee649..21498ac 100644
--- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/task/Update.java
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/task/Update.java
@@ -19,7 +19,8 @@
 package org.apache.syncope.core.workflow.activiti.task;
 
 import org.apache.commons.lang3.SerializationUtils;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.PasswordPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
@@ -37,23 +38,29 @@ public class Update extends AbstractActivitiServiceTask {
     protected void doExecute(final String executionId) {
         User user = engine.getRuntimeService().
                 getVariable(executionId, ActivitiUserWorkflowAdapter.USER, User.class);
-        UserMod userMod =
-                engine.getRuntimeService().
-                getVariable(executionId, ActivitiUserWorkflowAdapter.USER_MOD, UserMod.class);
+        UserPatch userPatch = engine.getRuntimeService().
+                getVariable(executionId, ActivitiUserWorkflowAdapter.USER_PATCH, UserPatch.class);
 
         // update password internally only if required
-        UserMod updatedMod = SerializationUtils.clone(userMod);
-        String updatedPwd = updatedMod.getPassword();
-        if (updatedMod.getPwdPropRequest() != null && !updatedMod.getPwdPropRequest().isOnSyncope()) {
-            updatedMod.setPassword(null);
+        UserPatch updatedPatch = SerializationUtils.clone(userPatch);
+        PasswordPatch updatedPwd = updatedPatch.getPassword();
+        if (updatedPatch.getPassword() != null && !updatedPatch.getPassword().isOnSyncope()) {
+            updatedPatch.setPassword(null);
         }
         // update user
-        PropagationByResource propByRes = dataBinder.update(user, updatedMod);
-        updatedMod.setPassword(updatedPwd);
+        PropagationByResource propByRes = dataBinder.update(user, updatedPatch);
+        if (updatedPatch.getPassword() != null && !updatedPatch.getPassword().getResources().isEmpty()) {
+            if (updatedPwd == null) {
+                updatedPwd = updatedPatch.getPassword();
+            } else {
+                updatedPwd.getResources().addAll(updatedPatch.getPassword().getResources());
+            }
+        }
+        updatedPatch.setPassword(updatedPwd);
 
         // report updated user and propagation by resource as result
         engine.getRuntimeService().setVariable(executionId, ActivitiUserWorkflowAdapter.USER, user);
-        engine.getRuntimeService().setVariable(executionId, ActivitiUserWorkflowAdapter.USER_MOD, updatedMod);
+        engine.getRuntimeService().setVariable(executionId, ActivitiUserWorkflowAdapter.USER_PATCH, updatedPatch);
         engine.getRuntimeService().setVariable(executionId, ActivitiUserWorkflowAdapter.PROP_BY_RESOURCE, propByRes);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java
index 4927388..2a05443 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/AnyObjectWorkflowAdapter.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.workflow.api;
 
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
-import org.apache.syncope.common.lib.mod.AnyObjectMod;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 
 /**
@@ -47,10 +47,10 @@ public interface AnyObjectWorkflowAdapter extends WorkflowAdapter {
     /**
      * Update a anyObject.
      *
-     * @param anyObjectMod modification set to be performed
+     * @param anyObjectPatch modification set to be performed
      * @return anyObject just updated and propagations to be performed
      */
-    WorkflowResult<Long> update(AnyObjectMod anyObjectMod);
+    WorkflowResult<Long> update(AnyObjectPatch anyObjectPatch);
 
     /**
      * Delete a anyObject.

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java
index 26864ba..04f7f17 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/GroupWorkflowAdapter.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.workflow.api;
 
+import org.apache.syncope.common.lib.patch.GroupPatch;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
-import org.apache.syncope.common.lib.mod.GroupMod;
 import org.apache.syncope.common.lib.to.GroupTO;
 
 /**
@@ -47,10 +47,10 @@ public interface GroupWorkflowAdapter extends WorkflowAdapter {
     /**
      * Update a group.
      *
-     * @param groupMod modification set to be performed
+     * @param groupPatch modification set to be performed
      * @return group just updated and propagations to be performed
      */
-    WorkflowResult<Long> update(GroupMod groupMod);
+    WorkflowResult<Long> update(GroupPatch groupPatch);
 
     /**
      * Delete a group.

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
index 7122b84..51c3e77 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/UserWorkflowAdapter.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.workflow.api;
 
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
-import org.apache.syncope.common.lib.mod.UserMod;
 import org.apache.syncope.common.lib.to.UserTO;
 
 /**
@@ -81,10 +81,10 @@ public interface UserWorkflowAdapter extends WorkflowAdapter {
     /**
      * Update an user.
      *
-     * @param userMod modification set to be performed
+     * @param userPatch modification set to be performed
      * @return user just updated and propagations to be performed
      */
-    WorkflowResult<Pair<UserMod, Boolean>> update(UserMod userMod);
+    WorkflowResult<Pair<UserPatch, Boolean>> update(UserPatch userPatch);
 
     /**
      * Suspend an user.

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
index faf954a..fa05f09 100644
--- a/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
+++ b/core/workflow-api/src/main/java/org/apache/syncope/core/workflow/api/WorkflowAdapter.java
@@ -18,11 +18,11 @@
  */
 package org.apache.syncope.core.workflow.api;
 
-import org.apache.syncope.core.provisioning.api.WorkflowResult;
 import java.io.OutputStream;
 import java.util.List;
-import org.apache.syncope.common.lib.mod.AnyMod;
+import org.apache.syncope.common.lib.patch.AnyPatch;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
+import org.apache.syncope.core.provisioning.api.WorkflowResult;
 
 public interface WorkflowAdapter {
 
@@ -92,5 +92,5 @@ public interface WorkflowAdapter {
      * @param form to be submitted
      * @return object updated by this form submit
      */
-    WorkflowResult<? extends AnyMod> submitForm(WorkflowFormTO form);
+    WorkflowResult<? extends AnyPatch> submitForm(WorkflowFormTO form);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractAnyObjectWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractAnyObjectWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractAnyObjectWorkflowAdapter.java
index 3f0d61a..d124051 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractAnyObjectWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractAnyObjectWorkflowAdapter.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.workflow.java;
 
-import org.apache.syncope.common.lib.mod.AnyObjectMod;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -46,11 +46,11 @@ public abstract class AbstractAnyObjectWorkflowAdapter implements AnyObjectWorkf
         return null;
     }
 
-    protected abstract WorkflowResult<Long> doUpdate(AnyObject anyObject, AnyObjectMod anyObjectMod);
+    protected abstract WorkflowResult<Long> doUpdate(AnyObject anyObject, AnyObjectPatch anyObjectPatch);
 
     @Override
-    public WorkflowResult<Long> update(final AnyObjectMod anyObjectMod) {
-        return doUpdate(anyObjectDAO.authFind(anyObjectMod.getKey()), anyObjectMod);
+    public WorkflowResult<Long> update(final AnyObjectPatch anyObjectPatch) {
+        return doUpdate(anyObjectDAO.authFind(anyObjectPatch.getKey()), anyObjectPatch);
     }
 
     protected abstract void doDelete(AnyObject anyObject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractGroupWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractGroupWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractGroupWorkflowAdapter.java
index 2b921ce..50e96fe 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractGroupWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractGroupWorkflowAdapter.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.workflow.java;
 
-import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.patch.GroupPatch;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -46,11 +46,11 @@ public abstract class AbstractGroupWorkflowAdapter implements GroupWorkflowAdapt
         return null;
     }
 
-    protected abstract WorkflowResult<Long> doUpdate(Group group, GroupMod groupMod);
+    protected abstract WorkflowResult<Long> doUpdate(Group group, GroupPatch groupPatch);
 
     @Override
-    public WorkflowResult<Long> update(final GroupMod groupMod) {
-        return doUpdate(groupDAO.authFind(groupMod.getKey()), groupMod);
+    public WorkflowResult<Long> update(final GroupPatch groupPatch) {
+        return doUpdate(groupDAO.authFind(groupPatch.getKey()), groupPatch);
     }
 
     protected abstract void doDelete(Group group);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
index b829137..4236cff 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/AbstractUserWorkflowAdapter.java
@@ -20,7 +20,7 @@ package org.apache.syncope.core.workflow.java;
 
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.UserPatch;
 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.user.User;
@@ -71,11 +71,11 @@ public abstract class AbstractUserWorkflowAdapter implements UserWorkflowAdapter
         return doActivate(userDAO.authFind(key), token);
     }
 
-    protected abstract WorkflowResult<Pair<UserMod, Boolean>> doUpdate(User user, UserMod userMod);
+    protected abstract WorkflowResult<Pair<UserPatch, Boolean>> doUpdate(User user, UserPatch userPatch);
 
     @Override
-    public WorkflowResult<Pair<UserMod, Boolean>> update(final UserMod userMod) {
-        return doUpdate(userDAO.authFind(userMod.getKey()), userMod);
+    public WorkflowResult<Pair<UserPatch, Boolean>> update(final UserPatch userPatch) {
+        return doUpdate(userDAO.authFind(userPatch.getKey()), userPatch);
     }
 
     protected abstract WorkflowResult<Long> doSuspend(User user);

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
index 09f007d..36b2d65 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultAnyObjectWorkflowAdapter.java
@@ -21,7 +21,7 @@ package org.apache.syncope.core.workflow.java;
 import java.io.OutputStream;
 import java.util.Collections;
 import java.util.List;
-import org.apache.syncope.common.lib.mod.AnyObjectMod;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
 import org.apache.syncope.common.lib.types.PropagationByResource;
@@ -51,8 +51,8 @@ public class DefaultAnyObjectWorkflowAdapter extends AbstractAnyObjectWorkflowAd
     }
 
     @Override
-    protected WorkflowResult<Long> doUpdate(final AnyObject anyObject, final AnyObjectMod anyObjectMod) {
-        PropagationByResource propByRes = dataBinder.update(anyObject, anyObjectMod);
+    protected WorkflowResult<Long> doUpdate(final AnyObject anyObject, final AnyObjectPatch anyObjectPatch) {
+        PropagationByResource propByRes = dataBinder.update(anyObject, anyObjectPatch);
 
         AnyObject updated = anyObjectDAO.save(anyObject);
 
@@ -105,7 +105,7 @@ public class DefaultAnyObjectWorkflowAdapter extends AbstractAnyObjectWorkflowAd
     }
 
     @Override
-    public WorkflowResult<AnyObjectMod> submitForm(final WorkflowFormTO form) {
+    public WorkflowResult<AnyObjectPatch> submitForm(final WorkflowFormTO form) {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
index fa765ed..12173c1 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultGroupWorkflowAdapter.java
@@ -21,7 +21,7 @@ package org.apache.syncope.core.workflow.java;
 import java.io.OutputStream;
 import java.util.Collections;
 import java.util.List;
-import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.patch.GroupPatch;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
 import org.apache.syncope.common.lib.types.PropagationByResource;
@@ -51,8 +51,8 @@ public class DefaultGroupWorkflowAdapter extends AbstractGroupWorkflowAdapter {
     }
 
     @Override
-    protected WorkflowResult<Long> doUpdate(final Group group, final GroupMod groupMod) {
-        PropagationByResource propByRes = dataBinder.update(group, groupMod);
+    protected WorkflowResult<Long> doUpdate(final Group group, final GroupPatch groupPatch) {
+        PropagationByResource propByRes = dataBinder.update(group, groupPatch);
 
         Group updated = groupDAO.save(group);
 
@@ -105,7 +105,7 @@ public class DefaultGroupWorkflowAdapter extends AbstractGroupWorkflowAdapter {
     }
 
     @Override
-    public WorkflowResult<GroupMod> submitForm(final WorkflowFormTO form) {
+    public WorkflowResult<GroupPatch> submitForm(final WorkflowFormTO form) {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
index ef40bd5..1d70394 100644
--- a/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
+++ b/core/workflow-java/src/main/java/org/apache/syncope/core/workflow/java/DefaultUserWorkflowAdapter.java
@@ -24,7 +24,8 @@ import java.util.List;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.patch.PasswordPatch;
+import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
 import org.apache.syncope.common.lib.types.PropagationByResource;
@@ -105,21 +106,28 @@ public class DefaultUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     }
 
     @Override
-    protected WorkflowResult<Pair<UserMod, Boolean>> doUpdate(final User user, final UserMod userMod) {
+    protected WorkflowResult<Pair<UserPatch, Boolean>> doUpdate(final User user, final UserPatch userPatch) {
         // update password internally only if required
-        UserMod updatedMod = SerializationUtils.clone(userMod);
-        String updatedPwd = updatedMod.getPassword();
-        if (updatedMod.getPwdPropRequest() != null && !updatedMod.getPwdPropRequest().isOnSyncope()) {
-            updatedMod.setPassword(null);
+        UserPatch updatedPatch = SerializationUtils.clone(userPatch);
+        PasswordPatch updatedPwd = updatedPatch.getPassword();
+        if (updatedPatch.getPassword() != null && !updatedPatch.getPassword().isOnSyncope()) {
+            updatedPatch.setPassword(null);
         }
         // update User
-        PropagationByResource propByRes = dataBinder.update(user, updatedMod);
-        updatedMod.setPassword(updatedPwd);
+        PropagationByResource propByRes = dataBinder.update(user, updatedPatch);
+        if (updatedPatch.getPassword() != null && !updatedPatch.getPassword().getResources().isEmpty()) {
+            if (updatedPwd == null) {
+                updatedPwd = updatedPatch.getPassword();
+            } else {
+                updatedPwd.getResources().addAll(updatedPatch.getPassword().getResources());
+            }
+        }
+        updatedPatch.setPassword(updatedPwd);
 
         userDAO.save(user);
 
-        return new WorkflowResult<Pair<UserMod, Boolean>>(
-                new ImmutablePair<>(updatedMod, !user.isSuspended()), propByRes, "update");
+        return new WorkflowResult<Pair<UserPatch, Boolean>>(
+                new ImmutablePair<>(updatedPatch, !user.isSuspended()), propByRes, "update");
     }
 
     @Override
@@ -203,7 +211,7 @@ public class DefaultUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     }
 
     @Override
-    public WorkflowResult<UserMod> submitForm(final WorkflowFormTO form) {
+    public WorkflowResult<UserPatch> submitForm(final WorkflowFormTO form) {
         throw new WorkflowException(new UnsupportedOperationException("Not supported."));
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
index bb01cd3..4ba890a 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelAnyObjectProvisioningManager.java
@@ -27,7 +27,7 @@ import java.util.Set;
 import org.apache.camel.Exchange;
 import org.apache.camel.PollingConsumer;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.mod.AnyObjectMod;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
@@ -62,21 +62,21 @@ public class CamelAnyObjectProvisioningManager
     }
 
     @Override
-    public Pair<Long, List<PropagationStatus>> update(final AnyObjectMod anyMod) {
-        return update(anyMod, Collections.<String>emptySet());
+    public Pair<Long, List<PropagationStatus>> update(final AnyObjectPatch anyPatch) {
+        return update(anyPatch, Collections.<String>emptySet());
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public Pair<Long, List<PropagationStatus>> update(
-            final AnyObjectMod anyMod, final Set<String> excludedResources) {
+            final AnyObjectPatch anyPatch, final Set<String> excludedResources) {
 
         PollingConsumer pollingConsumer = getConsumer("direct:updateAnyObjectPort");
 
         Map<String, Object> props = new HashMap<>();
         props.put("excludedResources", excludedResources);
 
-        sendMessage("direct:updateAnyObject", anyMod, props);
+        sendMessage("direct:updateAnyObject", anyPatch, props);
 
         Exchange exchange = pollingConsumer.receive();
 
@@ -112,10 +112,10 @@ public class CamelAnyObjectProvisioningManager
     }
 
     @Override
-    public Long unlink(final AnyObjectMod anyObjectMod) {
+    public Long unlink(final AnyObjectPatch anyObjectPatch) {
         PollingConsumer pollingConsumer = getConsumer("direct:unlinkAnyObjectPort");
 
-        sendMessage("direct:unlinkAnyObject", anyObjectMod);
+        sendMessage("direct:unlinkAnyObject", anyObjectPatch);
 
         Exchange exchange = pollingConsumer.receive();
 
@@ -127,10 +127,10 @@ public class CamelAnyObjectProvisioningManager
     }
 
     @Override
-    public Long link(final AnyObjectMod anyObjectMod) {
+    public Long link(final AnyObjectPatch anyObjectPatch) {
         PollingConsumer pollingConsumer = getConsumer("direct:linkAnyObjectPort");
 
-        sendMessage("direct:linkAnyObject", anyObjectMod);
+        sendMessage("direct:linkAnyObject", anyObjectPatch);
 
         Exchange exchange = pollingConsumer.receive();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f73fa43/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelGroupProvisioningManager.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelGroupProvisioningManager.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelGroupProvisioningManager.java
index bc0c854..ea022bb 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelGroupProvisioningManager.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/CamelGroupProvisioningManager.java
@@ -27,7 +27,7 @@ import java.util.Set;
 import org.apache.camel.Exchange;
 import org.apache.camel.PollingConsumer;
 import org.apache.commons.lang3.tuple.Pair;
-import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.patch.GroupPatch;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.core.provisioning.api.GroupProvisioningManager;
@@ -82,21 +82,21 @@ public class CamelGroupProvisioningManager
     }
 
     @Override
-    public Pair<Long, List<PropagationStatus>> update(final GroupMod anyMod) {
-        return update(anyMod, Collections.<String>emptySet());
+    public Pair<Long, List<PropagationStatus>> update(final GroupPatch anyPatch) {
+        return update(anyPatch, Collections.<String>emptySet());
     }
 
     @Override
     @SuppressWarnings("unchecked")
     public Pair<Long, List<PropagationStatus>> update(
-            final GroupMod anyMod, final Set<String> excludedResources) {
+            final GroupPatch anyPatch, final Set<String> excludedResources) {
 
         PollingConsumer pollingConsumer = getConsumer("direct:updateGroupPort");
 
         Map<String, Object> props = new HashMap<>();
         props.put("excludedResources", excludedResources);
 
-        sendMessage("direct:updateGroup", anyMod, props);
+        sendMessage("direct:updateGroup", anyPatch, props);
 
         Exchange exchange = pollingConsumer.receive();
 
@@ -132,10 +132,10 @@ public class CamelGroupProvisioningManager
     }
 
     @Override
-    public Long unlink(final GroupMod groupMod) {
+    public Long unlink(final GroupPatch groupPatch) {
         PollingConsumer pollingConsumer = getConsumer("direct:unlinkGroupPort");
 
-        sendMessage("direct:unlinkGroup", groupMod);
+        sendMessage("direct:unlinkGroup", groupPatch);
 
         Exchange exchange = pollingConsumer.receive();
 
@@ -147,10 +147,10 @@ public class CamelGroupProvisioningManager
     }
 
     @Override
-    public Long link(final GroupMod groupMod) {
+    public Long link(final GroupPatch groupPatch) {
         PollingConsumer pollingConsumer = getConsumer("direct:linkGroupPort");
 
-        sendMessage("direct:linkGroup", groupMod);
+        sendMessage("direct:linkGroup", groupPatch);
 
         Exchange exchange = pollingConsumer.receive();
 
@@ -179,7 +179,7 @@ public class CamelGroupProvisioningManager
 
         return exchange.getIn().getBody(List.class);
     }
-    
+
     @Override
     @SuppressWarnings("unchecked")
     public List<PropagationStatus> deprovision(final Long key, final Collection<String> resources) {


Mime
View raw message