You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/06/29 12:10:18 UTC

[2/2] syncope git commit: Cleaning up unused R/O maps from TOs

Cleaning up unused R/O maps from TOs


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

Branch: refs/heads/master
Commit: 653b88a7251692cc63060444b71ff300c41d83d9
Parents: e19910c
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Thu Jun 29 14:09:31 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Thu Jun 29 14:10:04 2017 +0200

----------------------------------------------------------------------
 .../client/console/wizards/any/Groups.java      |  11 +-
 .../resources/UserSelfUpdateResource.java       |  13 +-
 .../syncope/common/lib/AnyOperations.java       |  91 +++------
 .../syncope/common/lib/EntityTOUtils.java       |  26 ++-
 .../common/lib/patch/MembershipPatch.java       |   8 +-
 .../syncope/common/lib/to/AnyObjectTO.java      |  46 +++--
 .../common/lib/to/GroupableRelatableTO.java     |   6 +-
 .../apache/syncope/common/lib/to/UserTO.java    |  44 ++---
 .../syncope/common/lib/to/WorkflowFormTO.java   |  48 ++---
 .../provisioning/java/MappingManagerImpl.java   |   6 +-
 .../java/data/AnyObjectDataBinderImpl.java      |  46 +++--
 .../java/data/UserDataBinderImpl.java           |  46 +++--
 .../provisioning/java/utils/TemplateUtils.java  |  35 ++--
 .../activiti/ActivitiUserWorkflowAdapter.java   |  17 +-
 .../syncope/fit/core/AnyObjectITCase.java       |   2 +-
 .../syncope/fit/core/AuthenticationITCase.java  |   6 +-
 .../apache/syncope/fit/core/GroupITCase.java    |   4 +-
 .../fit/core/IdentityRecertificationITCase.java |   2 +-
 .../syncope/fit/core/MembershipITCase.java      |  14 +-
 .../apache/syncope/fit/core/PushTaskITCase.java | 148 ---------------
 .../syncope/fit/core/PushTaskIssuesITCase.java  | 185 +++++++++++++++++++
 .../org/apache/syncope/fit/core/UserITCase.java |  31 +---
 .../apache/syncope/fit/core/UserSelfITCase.java |  11 +-
 .../syncope/fit/core/UserWorkflowITCase.java    |  19 +-
 24 files changed, 402 insertions(+), 463 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
index a348f94..0ea89e5 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Groups.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.console.wizards.any;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Map;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.ListUtils;
@@ -159,10 +158,10 @@ public class Groups extends WizardStep implements ICondition {
             }
 
             // set group names in membership TOs
-            Map<String, MembershipTO> membershipMap = GroupableRelatableTO.class.cast(anyTO).getMembershipMap();
             for (GroupTO group : groups) {
-                if (membershipMap.containsKey(group.getKey())) {
-                    membershipMap.get(group.getKey()).setGroupName(group.getName());
+                MembershipTO membership = GroupableRelatableTO.class.cast(anyTO).getMembership(group.getKey());
+                if (membership != null) {
+                    membership.setGroupName(group.getName());
                 }
             }
 
@@ -180,7 +179,7 @@ public class Groups extends WizardStep implements ICondition {
                             : groupRestClient.search(
                                     realm,
                                     SyncopeClient.getGroupSearchConditionBuilder().
-                                    isAssignable().and().is("name").equalTo(filter).query(),
+                                            isAssignable().and().is("name").equalTo(filter).query(),
                                     1, MAX_GROUP_LIST_CARDINALITY,
                                     new SortParam<>("name", true),
                                     null),
@@ -267,6 +266,6 @@ public class Groups extends WizardStep implements ICondition {
                 ? CollectionUtils.isNotEmpty(allDynRealms)
                 : CollectionUtils.isNotEmpty(allDynRealms) || CollectionUtils.isNotEmpty(allGroups))
                 && SyncopeConsoleApplication.get().getSecuritySettings().getAuthorizationStrategy().
-                isActionAuthorized(this, RENDER);
+                        isActionAuthorized(this, RENDER);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
----------------------------------------------------------------------
diff --git a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
index 56c6152..037b1fb 100644
--- a/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
+++ b/client/enduser/src/main/java/org/apache/syncope/client/enduser/resources/UserSelfUpdateResource.java
@@ -196,14 +196,13 @@ public class UserSelfUpdateResource extends BaseUserSelfResource {
     private void completeUserObject(final UserTO userTO, final UserTO selfTO) {
         // memberships plain and virtual attrs
         for (final MembershipTO updatedTOMemb : userTO.getMemberships()) {
-            MembershipTO oldTOMatchedMemb =
-                    IterableUtils.find(selfTO.getMemberships(), new Predicate<MembershipTO>() {
+            MembershipTO oldTOMatchedMemb = IterableUtils.find(selfTO.getMemberships(), new Predicate<MembershipTO>() {
 
-                        @Override
-                        public boolean evaluate(final MembershipTO oldTOMemb) {
-                            return updatedTOMemb.getGroupKey().equals(oldTOMemb.getGroupKey());
-                        }
-                    });
+                @Override
+                public boolean evaluate(final MembershipTO oldTOMemb) {
+                    return updatedTOMemb.getGroupKey().equals(oldTOMemb.getGroupKey());
+                }
+            });
             if (oldTOMatchedMemb != null) {
                 if (!updatedTOMemb.getPlainAttrs().isEmpty()) {
                     completeAttrs(updatedTOMemb.getPlainAttrs(), oldTOMatchedMemb.getPlainAttrs());

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/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 ba68a49..c0b211f 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
@@ -89,40 +89,8 @@ public final class AnyOperations {
         result.setGroup(updated.getGroupKey());
 
         // 1. plain attributes
-        Map<String, AttrTO> updatedAttrs = EntityTOUtils.buildAttrMap(updated.getPlainAttrs());
-        Map<String, AttrTO> originalAttrs = EntityTOUtils.buildAttrMap(original.getPlainAttrs());
-
         result.getPlainAttrs().clear();
-
-        if (!incremental) {
-            IterableUtils.forEach(CollectionUtils.subtract(originalAttrs.keySet(), updatedAttrs.keySet()),
-                    new Closure<String>() {
-
-                @Override
-                public void execute(final String schema) {
-                    result.getPlainAttrs().add(new AttrPatch.Builder().
-                            operation(PatchOperation.DELETE).
-                            attrTO(new AttrTO.Builder().schema(schema).build()).
-                            build());
-                }
-            });
-        }
-
-        for (AttrTO attrTO : updatedAttrs.values()) {
-            if (attrTO.getValues().isEmpty()) {
-                if (!incremental) {
-                    result.getPlainAttrs().add(new AttrPatch.Builder().
-                            operation(PatchOperation.DELETE).
-                            attrTO(new AttrTO.Builder().schema(attrTO.getSchema()).build()).
-                            build());
-                }
-            } else {
-                AttrPatch patch = new AttrPatch.Builder().operation(PatchOperation.ADD_REPLACE).attrTO(attrTO).build();
-                if (!patch.isEmpty()) {
-                    result.getPlainAttrs().add(patch);
-                }
-            }
-        }
+        result.getPlainAttrs().addAll(updated.getPlainAttrs());
 
         // 2. virtual attributes
         result.getVirAttrs().clear();
@@ -236,8 +204,10 @@ public final class AnyOperations {
         result.setName(replacePatchItem(updated.getName(), original.getName(), new StringReplacePatchItem()));
 
         // 2. relationships
-        Map<Pair<String, String>, RelationshipTO> updatedRels = updated.getRelationshipMap();
-        Map<Pair<String, String>, RelationshipTO> originalRels = original.getRelationshipMap();
+        Map<Pair<String, String>, RelationshipTO> updatedRels =
+                EntityTOUtils.buildRelationshipMap(updated.getRelationships());
+        Map<Pair<String, String>, RelationshipTO> originalRels =
+                EntityTOUtils.buildRelationshipMap(original.getRelationships());
 
         for (Map.Entry<Pair<String, String>, RelationshipTO> entry : updatedRels.entrySet()) {
             if (!originalRels.containsKey(entry.getKey())) {
@@ -256,8 +226,8 @@ public final class AnyOperations {
         }
 
         // 3. memberships
-        Map<String, MembershipTO> updatedMembs = updated.getMembershipMap();
-        Map<String, MembershipTO> originalMembs = original.getMembershipMap();
+        Map<String, MembershipTO> updatedMembs = EntityTOUtils.buildMembershipMap(updated.getMemberships());
+        Map<String, MembershipTO> originalMembs = EntityTOUtils.buildMembershipMap(original.getMemberships());
 
         for (Map.Entry<String, MembershipTO> entry : updatedMembs.entrySet()) {
             if (!originalMembs.containsKey(entry.getKey())) {
@@ -332,8 +302,10 @@ public final class AnyOperations {
         }
 
         // 5. relationships
-        Map<Pair<String, String>, RelationshipTO> updatedRels = updated.getRelationshipMap();
-        Map<Pair<String, String>, RelationshipTO> originalRels = original.getRelationshipMap();
+        Map<Pair<String, String>, RelationshipTO> updatedRels =
+                EntityTOUtils.buildRelationshipMap(updated.getRelationships());
+        Map<Pair<String, String>, RelationshipTO> originalRels =
+                EntityTOUtils.buildRelationshipMap(original.getRelationships());
 
         for (Map.Entry<Pair<String, String>, RelationshipTO> entry : updatedRels.entrySet()) {
             if (!originalRels.containsKey(entry.getKey())) {
@@ -352,8 +324,8 @@ public final class AnyOperations {
         }
 
         // 6. memberships
-        Map<String, MembershipTO> updatedMembs = updated.getMembershipMap();
-        Map<String, MembershipTO> originalMembs = original.getMembershipMap();
+        Map<String, MembershipTO> updatedMembs = EntityTOUtils.buildMembershipMap(updated.getMemberships());
+        Map<String, MembershipTO> originalMembs = EntityTOUtils.buildMembershipMap(original.getMemberships());
 
         for (Map.Entry<String, MembershipTO> entry : updatedMembs.entrySet()) {
             MembershipPatch membershipPatch = new MembershipPatch.Builder().
@@ -365,8 +337,7 @@ public final class AnyOperations {
                 omemb = originalMembs.get(entry.getKey());
             } else {
                 // create an empty one to generate the patch
-                omemb = new MembershipTO();
-                omemb.setGroupKey(entry.getKey());
+                omemb = new MembershipTO.Builder().group(entry.getKey()).build();
             }
 
             diff(entry.getValue(), omemb, membershipPatch, incremental);
@@ -553,19 +524,12 @@ public final class AnyOperations {
                 }
 
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    MembershipTO newMembershipTO = new MembershipTO();
-                    newMembershipTO.setGroupKey(membPatch.getGroup());
-
-                    if (memb == null) {
-                        for (AttrPatch attrPatch : membPatch.getPlainAttrs()) {
-                            newMembershipTO.getPlainAttrs().add(attrPatch.getAttrTO());
-                        }
-                    } else {
-                        newMembershipTO.getPlainAttrs().addAll(
-                                patch(EntityTOUtils.buildAttrMap(memb.getPlainAttrs()), membPatch.getPlainAttrs()));
-                    }
+                    MembershipTO newMembershipTO = new MembershipTO.Builder().group(membPatch.getGroup()).build();
+
+                    // 3. plain attributes
+                    newMembershipTO.getPlainAttrs().addAll(membPatch.getPlainAttrs());
 
-                    // 3. virtual attributes
+                    // 4. virtual attributes
                     newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
 
                     result.getMemberships().add(newMembershipTO);
@@ -619,19 +583,12 @@ public final class AnyOperations {
                 }
 
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    MembershipTO newMembershipTO = new MembershipTO();
-                    newMembershipTO.setGroupKey(membPatch.getGroup());
-
-                    if (memb == null) {
-                        for (AttrPatch attrPatch : membPatch.getPlainAttrs()) {
-                            newMembershipTO.getPlainAttrs().add(attrPatch.getAttrTO());
-                        }
-                    } else {
-                        newMembershipTO.getPlainAttrs().addAll(
-                                patch(EntityTOUtils.buildAttrMap(memb.getPlainAttrs()), membPatch.getPlainAttrs()));
-                    }
+                    MembershipTO newMembershipTO = new MembershipTO.Builder().group(membPatch.getGroup()).build();
+
+                    // 3. plain attributes
+                    newMembershipTO.getPlainAttrs().addAll(membPatch.getPlainAttrs());
 
-                    // 3. virtual attributes
+                    // 4. virtual attributes
                     newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
 
                     result.getMemberships().add(newMembershipTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java b/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
index d0c04bc..dfc0a1e 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/EntityTOUtils.java
@@ -19,11 +19,15 @@
 package org.apache.syncope.common.lib;
 
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 
 public final class EntityTOUtils {
 
@@ -43,7 +47,27 @@ public final class EntityTOUtils {
             result.put(attributeTO.getSchema(), attributeTO);
         }
 
-        return result;
+        return Collections.unmodifiableMap(result);
+    }
+
+    public static Map<Pair<String, String>, RelationshipTO> buildRelationshipMap(
+            final Collection<RelationshipTO> relationships) {
+
+        Map<Pair<String, String>, RelationshipTO> result = new HashMap<>(relationships.size());
+        for (RelationshipTO relationship : relationships) {
+            result.put(Pair.of(relationship.getType(), relationship.getRightKey()), relationship);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    public static Map<String, MembershipTO> buildMembershipMap(final Collection<MembershipTO> memberships) {
+        Map<String, MembershipTO> result = new HashMap<>(memberships.size());
+        for (MembershipTO membership : memberships) {
+            result.put(membership.getRightKey(), membership);
+        }
+
+        return Collections.unmodifiableMap(result);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
index 8487e1f..f2dcab5 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/MembershipPatch.java
@@ -29,7 +29,7 @@ import org.apache.syncope.common.lib.to.AttrTO;
 
 @XmlRootElement(name = "membershipPatch")
 @XmlType
-public class MembershipPatch extends AbstractPatch implements AttributablePatch {
+public class MembershipPatch extends AbstractPatch {
 
     private static final long serialVersionUID = -6783121761221554433L;
 
@@ -48,7 +48,7 @@ public class MembershipPatch extends AbstractPatch implements AttributablePatch
 
     private String group;
 
-    private final Set<AttrPatch> plainAttrs = new HashSet<>();
+    private final Set<AttrTO> plainAttrs = new HashSet<>();
 
     private final Set<AttrTO> virAttrs = new HashSet<>();
 
@@ -63,15 +63,13 @@ public class MembershipPatch extends AbstractPatch implements AttributablePatch
     @XmlElementWrapper(name = "plainAttrs")
     @XmlElement(name = "attribute")
     @JsonProperty("plainAttrs")
-    @Override
-    public Set<AttrPatch> getPlainAttrs() {
+    public Set<AttrTO> getPlainAttrs() {
         return plainAttrs;
     }
 
     @XmlElementWrapper(name = "virAttrs")
     @XmlElement(name = "attribute")
     @JsonProperty("virAttrs")
-    @Override
     public Set<AttrTO> getVirAttrs() {
         return virAttrs;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
index 81a445a..231504b 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
@@ -21,15 +21,13 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 
 @XmlRootElement(name = "anyObject")
 @XmlType
@@ -53,6 +51,18 @@ public class AnyObjectTO extends AnyTO implements GroupableRelatableTO {
         this.name = name;
     }
 
+    @JsonIgnore
+    @Override
+    public RelationshipTO getRelationship(final String type, final String rightKey) {
+        return IterableUtils.find(relationships, new Predicate<RelationshipTO>() {
+
+            @Override
+            public boolean evaluate(final RelationshipTO object) {
+                return type.equals(object.getType()) && rightKey.equals(object.getRightKey());
+            }
+        });
+    }
+
     @XmlElementWrapper(name = "relationships")
     @XmlElement(name = "relationship")
     @JsonProperty("relationships")
@@ -63,14 +73,14 @@ public class AnyObjectTO extends AnyTO implements GroupableRelatableTO {
 
     @JsonIgnore
     @Override
-    public Map<Pair<String, String>, RelationshipTO> getRelationshipMap() {
-        Map<Pair<String, String>, RelationshipTO> result = new HashMap<>(getRelationships().size());
-        for (RelationshipTO relationship : getRelationships()) {
-            result.put(Pair.of(relationship.getType(), relationship.getRightKey()), relationship);
-        }
-        result = Collections.unmodifiableMap(result);
-
-        return result;
+    public MembershipTO getMembership(final String groupKey) {
+        return IterableUtils.find(memberships, new Predicate<MembershipTO>() {
+
+            @Override
+            public boolean evaluate(final MembershipTO object) {
+                return groupKey.equals(object.getGroupKey());
+            }
+        });
     }
 
     @XmlElementWrapper(name = "memberships")
@@ -81,18 +91,6 @@ public class AnyObjectTO extends AnyTO implements GroupableRelatableTO {
         return memberships;
     }
 
-    @JsonIgnore
-    @Override
-    public Map<String, MembershipTO> getMembershipMap() {
-        Map<String, MembershipTO> result = new HashMap<>(getMemberships().size());
-        for (MembershipTO membership : getMemberships()) {
-            result.put(membership.getRightKey(), membership);
-        }
-        result = Collections.unmodifiableMap(result);
-
-        return result;
-    }
-
     @XmlElementWrapper(name = "dynGroups")
     @XmlElement(name = "role")
     @JsonProperty("dynGroups")

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableRelatableTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableRelatableTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableRelatableTO.java
index 09bc7e6..0dba26d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableRelatableTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableRelatableTO.java
@@ -19,18 +19,16 @@
 package org.apache.syncope.common.lib.to;
 
 import java.util.List;
-import java.util.Map;
-import org.apache.commons.lang3.tuple.Pair;
 
 public interface GroupableRelatableTO {
 
-    Map<String, MembershipTO> getMembershipMap();
+    MembershipTO getMembership(String groupKey);
 
     List<MembershipTO> getMemberships();
 
     List<String> getDynGroups();
 
-    Map<Pair<String, String>, RelationshipTO> getRelationshipMap();
+    RelationshipTO getRelationship(String type, String rightKey);
 
     List<RelationshipTO> getRelationships();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
index c575d90..40ebee5 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
@@ -22,18 +22,16 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "user")
@@ -197,6 +195,18 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
         this.mustChangePassword = mustChangePassword;
     }
 
+    @JsonIgnore
+    @Override
+    public RelationshipTO getRelationship(final String type, final String rightKey) {
+        return IterableUtils.find(relationships, new Predicate<RelationshipTO>() {
+
+            @Override
+            public boolean evaluate(final RelationshipTO object) {
+                return type.equals(object.getType()) && rightKey.equals(object.getRightKey());
+            }
+        });
+    }
+
     @XmlElementWrapper(name = "relationships")
     @XmlElement(name = "relationship")
     @JsonProperty("relationships")
@@ -207,12 +217,14 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
 
     @JsonIgnore
     @Override
-    public Map<Pair<String, String>, RelationshipTO> getRelationshipMap() {
-        Map<Pair<String, String>, RelationshipTO> result = new HashMap<>(getRelationships().size());
-        for (RelationshipTO relationship : getRelationships()) {
-            result.put(Pair.of(relationship.getType(), relationship.getRightKey()), relationship);
-        }
-        return Collections.unmodifiableMap(result);
+    public MembershipTO getMembership(final String groupKey) {
+        return IterableUtils.find(memberships, new Predicate<MembershipTO>() {
+
+            @Override
+            public boolean evaluate(final MembershipTO object) {
+                return groupKey.equals(object.getGroupKey());
+            }
+        });
     }
 
     @XmlElementWrapper(name = "memberships")
@@ -223,18 +235,6 @@ public class UserTO extends AnyTO implements GroupableRelatableTO {
         return memberships;
     }
 
-    @JsonIgnore
-    @Override
-    public Map<String, MembershipTO> getMembershipMap() {
-        Map<String, MembershipTO> result = new HashMap<>(getMemberships().size());
-        for (MembershipTO membership : getMemberships()) {
-            result.put(membership.getRightKey(), membership);
-        }
-        result = Collections.unmodifiableMap(result);
-
-        return result;
-    }
-
     @XmlElementWrapper(name = "dynGroups")
     @XmlElement(name = "role")
     @JsonProperty("dynGroups")

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormTO.java
index a73a8cc..0e80be6 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormTO.java
@@ -21,15 +21,14 @@ package org.apache.syncope.common.lib.to;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 import org.apache.syncope.common.lib.patch.UserPatch;
 
@@ -135,42 +134,21 @@ public class WorkflowFormTO extends AbstractBaseBean {
         this.userPatch = userPatch;
     }
 
+    @JsonIgnore
+    public WorkflowFormPropertyTO getProperty(final String id) {
+        return IterableUtils.find(properties, new Predicate<WorkflowFormPropertyTO>() {
+
+            @Override
+            public boolean evaluate(final WorkflowFormPropertyTO object) {
+                return id.equals(object.getId());
+            }
+        });
+    }
+
     @XmlElementWrapper(name = "workflowFormProperties")
     @XmlElement(name = "workflowFormProperty")
     @JsonProperty("workflowFormProperties")
     public List<WorkflowFormPropertyTO> getProperties() {
         return properties;
     }
-
-    public boolean addProperty(final WorkflowFormPropertyTO property) {
-        return properties.contains(property)
-                ? true
-                : properties.add(property);
-    }
-
-    public boolean removeProperty(final WorkflowFormPropertyTO property) {
-        return properties.remove(property);
-    }
-
-    @JsonIgnore
-    public Map<String, WorkflowFormPropertyTO> getPropertyMap() {
-        Map<String, WorkflowFormPropertyTO> result = new HashMap<>();
-        for (WorkflowFormPropertyTO prop : getProperties()) {
-            result.put(prop.getId(), prop);
-        }
-
-        return Collections.unmodifiableMap(result);
-    }
-
-    @JsonIgnore
-    public Map<String, String> getPropertiesForSubmit() {
-        Map<String, String> props = new HashMap<>();
-        for (WorkflowFormPropertyTO prop : getProperties()) {
-            if (prop.isWritable()) {
-                props.put(prop.getId(), prop.getValue());
-            }
-        }
-
-        return Collections.unmodifiableMap(props);
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
index 6b5e588..38c895e 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/MappingManagerImpl.java
@@ -626,7 +626,7 @@ public class MappingManagerImpl implements MappingManager {
                     if (groupableTO == null || group == null) {
                         anyTO.getPlainAttrs().add(attrTO);
                     } else {
-                        MembershipTO membership = groupableTO.getMembershipMap().get(group.getKey());
+                        MembershipTO membership = groupableTO.getMembership(group.getKey());
                         if (membership == null) {
                             membership = new MembershipTO.Builder().group(group.getKey(), group.getName()).build();
                             groupableTO.getMemberships().add(membership);
@@ -641,7 +641,7 @@ public class MappingManagerImpl implements MappingManager {
                     if (groupableTO == null || group == null) {
                         anyTO.getDerAttrs().add(attrTO);
                     } else {
-                        MembershipTO membership = groupableTO.getMembershipMap().get(group.getKey());
+                        MembershipTO membership = groupableTO.getMembership(group.getKey());
                         if (membership == null) {
                             membership = new MembershipTO.Builder().group(group.getKey(), group.getName()).build();
                             groupableTO.getMemberships().add(membership);
@@ -666,7 +666,7 @@ public class MappingManagerImpl implements MappingManager {
                     if (groupableTO == null || group == null) {
                         anyTO.getVirAttrs().add(attrTO);
                     } else {
-                        MembershipTO membership = groupableTO.getMembershipMap().get(group.getKey());
+                        MembershipTO membership = groupableTO.getMembership(group.getKey());
                         if (membership == null) {
                             membership = new MembershipTO.Builder().group(group.getKey(), group.getName()).build();
                             groupableTO.getMemberships().add(membership);

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/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 550f183..a2ba7e7 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
@@ -36,6 +36,7 @@ import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.MembershipPatch;
 import org.apache.syncope.common.lib.patch.RelationshipPatch;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -374,30 +375,27 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
                         anyObject.add(membership);
 
-                        for (AttrPatch patch : membPatch.getPlainAttrs()) {
-                            if (patch.getAttrTO() != null) {
-                                PlainSchema schema = getPlainSchema(patch.getAttrTO().getSchema());
-                                if (schema == null) {
-                                    LOG.debug("Invalid " + PlainSchema.class.getSimpleName()
-                                            + "{}, ignoring...", patch.getAttrTO().getSchema());
-                                } else {
-                                    APlainAttr attr = anyObject.getPlainAttr(schema.getKey(), membership);
-                                    if (attr == null) {
-                                        LOG.debug("No plain attribute found for {} and membership of {}",
-                                                schema, membership.getRightEnd());
-
-                                        if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
-                                            attr = anyUtils.newPlainAttr();
-                                            attr.setOwner(anyObject);
-                                            attr.setMembership(membership);
-                                            attr.setSchema(schema);
-                                            anyObject.add(attr);
-
-                                            processAttrPatch(
-                                                    anyObject, patch, schema, attr, anyUtils,
-                                                    resources, propByRes, invalidValues);
-                                        }
-                                    }
+                        for (AttrTO attrTO : membPatch.getPlainAttrs()) {
+                            PlainSchema schema = getPlainSchema(attrTO.getSchema());
+                            if (schema == null) {
+                                LOG.debug("Invalid " + PlainSchema.class.getSimpleName()
+                                        + "{}, ignoring...", attrTO.getSchema());
+                            } else {
+                                APlainAttr attr = anyObject.getPlainAttr(schema.getKey(), membership);
+                                if (attr == null) {
+                                    LOG.debug("No plain attribute found for {} and membership of {}",
+                                            schema, membership.getRightEnd());
+
+                                    attr = anyUtils.newPlainAttr();
+                                    attr.setOwner(anyObject);
+                                    attr.setMembership(membership);
+                                    attr.setSchema(schema);
+                                    anyObject.add(attr);
+
+                                    AttrPatch patch = new AttrPatch.Builder().attrTO(attrTO).build();
+                                    processAttrPatch(
+                                            anyObject, patch, schema, attr, anyUtils,
+                                            resources, propByRes, invalidValues);
                                 }
                             }
                         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/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 54c9983..38c411b 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
@@ -40,6 +40,7 @@ import org.apache.syncope.common.lib.patch.PasswordPatch;
 import org.apache.syncope.common.lib.patch.RelationshipPatch;
 import org.apache.syncope.common.lib.patch.StringPatchItem;
 import org.apache.syncope.common.lib.patch.UserPatch;
+import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -476,30 +477,27 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
 
                         user.add(membership);
 
-                        for (AttrPatch patch : membPatch.getPlainAttrs()) {
-                            if (patch.getAttrTO() != null) {
-                                PlainSchema schema = getPlainSchema(patch.getAttrTO().getSchema());
-                                if (schema == null) {
-                                    LOG.debug("Invalid " + PlainSchema.class.getSimpleName()
-                                            + "{}, ignoring...", patch.getAttrTO().getSchema());
-                                } else {
-                                    UPlainAttr attr = user.getPlainAttr(schema.getKey(), membership);
-                                    if (attr == null) {
-                                        LOG.debug("No plain attribute found for {} and membership of {}",
-                                                schema, membership.getRightEnd());
-
-                                        if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
-                                            attr = anyUtils.newPlainAttr();
-                                            attr.setOwner(user);
-                                            attr.setMembership(membership);
-                                            attr.setSchema(schema);
-                                            user.add(attr);
-
-                                            processAttrPatch(
-                                                    user, patch, schema, attr, anyUtils,
-                                                    resources, propByRes, invalidValues);
-                                        }
-                                    }
+                        for (AttrTO attrTO : membPatch.getPlainAttrs()) {
+                            PlainSchema schema = getPlainSchema(attrTO.getSchema());
+                            if (schema == null) {
+                                LOG.debug("Invalid " + PlainSchema.class.getSimpleName()
+                                        + "{}, ignoring...", attrTO.getSchema());
+                            } else {
+                                UPlainAttr attr = user.getPlainAttr(schema.getKey(), membership);
+                                if (attr == null) {
+                                    LOG.debug("No plain attribute found for {} and membership of {}",
+                                            schema, membership.getRightEnd());
+
+                                    attr = anyUtils.newPlainAttr();
+                                    attr.setOwner(user);
+                                    attr.setMembership(membership);
+                                    attr.setSchema(schema);
+                                    user.add(attr);
+
+                                    AttrPatch patch = new AttrPatch.Builder().attrTO(attrTO).build();
+                                    processAttrPatch(
+                                            user, patch, schema, attr, anyUtils,
+                                            resources, propByRes, invalidValues);
                                 }
                             }
                         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
index 69485e4..d56f651 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/TemplateUtils.java
@@ -18,17 +18,16 @@
  */
 package org.apache.syncope.core.provisioning.java.utils;
 
-import java.util.List;
 import java.util.Map;
 import org.apache.commons.jexl3.MapContext;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -108,22 +107,18 @@ public class TemplateUtils {
         anyTO.getAuxClasses().addAll(template.getAuxClasses());
     }
 
-    private void fillRelationships(final Map<Pair<String, String>, RelationshipTO> anyRelMap,
-            final List<RelationshipTO> anyRels, final List<RelationshipTO> templateRels) {
-
-        for (RelationshipTO memb : templateRels) {
-            if (!anyRelMap.containsKey(Pair.of(memb.getRightType(), memb.getRightKey()))) {
-                anyRels.add(memb);
+    private void fillRelationships(final GroupableRelatableTO any, final GroupableRelatableTO template) {
+        for (RelationshipTO relationship : template.getRelationships()) {
+            if (any.getRelationship(relationship.getRightKey(), relationship.getRightKey()) == null) {
+                any.getRelationships().add(relationship);
             }
         }
     }
 
-    private void fillMemberships(final Map<String, MembershipTO> anyMembMap,
-            final List<MembershipTO> anyMembs, final List<MembershipTO> templateMembs) {
-
-        for (MembershipTO memb : templateMembs) {
-            if (!anyMembMap.containsKey(memb.getRightKey())) {
-                anyMembs.add(memb);
+    private void fillMemberships(final GroupableRelatableTO any, final GroupableRelatableTO template) {
+        for (MembershipTO membership : template.getMemberships()) {
+            if (any.getMembership(membership.getGroupKey()) == null) {
+                any.getMemberships().add(membership);
             }
         }
     }
@@ -135,10 +130,8 @@ public class TemplateUtils {
             fill(anyTO, template);
 
             if (template instanceof AnyObjectTO) {
-                fillRelationships(((AnyObjectTO) anyTO).getRelationshipMap(),
-                        ((AnyObjectTO) anyTO).getRelationships(), ((AnyObjectTO) template).getRelationships());
-                fillMemberships(((AnyObjectTO) anyTO).getMembershipMap(),
-                        ((AnyObjectTO) anyTO).getMemberships(), ((AnyObjectTO) template).getMemberships());
+                fillRelationships((GroupableRelatableTO) anyTO, ((GroupableRelatableTO) template));
+                fillMemberships((GroupableRelatableTO) anyTO, ((GroupableRelatableTO) template));
             } else if (template instanceof UserTO) {
                 if (StringUtils.isNotBlank(((UserTO) template).getUsername())) {
                     String evaluated = JexlUtils.evaluate(((UserTO) template).getUsername(), anyTO, new MapContext());
@@ -154,10 +147,8 @@ public class TemplateUtils {
                     }
                 }
 
-                fillRelationships(((UserTO) anyTO).getRelationshipMap(),
-                        ((UserTO) anyTO).getRelationships(), ((UserTO) template).getRelationships());
-                fillMemberships(((UserTO) anyTO).getMembershipMap(),
-                        ((UserTO) anyTO).getMemberships(), ((UserTO) template).getMemberships());
+                fillRelationships((GroupableRelatableTO) anyTO, ((GroupableRelatableTO) template));
+                fillMemberships((GroupableRelatableTO) anyTO, ((GroupableRelatableTO) template));
             } else if (template instanceof GroupTO) {
                 if (StringUtils.isNotBlank(((GroupTO) template).getName())) {
                     String evaluated = JexlUtils.evaluate(((GroupTO) template).getName(), anyTO, new MapContext());

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/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 21727fd..8ce6d1b 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
@@ -535,7 +535,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
             propertyTO.setId(prop.getPropertyId());
             propertyTO.setName(prop.getPropertyId());
             propertyTO.setValue(prop.getPropertyValue());
-            formTO.addProperty(propertyTO);
+            formTO.getProperties().add(propertyTO);
         }
 
         return formTO;
@@ -574,7 +574,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
                 propertyTO.getEnumValues().putAll((Map<String, String>) fProp.getType().getInformation("values"));
             }
 
-            formTO.addProperty(propertyTO);
+            formTO.getProperties().add(propertyTO);
         }
 
         return formTO;
@@ -712,6 +712,17 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
         return getFormTO(task, checked.getValue());
     }
 
+    private Map<String, String> getPropertiesForSubmit(final WorkflowFormTO form) {
+        Map<String, String> props = new HashMap<>();
+        for (WorkflowFormPropertyTO prop : form.getProperties()) {
+            if (prop.isWritable()) {
+                props.put(prop.getId(), prop.getValue());
+            }
+        }
+
+        return Collections.unmodifiableMap(props);
+    }
+
     @Override
     public WorkflowResult<UserPatch> submitForm(final WorkflowFormTO form) {
         String authUser = AuthContextUtils.getUsername();
@@ -729,7 +740,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
 
         Set<String> preTasks = getPerformedTasks(user);
         try {
-            engine.getFormService().submitTaskFormData(form.getTaskId(), form.getPropertiesForSubmit());
+            engine.getFormService().submitTaskFormData(form.getTaskId(), getPropertiesForSubmit(form));
             engine.getRuntimeService().setVariable(user.getWorkflowId(), FORM_SUBMITTER, authUser);
         } catch (ActivitiException e) {
             throwException(e, "While submitting form for task " + form.getTaskId());

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
index ffd55b1..a3251fe 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AnyObjectITCase.java
@@ -92,7 +92,7 @@ public class AnyObjectITCase extends AbstractITCase {
         anyObjectTO.setRealm("/even/two");
 
         anyObjectTO = createAnyObject(anyObjectTO).getEntity();
-        assertTrue(anyObjectTO.getMembershipMap().containsKey("034740a9-fa10-453b-af37-dc7897e98fb1"));
+        assertNotNull(anyObjectTO.getMembership("034740a9-fa10-453b-af37-dc7897e98fb1"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
index 50fa799..01df4f5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java
@@ -60,7 +60,6 @@ import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
@@ -524,10 +523,7 @@ public class AuthenticationITCase extends AbstractITCase {
         // 3. approve user
         WorkflowFormTO form = userWorkflowService.getFormForUser(userTO.getKey());
         form = userWorkflowService.claimForm(form.getTaskId());
-        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
-        props.get("approve").setValue(Boolean.TRUE.toString());
-        form.getProperties().clear();
-        form.getProperties().addAll(props.values());
+        form.getProperty("approve").setValue(Boolean.TRUE.toString());
         userTO = userWorkflowService.submitForm(form);
         assertNotNull(userTO);
         assertEquals("active", userTO.getStatus());

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
index e24fc66..8b7b0f8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/GroupITCase.java
@@ -187,8 +187,8 @@ public class GroupITCase extends AbstractITCase {
         UserTO userTO = userService.read("1417acbe-cbf6-4277-9372-e75e04f97000");
         assertNotNull(userTO);
 
-        assertTrue(userTO.getMembershipMap().containsKey("37d15e4c-cdc1-460b-a591-8505c8133806"));
-        assertFalse(userTO.getMembershipMap().containsKey("29f96485-729e-4d31-88a1-6fc60e4677f3"));
+        assertNotNull(userTO.getMembership("37d15e4c-cdc1-460b-a591-8505c8133806"));
+        assertNull(userTO.getMembership("29f96485-729e-4d31-88a1-6fc60e4677f3"));
 
         GroupService groupService2 = clientFactory.create("rossini", ADMIN_PWD).getService(GroupService.class);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/IdentityRecertificationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/IdentityRecertificationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/IdentityRecertificationITCase.java
index 80eae86..3a9ee36 100755
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/IdentityRecertificationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/IdentityRecertificationITCase.java
@@ -39,7 +39,7 @@ public class IdentityRecertificationITCase extends AbstractTaskITCase {
         assertFalse(forms.isEmpty());
         for (WorkflowFormTO form : forms) {
             userWorkflowService.claimForm(form.getTaskId());
-            WorkflowFormPropertyTO approve = form.getPropertyMap().get("approve");
+            WorkflowFormPropertyTO approve = form.getProperty("approve");
             approve.setValue("true");
             userWorkflowService.submitForm(form);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
index e150bb2..3c7f929 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
@@ -113,7 +113,7 @@ public class MembershipITCase extends AbstractITCase {
 
             // 2. verify that 'aLong' is correctly populated for user's membership
             assertEquals(1, user.getMemberships().size());
-            membership = user.getMembershipMap().get("034740a9-fa10-453b-af37-dc7897e98fb1");
+            membership = user.getMembership("034740a9-fa10-453b-af37-dc7897e98fb1");
             assertNotNull(membership);
             assertEquals(1, membership.getPlainAttr("aLong").getValues().size());
             assertEquals("1977", membership.getPlainAttr("aLong").getValues().get(0));
@@ -130,10 +130,10 @@ public class MembershipITCase extends AbstractITCase {
                     attrTO(new AttrTO.Builder().schema("aLong").value("1977").build()).build());
 
             MembershipPatch membershipPatch = new MembershipPatch.Builder().group(membership.getGroupKey()).build();
-            membershipPatch.getPlainAttrs().add(new AttrPatch.Builder().
-                    attrTO(new AttrTO.Builder().schema("aLong").value("1976").build()).build());
-            membershipPatch.getPlainAttrs().add(new AttrPatch.Builder().
-                    attrTO(new AttrTO.Builder().schema("ctype").value("membership type").build()).build());
+            membershipPatch.getPlainAttrs().add(
+                    new AttrTO.Builder().schema("aLong").value("1976").build());
+            membershipPatch.getPlainAttrs().add(
+                    new AttrTO.Builder().schema("ctype").value("membership type").build());
             userPatch.getMemberships().add(membershipPatch);
 
             user = updateUser(userPatch).getEntity();
@@ -145,7 +145,7 @@ public class MembershipITCase extends AbstractITCase {
 
             // 5. verify that 'aLong' is correctly populated for user's membership
             assertEquals(1, user.getMemberships().size());
-            membership = user.getMembershipMap().get("034740a9-fa10-453b-af37-dc7897e98fb1");
+            membership = user.getMembership("034740a9-fa10-453b-af37-dc7897e98fb1");
             assertNotNull(membership);
             assertEquals(1, membership.getPlainAttr("aLong").getValues().size());
             assertEquals("1976", membership.getPlainAttr("aLong").getValues().get(0));
@@ -211,7 +211,7 @@ public class MembershipITCase extends AbstractITCase {
 
         // verify that 'aLong' is correctly populated for user's membership
         assertEquals(1, user.getMemberships().size());
-        membership = user.getMembershipMap().get(groupTO.getKey());
+        membership = user.getMembership(groupTO.getKey());
         assertNotNull(membership);
         assertEquals(1, membership.getPlainAttr("aLong").getValues().size());
         assertEquals("1454", membership.getPlainAttr("aLong").getValues().get(0));

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
index 549f4e0..f1d1a22 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
@@ -31,32 +31,16 @@ import javax.sql.DataSource;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.AbstractTaskTO;
-import org.apache.syncope.common.lib.to.AnyTypeClassTO;
-import org.apache.syncope.common.lib.to.MappingItemTO;
-import org.apache.syncope.common.lib.to.MappingTO;
-import org.apache.syncope.common.lib.to.NotificationTO;
-import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.to.PagedResult;
-import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.PushTaskTO;
-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.ExecTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
-import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.lib.types.TaskType;
-import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
-import org.apache.syncope.common.rest.api.service.NotificationService;
-import org.apache.syncope.common.rest.api.service.ResourceService;
 import org.apache.syncope.common.rest.api.service.TaskService;
-import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -297,136 +281,4 @@ public class PushTaskITCase extends AbstractTaskITCase {
         assertNotNull(getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, "ou=even,o=isp"));
         assertNotNull(getLdapRemoteObject(RESOURCE_LDAP_ADMIN_DN, RESOURCE_LDAP_ADMIN_PWD, "ou=two,ou=even,o=isp"));
     }
-
-    @Test
-    public void issueSYNCOPE598() {
-        // create a new group schema
-        PlainSchemaTO schemaTO = new PlainSchemaTO();
-        schemaTO.setKey("LDAPGroupName" + getUUIDString());
-        schemaTO.setType(AttrSchemaType.String);
-        schemaTO.setMandatoryCondition("true");
-
-        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
-        assertNotNull(schemaTO);
-
-        AnyTypeClassTO typeClass = new AnyTypeClassTO();
-        typeClass.setKey("SYNCOPE-598" + getUUIDString());
-        typeClass.getPlainSchemas().add(schemaTO.getKey());
-        anyTypeClassService.create(typeClass);
-
-        // create a new sample group
-        GroupTO groupTO = new GroupTO();
-        groupTO.setName("all" + getUUIDString());
-        groupTO.setRealm("/even");
-        groupTO.getAuxClasses().add(typeClass.getKey());
-
-        groupTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "all"));
-
-        groupTO = createGroup(groupTO).getEntity();
-        assertNotNull(groupTO);
-
-        String resourceName = "resource-ldap-grouponly";
-        ResourceTO newResourceTO = null;
-
-        try {
-            // Create resource ad-hoc
-            ResourceTO resourceTO = new ResourceTO();
-            resourceTO.setKey(resourceName);
-            resourceTO.setConnector("74141a3b-0762-4720-a4aa-fc3e374ef3ef");
-
-            ProvisionTO provisionTO = new ProvisionTO();
-            provisionTO.setAnyType(AnyTypeKind.GROUP.name());
-            provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
-            provisionTO.getAuxClasses().add(typeClass.getKey());
-            resourceTO.getProvisions().add(provisionTO);
-
-            MappingTO mapping = new MappingTO();
-            provisionTO.setMapping(mapping);
-
-            MappingItemTO item = new MappingItemTO();
-            item.setExtAttrName("cn");
-            item.setIntAttrName(schemaTO.getKey());
-            item.setConnObjectKey(true);
-            item.setPurpose(MappingPurpose.BOTH);
-            mapping.setConnObjectKeyItem(item);
-
-            mapping.setConnObjectLink("'cn=' + " + schemaTO.getKey() + " + ',ou=groups,o=isp'");
-
-            Response response = resourceService.create(resourceTO);
-            newResourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
-            assertNotNull(newResourceTO);
-            assertNull(newResourceTO.getProvision(AnyTypeKind.USER.name()));
-            assertNotNull(newResourceTO.getProvision(AnyTypeKind.GROUP.name()).getMapping());
-
-            // create push task ad-hoc
-            PushTaskTO task = new PushTaskTO();
-            task.setName("issueSYNCOPE598");
-            task.setActive(true);
-            task.setResource(resourceName);
-            task.setPerformCreate(true);
-            task.setPerformDelete(true);
-            task.setPerformUpdate(true);
-            task.setUnmatchingRule(UnmatchingRule.ASSIGN);
-            task.setMatchingRule(MatchingRule.UPDATE);
-            task.getFilters().put(AnyTypeKind.GROUP.name(),
-                    SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo(groupTO.getName()).query());
-
-            response = taskService.create(task);
-            PushTaskTO push = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
-            assertNotNull(push);
-
-            // execute the new task
-            ExecTO exec = execProvisioningTask(taskService, push.getKey(), 50, false);
-            assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(exec.getStatus()));
-        } finally {
-            groupService.delete(groupTO.getKey());
-            if (newResourceTO != null) {
-                resourceService.delete(resourceName);
-            }
-        }
-    }
-
-    @Test
-    public void issueSYNCOPE648() {
-        // 1. Create Push Task
-        PushTaskTO task = new PushTaskTO();
-        task.setName("Test create Push");
-        task.setActive(true);
-        task.setResource(RESOURCE_NAME_LDAP);
-        task.getFilters().put(AnyTypeKind.USER.name(),
-                SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("_NO_ONE_").query());
-        task.getFilters().put(AnyTypeKind.GROUP.name(),
-                SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("citizen").query());
-        task.setMatchingRule(MatchingRule.IGNORE);
-        task.setUnmatchingRule(UnmatchingRule.IGNORE);
-
-        Response response = taskService.create(task);
-        PushTaskTO actual = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
-        assertNotNull(actual);
-
-        // 2. Create notification
-        NotificationTO notification = new NotificationTO();
-        notification.setTraceLevel(TraceLevel.FAILURES);
-        notification.getEvents().add("[PushTask]:[group]:[resource-ldap]:[matchingrule_ignore]:[SUCCESS]");
-        notification.getEvents().add("[PushTask]:[group]:[resource-ldap]:[unmatchingrule_ignore]:[SUCCESS]");
-
-        notification.getStaticRecipients().add("issueyncope648@syncope.apache.org");
-        notification.setSelfAsRecipient(false);
-        notification.setRecipientAttrName("email");
-
-        notification.setSender("syncope648@syncope.apache.org");
-        String subject = "Test notification";
-        notification.setSubject(subject);
-        notification.setTemplate("optin");
-        notification.setActive(true);
-
-        Response responseNotification = notificationService.create(notification);
-        notification = getObject(responseNotification.getLocation(), NotificationService.class, NotificationTO.class);
-        assertNotNull(notification);
-
-        execProvisioningTask(taskService, actual.getKey(), 50, false);
-
-        NotificationTaskTO taskTO = findNotificationTask(notification.getKey(), 50);
-        assertNotNull(taskTO);
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskIssuesITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskIssuesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskIssuesITCase.java
new file mode 100644
index 0000000..95d648e
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskIssuesITCase.java
@@ -0,0 +1,185 @@
+/*
+ * 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.fit.core;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import javax.ws.rs.core.Response;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
+import org.apache.syncope.common.lib.to.MappingTO;
+import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.to.PlainSchemaTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+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.ExecTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.MatchingRule;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
+import org.apache.syncope.common.rest.api.service.NotificationService;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+import org.apache.syncope.common.rest.api.service.TaskService;
+import org.identityconnectors.framework.common.objects.ObjectClass;
+import org.junit.Test;
+
+public class PushTaskIssuesITCase extends AbstractTaskITCase {
+
+    @Test
+    public void issueSYNCOPE598() {
+        // create a new group schema
+        PlainSchemaTO schemaTO = new PlainSchemaTO();
+        schemaTO.setKey("LDAPGroupName" + getUUIDString());
+        schemaTO.setType(AttrSchemaType.String);
+        schemaTO.setMandatoryCondition("true");
+
+        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertNotNull(schemaTO);
+
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("SYNCOPE-598" + getUUIDString());
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
+        // create a new sample group
+        GroupTO groupTO = new GroupTO();
+        groupTO.setName("all" + getUUIDString());
+        groupTO.setRealm("/even");
+        groupTO.getAuxClasses().add(typeClass.getKey());
+
+        groupTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "all"));
+
+        groupTO = createGroup(groupTO).getEntity();
+        assertNotNull(groupTO);
+
+        String resourceName = "resource-ldap-grouponly";
+        ResourceTO newResourceTO = null;
+
+        try {
+            // Create resource ad-hoc
+            ResourceTO resourceTO = new ResourceTO();
+            resourceTO.setKey(resourceName);
+            resourceTO.setConnector("74141a3b-0762-4720-a4aa-fc3e374ef3ef");
+
+            ProvisionTO provisionTO = new ProvisionTO();
+            provisionTO.setAnyType(AnyTypeKind.GROUP.name());
+            provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
+            provisionTO.getAuxClasses().add(typeClass.getKey());
+            resourceTO.getProvisions().add(provisionTO);
+
+            MappingTO mapping = new MappingTO();
+            provisionTO.setMapping(mapping);
+
+            MappingItemTO item = new MappingItemTO();
+            item.setExtAttrName("cn");
+            item.setIntAttrName(schemaTO.getKey());
+            item.setConnObjectKey(true);
+            item.setPurpose(MappingPurpose.BOTH);
+            mapping.setConnObjectKeyItem(item);
+
+            mapping.setConnObjectLink("'cn=' + " + schemaTO.getKey() + " + ',ou=groups,o=isp'");
+
+            Response response = resourceService.create(resourceTO);
+            newResourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
+            assertNotNull(newResourceTO);
+            assertNull(newResourceTO.getProvision(AnyTypeKind.USER.name()));
+            assertNotNull(newResourceTO.getProvision(AnyTypeKind.GROUP.name()).getMapping());
+
+            // create push task ad-hoc
+            PushTaskTO task = new PushTaskTO();
+            task.setName("issueSYNCOPE598");
+            task.setActive(true);
+            task.setResource(resourceName);
+            task.setPerformCreate(true);
+            task.setPerformDelete(true);
+            task.setPerformUpdate(true);
+            task.setUnmatchingRule(UnmatchingRule.ASSIGN);
+            task.setMatchingRule(MatchingRule.UPDATE);
+            task.getFilters().put(AnyTypeKind.GROUP.name(),
+                    SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo(groupTO.getName()).query());
+
+            response = taskService.create(task);
+            PushTaskTO push = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
+            assertNotNull(push);
+
+            // execute the new task
+            ExecTO exec = execProvisioningTask(taskService, push.getKey(), 50, false);
+            assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(exec.getStatus()));
+        } finally {
+            groupService.delete(groupTO.getKey());
+            if (newResourceTO != null) {
+                resourceService.delete(resourceName);
+            }
+        }
+    }
+
+    @Test
+    public void issueSYNCOPE648() {
+        // 1. Create Push Task
+        PushTaskTO task = new PushTaskTO();
+        task.setName("Test create Push");
+        task.setActive(true);
+        task.setResource(RESOURCE_NAME_LDAP);
+        task.getFilters().put(AnyTypeKind.USER.name(),
+                SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("_NO_ONE_").query());
+        task.getFilters().put(AnyTypeKind.GROUP.name(),
+                SyncopeClient.getGroupSearchConditionBuilder().is("name").equalTo("citizen").query());
+        task.setMatchingRule(MatchingRule.IGNORE);
+        task.setUnmatchingRule(UnmatchingRule.IGNORE);
+
+        Response response = taskService.create(task);
+        PushTaskTO actual = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
+        assertNotNull(actual);
+
+        // 2. Create notification
+        NotificationTO notification = new NotificationTO();
+        notification.setTraceLevel(TraceLevel.FAILURES);
+        notification.getEvents().add("[PushTask]:[group]:[resource-ldap]:[matchingrule_ignore]:[SUCCESS]");
+        notification.getEvents().add("[PushTask]:[group]:[resource-ldap]:[unmatchingrule_ignore]:[SUCCESS]");
+
+        notification.getStaticRecipients().add("issueyncope648@syncope.apache.org");
+        notification.setSelfAsRecipient(false);
+        notification.setRecipientAttrName("email");
+
+        notification.setSender("syncope648@syncope.apache.org");
+        String subject = "Test notification";
+        notification.setSubject(subject);
+        notification.setTemplate("optin");
+        notification.setActive(true);
+
+        Response responseNotification = notificationService.create(notification);
+        notification = getObject(responseNotification.getLocation(), NotificationService.class, NotificationTO.class);
+        assertNotNull(notification);
+
+        execProvisioningTask(taskService, actual.getKey(), 50, false);
+
+        NotificationTaskTO taskTO = findNotificationTask(notification.getKey(), 50);
+        assertNotNull(taskTO);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
index 356d98a..3ba48e8 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
@@ -39,7 +39,6 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.collections4.MapUtils;
 import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.time.DateFormatUtils;
-import org.apache.commons.lang3.time.FastDateFormat;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.jaxrs.client.WebClient;
 import org.apache.syncope.client.lib.SyncopeClient;
@@ -90,8 +89,6 @@ import org.junit.Test;
 
 public class UserITCase extends AbstractITCase {
 
-    private static final FastDateFormat DATE_FORMAT = DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT;
-
     private boolean getBooleanAttribute(final ConnObjectTO connObjectTO, final String attrName) {
         return Boolean.parseBoolean(connObjectTO.getAttr(attrName).getValues().get(0));
     }
@@ -112,8 +109,9 @@ public class UserITCase extends AbstractITCase {
         userTO.getPlainAttrs().add(attrTO("ctype", "a type"));
         userTO.getPlainAttrs().add(attrTO("userId", email));
         userTO.getPlainAttrs().add(attrTO("email", email));
-        userTO.getPlainAttrs().add(attrTO("loginDate", DATE_FORMAT.format(new Date())));
-        userTO.getDerAttrs().add(attrTO("cn", null));
+        userTO.getPlainAttrs().add(
+                attrTO("loginDate", DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT.format(new Date())));
+
         return userTO;
     }
 
@@ -445,18 +443,6 @@ public class UserITCase extends AbstractITCase {
     @Test
     public void list() {
         PagedResult<UserTO> users = userService.search(
-                new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).build());
-        assertNotNull(users);
-        assertFalse(users.getResult().isEmpty());
-
-        for (UserTO user : users.getResult()) {
-            assertNotNull(user);
-        }
-    }
-
-    @Test
-    public void paginatedList() {
-        PagedResult<UserTO> users = userService.search(
                 new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).page(1).size(2).build());
         assertNotNull(users);
         assertFalse(users.getResult().isEmpty());
@@ -489,13 +475,6 @@ public class UserITCase extends AbstractITCase {
     }
 
     @Test
-    public void readWithMailAddressAsUserName() {
-        UserTO userTO = createUser(getUniqueSampleTO("mail@domain.org")).getEntity();
-        userTO = userService.read(userTO.getKey());
-        assertNotNull(userTO);
-    }
-
-    @Test
     public void updateWithoutPassword() {
         UserTO userTO = getUniqueSampleTO("updatewithout@password.com");
 
@@ -1000,10 +979,6 @@ public class UserITCase extends AbstractITCase {
         UserTO userTO = getUniqueSampleTO("mpurpose@apache.org");
         userTO.getAuxClasses().add("csv");
 
-        AttrTO csvuserid = new AttrTO();
-        csvuserid.setSchema("csvuserid");
-        userTO.getDerAttrs().add(csvuserid);
-
         userTO.getResources().clear();
         userTO.getResources().add(RESOURCE_NAME_CSV);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java
index 5f8661b..aba92ef 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java
@@ -46,7 +46,6 @@ import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -127,10 +126,7 @@ public class UserSelfITCase extends AbstractITCase {
         // now approve and verify that propagation has happened
         WorkflowFormTO form = userWorkflowService.getFormForUser(userTO.getKey());
         form = userWorkflowService.claimForm(form.getTaskId());
-        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
-        props.get("approve").setValue(Boolean.TRUE.toString());
-        form.getProperties().clear();
-        form.getProperties().addAll(props.values());
+        form.getProperty("approve").setValue(Boolean.TRUE.toString());
         userTO = userWorkflowService.submitForm(form);
         assertNotNull(userTO);
         assertEquals("active", userTO.getStatus());
@@ -228,10 +224,7 @@ public class UserSelfITCase extends AbstractITCase {
         // 3. approve self-update as admin
         WorkflowFormTO form = userWorkflowService.getFormForUser(updated.getKey());
         form = userWorkflowService.claimForm(form.getTaskId());
-        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
-        props.get("approve").setValue(Boolean.TRUE.toString());
-        form.getProperties().clear();
-        form.getProperties().addAll(props.values());
+        form.getProperty("approve").setValue(Boolean.TRUE.toString());
         updated = userWorkflowService.submitForm(form);
         assertNotNull(updated);
         assertEquals("active", updated.getStatus());

http://git-wip-us.apache.org/repos/asf/syncope/blob/653b88a7/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
index 896b922..e21929e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserWorkflowITCase.java
@@ -29,7 +29,6 @@ import static org.junit.Assert.fail;
 
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import javax.sql.DataSource;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.lib.SyncopeClient;
@@ -41,7 +40,6 @@ import org.apache.syncope.common.lib.patch.UserPatch;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.UserTO;
-import org.apache.syncope.common.lib.to.WorkflowFormPropertyTO;
 import org.apache.syncope.common.lib.to.WorkflowFormTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
@@ -120,11 +118,8 @@ public class UserWorkflowITCase extends AbstractITCase {
         assertNotNull(form.getOwner());
 
         // 5. reject user
-        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
-        props.get("approve").setValue(Boolean.FALSE.toString());
-        props.get("rejectReason").setValue("I don't like him.");
-        form.getProperties().clear();
-        form.getProperties().addAll(props.values());
+        form.getProperty("approve").setValue(Boolean.FALSE.toString());
+        form.getProperty("rejectReason").setValue("I don't like him.");
         userTO = userService3.submitForm(form);
         assertNotNull(userTO);
         assertEquals("rejected", userTO.getStatus());
@@ -196,10 +191,7 @@ public class UserWorkflowITCase extends AbstractITCase {
         assertNotNull(form.getOwner());
 
         // 5. approve user (and verify that propagation occurred)
-        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
-        props.get("approve").setValue(Boolean.TRUE.toString());
-        form.getProperties().clear();
-        form.getProperties().addAll(props.values());
+        form.getProperty("approve").setValue(Boolean.TRUE.toString());
         userTO = userWorkflowService.submitForm(form);
         assertNotNull(userTO);
         assertEquals("active", userTO.getStatus());
@@ -300,10 +292,7 @@ public class UserWorkflowITCase extends AbstractITCase {
         assertNotNull(form);
 
         // 5. approve user
-        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
-        props.get("approve").setValue(Boolean.TRUE.toString());
-        form.getProperties().clear();
-        form.getProperties().addAll(props.values());
+        form.getProperty("approve").setValue(Boolean.TRUE.toString());
 
         // 6. submit approve
         userTO = userWorkflowService.submitForm(form);