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 2016/05/31 15:59:18 UTC

[2/4] syncope git commit: [SYNCOPE-862] Preliminary work

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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 0e19eb7..d129dcb 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
@@ -29,7 +29,9 @@ import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.patch.AnyObjectPatch;
+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;
@@ -46,14 +48,17 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -74,7 +79,9 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
     @Transactional(readOnly = true)
     @Override
     public AnyObjectTO getAnyObjectTO(final String key) {
-        return getAnyObjectTO(anyObjectDAO.authFind(key), true);
+        return SyncopeConstants.UUID_PATTERN.matcher(key).matches()
+                ? getAnyObjectTO(anyObjectDAO.authFind(key), true)
+                : getAnyObjectTO(anyObjectDAO.authFindByName(key), true);
     }
 
     @Override
@@ -84,12 +91,15 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
         BeanUtils.copyProperties(anyObject, anyObjectTO, IGNORE_PROPERTIES);
 
-        Map<DerSchema, String> derAttrValues = derAttrHandler.getValues(anyObject);
         Map<VirSchema, List<String>> virAttrValues = details
-                ? virAttrHander.getValues(anyObject)
+                ? virAttrHandler.getValues(anyObject)
                 : Collections.<VirSchema, List<String>>emptyMap();
-        fillTO(anyObjectTO, anyObject.getRealm().getFullPath(), anyObject.getAuxClasses(),
-                anyObject.getPlainAttrs(), derAttrValues, virAttrValues, anyObjectDAO.findAllResources(anyObject));
+        fillTO(anyObjectTO, anyObject.getRealm().getFullPath(),
+                anyObject.getAuxClasses(),
+                anyObject.getPlainAttrs(),
+                derAttrHandler.getValues(anyObject),
+                virAttrValues,
+                anyObjectDAO.findAllResources(anyObject));
 
         if (details) {
             // relationships
@@ -107,7 +117,11 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
                 @Override
                 public MembershipTO transform(final AMembership membership) {
-                    return AnyObjectDataBinderImpl.this.getMembershipTO(membership);
+                    return getMembershipTO(
+                            anyObject.getPlainAttrs(membership),
+                            derAttrHandler.getValues(anyObject, membership),
+                            virAttrHandler.getValues(anyObject, membership),
+                            membership);
                 }
             }, anyObjectTO.getMemberships());
 
@@ -131,6 +145,16 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
         SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
 
+        // name
+        SyncopeClientException invalidGroups = SyncopeClientException.build(ClientExceptionType.InvalidGroup);
+        if (anyObjectTO.getName() == null) {
+            LOG.error("No name specified for this anyObject");
+
+            invalidGroups.getElements().add("No name specified for this anyObject");
+        } else {
+            anyObject.setName(anyObjectTO.getName());
+        }
+
         // realm
         Realm realm = realmDAO.findByFullPath(anyObjectTO.getRealm());
         if (realm == null) {
@@ -140,6 +164,7 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
         }
         anyObject.setRealm(realm);
 
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT);
         if (anyObject.getRealm() != null) {
             AssignableCond assignableCond = new AssignableCond();
             assignableCond.setRealmFullPath(anyObject.getRealm().getFullPath());
@@ -199,6 +224,9 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
                     membership.setLeftEnd(anyObject);
 
                     anyObject.add(membership);
+
+                    // membership attributes
+                    fill(anyObject, membership, membershipTO, anyUtils, scce);
                 } else {
                     LOG.error("{} cannot be assigned to {}", group, anyObject);
 
@@ -210,8 +238,8 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
             }
         }
 
-        // attributes, derived attributes, virtual attributes and resources
-        fill(anyObject, anyObjectTO, anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), scce);
+        // attributes and resources
+        fill(anyObject, anyObjectTO, anyUtils, scce);
 
         // Throw composite exception if there is at least one element set in the composing exceptions
         if (scce.hasExceptions()) {
@@ -233,8 +261,19 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
         // fetch connObjectKeys before update
         Map<String, String> oldConnObjectKeys = getConnObjectKeys(anyObject);
 
-        // attributes, derived attributes, virtual attributes and resources
-        propByRes.merge(fill(anyObject, anyObjectPatch, anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), scce));
+        // realm
+        setRealm(anyObject, anyObjectPatch);
+
+        // name
+        if (anyObjectPatch.getName() != null && StringUtils.isNotBlank(anyObjectPatch.getName().getValue())) {
+            propByRes.addAll(ResourceOperation.UPDATE, anyObject.getResourceNames());
+
+            anyObject.setName(anyObjectPatch.getName().getValue());
+        }
+
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT);
+        // attributes and resources
+        propByRes.merge(fill(anyObject, anyObjectPatch, anyUtils, scce));
 
         Set<String> toBeDeprovisioned = new HashSet<>();
         Set<String> toBeProvisioned = new HashSet<>();
@@ -253,6 +292,8 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
                             anyObject.getRelationship(relationshipType, patch.getRelationshipTO().getRightKey());
                     if (relationship != null) {
                         anyObject.getRelationships().remove(relationship);
+                        relationship.setLeftEnd(null);
+
                         toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
                     }
 
@@ -293,22 +334,31 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
             }
         }
 
+        Set<ExternalResource> resources = anyUtils.getAllResources(anyObject);
+        SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
+
         // memberships
         List<Group> assignableGroups =
                 searchDAO.searchAssignable(anyObject.getRealm().getFullPath(), AnyTypeKind.GROUP);
 
-        for (MembershipPatch patch : anyObjectPatch.getMemberships()) {
-            if (patch.getMembershipTO() != null) {
-                AMembership membership = anyObject.getMembership(patch.getMembershipTO().getRightKey());
+        for (MembershipPatch membPatch : anyObjectPatch.getMemberships()) {
+            if (membPatch.getGroup() != null) {
+                AMembership membership = anyObject.getMembership(membPatch.getGroup());
                 if (membership != null) {
                     anyObject.getMemberships().remove(membership);
+                    membership.setLeftEnd(null);
+                    for (APlainAttr attr : anyObject.getPlainAttrs(membership)) {
+                        anyObject.remove(attr);
+                        attr.setOwner(null);
+                    }
+
                     toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
                 }
 
-                if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    Group group = groupDAO.find(patch.getMembershipTO().getRightKey());
+                if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
+                    Group group = groupDAO.find(membPatch.getGroup());
                     if (group == null) {
-                        LOG.debug("Ignoring invalid group {}", patch.getMembershipTO().getRightKey());
+                        LOG.debug("Ignoring invalid group {}", membPatch.getGroup());
                     } else if (assignableGroups.contains(group)) {
                         membership = entityFactory.newEntity(AMembership.class);
                         membership.setRightEnd(group);
@@ -316,6 +366,37 @@ 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);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (!invalidValues.isEmpty()) {
+                            scce.addException(invalidValues);
+                        }
+
                         toBeProvisioned.addAll(group.getResourceNames());
                     } else {
                         LOG.error("{} cannot be assigned to {}", group, anyObject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index 0aba4b9..38f1811 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -110,7 +110,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
         }
         group.setRealm(realm);
 
-        // attributes, derived attributes, virtual attributes and resources
+        // attributes and resources
         fill(group, groupTO, anyUtilsFactory.getInstance(AnyTypeKind.GROUP), scce);
 
         // owner
@@ -211,7 +211,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
                     : groupDAO.find(groupPatch.getGroupOwner().getValue()));
         }
 
-        // attributes, derived attributes, virtual attributes and resources
+        // attributes and resources
         propByRes.merge(fill(group, groupPatch, anyUtilsFactory.getInstance(AnyTypeKind.GROUP), scce));
 
         // check if some connObjectKey was changed by the update above
@@ -325,7 +325,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
 
         Map<DerSchema, String> derAttrValues = derAttrHandler.getValues(group);
         Map<VirSchema, List<String>> virAttrValues = details
-                ? virAttrHander.getValues(group)
+                ? virAttrHandler.getValues(group)
                 : Collections.<VirSchema, List<String>>emptyMap();
         fillTO(groupTO, group.getRealm().getFullPath(), group.getAuxClasses(),
                 group.getPlainAttrs(), derAttrValues, virAttrValues, group.getResources());

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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 0a7f0a8..1581463 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
@@ -34,6 +34,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.patch.AttrPatch;
 import org.apache.syncope.common.lib.patch.MembershipPatch;
 import org.apache.syncope.common.lib.patch.PasswordPatch;
 import org.apache.syncope.common.lib.patch.RelationshipPatch;
@@ -62,7 +63,8 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AssignableCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
@@ -72,6 +74,7 @@ import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -188,6 +191,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
         }
         user.setRealm(realm);
 
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(AnyTypeKind.USER);
         if (user.getRealm() != null) {
             AssignableCond assignableCond = new AssignableCond();
             assignableCond.setRealmFullPath(user.getRealm().getFullPath());
@@ -237,6 +241,9 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
                     membership.setLeftEnd(user);
 
                     user.add(membership);
+
+                    // membership attributes
+                    fill(user, membership, membershipTO, anyUtils, scce);
                 } else {
                     LOG.error("{} cannot be assigned to {}", group, user);
 
@@ -248,8 +255,8 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             }
         }
 
-        // attributes, derived attributes, virtual attributes and resources
-        fill(user, userTO, anyUtilsFactory.getInstance(AnyTypeKind.USER), scce);
+        // attributes and resources
+        fill(user, userTO, anyUtils, scce);
 
         // set password
         if (StringUtils.isBlank(userTO.getPassword()) || !storePassword) {
@@ -371,8 +378,9 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             }
         }
 
-        // attributes, derived attributes, virtual attributes and resources
-        propByRes.merge(fill(user, userPatch, anyUtilsFactory.getInstance(AnyTypeKind.USER), scce));
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(AnyTypeKind.USER);
+        // attributes and resources
+        propByRes.merge(fill(user, userPatch, anyUtils, scce));
 
         Set<String> toBeDeprovisioned = new HashSet<>();
         Set<String> toBeProvisioned = new HashSet<>();
@@ -391,6 +399,8 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
                             user.getRelationship(relationshipType, patch.getRelationshipTO().getRightKey());
                     if (relationship != null) {
                         user.getRelationships().remove(relationship);
+                        relationship.setLeftEnd(null);
+
                         toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
                     }
 
@@ -420,22 +430,32 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             }
         }
 
+        Set<ExternalResource> resources = anyUtils.getAllResources(user);
+        SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
+
         // memberships
         List<Group> assignableGroups =
                 searchDAO.searchAssignable(user.getRealm().getFullPath(), AnyTypeKind.GROUP);
 
-        for (MembershipPatch patch : userPatch.getMemberships()) {
-            if (patch.getMembershipTO() != null) {
-                UMembership membership = user.getMembership(patch.getMembershipTO().getRightKey());
+        for (MembershipPatch membPatch : userPatch.getMemberships()) {
+            if (membPatch.getGroup() != null) {
+                UMembership membership = user.getMembership(membPatch.getGroup());
                 if (membership != null) {
                     user.getMemberships().remove(membership);
+                    membership.setLeftEnd(null);
+                    for (UPlainAttr attr : user.getPlainAttrs(membership)) {
+                        user.remove(attr);
+                        attr.setOwner(null);
+                        attr.setMembership(null);
+                    }
+
                     toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
                 }
 
-                if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    Group group = groupDAO.find(patch.getMembershipTO().getRightKey());
+                if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
+                    Group group = groupDAO.find(membPatch.getGroup());
                     if (group == null) {
-                        LOG.debug("Ignoring invalid group {}", patch.getMembershipTO().getRightKey());
+                        LOG.debug("Ignoring invalid group {}", membPatch.getGroup());
                     } else if (assignableGroups.contains(group)) {
                         membership = entityFactory.newEntity(UMembership.class);
                         membership.setRightEnd(group);
@@ -443,6 +463,37 @@ 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);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                        if (!invalidValues.isEmpty()) {
+                            scce.addException(invalidValues);
+                        }
+
                         toBeProvisioned.addAll(group.getResourceNames());
 
                         // SYNCOPE-686: if password is invertible and we are adding resources with password mapping,
@@ -509,12 +560,15 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             userTO.setSecurityQuestion(user.getSecurityQuestion().getKey());
         }
 
-        Map<DerSchema, String> derAttrValues = derAttrHandler.getValues(user);
         Map<VirSchema, List<String>> virAttrValues = details
-                ? virAttrHander.getValues(user)
+                ? virAttrHandler.getValues(user)
                 : Collections.<VirSchema, List<String>>emptyMap();
-        fillTO(userTO, user.getRealm().getFullPath(), user.getAuxClasses(),
-                user.getPlainAttrs(), derAttrValues, virAttrValues, userDAO.findAllResources(user));
+        fillTO(userTO, user.getRealm().getFullPath(),
+                user.getAuxClasses(),
+                user.getPlainAttrs(),
+                derAttrHandler.getValues(user),
+                virAttrValues,
+                userDAO.findAllResources(user));
 
         if (details) {
             // roles
@@ -536,7 +590,11 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
 
                 @Override
                 public MembershipTO transform(final UMembership membership) {
-                    return UserDataBinderImpl.this.getMembershipTO(membership);
+                    return getMembershipTO(
+                            user.getPlainAttrs(membership),
+                            derAttrHandler.getValues(user, membership),
+                            virAttrHandler.getValues(user, membership),
+                            membership);
                 }
             }, userTO.getMemberships());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
index ead65e2..1b509d7 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/SetUMembershipsJob.java
@@ -22,7 +22,6 @@ import java.util.Map;
 import java.util.Set;
 import org.apache.syncope.common.lib.patch.MembershipPatch;
 import org.apache.syncope.common.lib.patch.UserPatch;
-import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
 import org.apache.syncope.core.provisioning.api.job.JobManager;
@@ -70,7 +69,7 @@ public class SetUMembershipsJob extends AbstractInterruptableJob {
                             userPatch.getMemberships().add(
                                     new MembershipPatch.Builder().
                                     operation(PatchOperation.ADD_REPLACE).
-                                    membershipTO(new MembershipTO.Builder().group(groupKey).build()).
+                                    group(groupKey).
                                     build());
                         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
index 599aabf..995f483 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullUtils.java
@@ -39,6 +39,7 @@ import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -237,6 +238,13 @@ public class PullUtils {
                 }
                 break;
 
+            case AnyObjectName:
+                AnyObject anyObject = anyObjectDAO.findByName(transfUid);
+                if (anyObject != null) {
+                    result.add(anyObject.getKey());
+                }
+                break;
+                
             default:
                 LOG.error("Invalid connObjectKey type '{}'", connObjectKeyItem.getIntMappingType());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
index 124724f..af2631c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/ConnObjectUtils.java
@@ -260,7 +260,7 @@ public class ConnObjectUtils {
                     }
                 }
 
-                connObjectTO.getPlainAttrs().add(attrTO);
+                connObjectTO.getAttrs().add(attrTO);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/build-tools/src/main/resources/testdb.sql
----------------------------------------------------------------------
diff --git a/fit/build-tools/src/main/resources/testdb.sql b/fit/build-tools/src/main/resources/testdb.sql
index df929da..610c8a3 100644
--- a/fit/build-tools/src/main/resources/testdb.sql
+++ b/fit/build-tools/src/main/resources/testdb.sql
@@ -45,5 +45,6 @@ lastModification TIMESTAMP);
 DROP TABLE testPRINTER IF EXISTS;
 CREATE TABLE testPRINTER (
 id CHAR(36) PRIMARY KEY,
+printername VARCHAR(80),
 location VARCHAR(80),
 lastModification TIMESTAMP);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
index 40befd3..bfd04fe 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AnyObjectsITCase.java
@@ -69,7 +69,7 @@ public class AnyObjectsITCase extends AbstractConsoleITCase {
                 "8559d14d-58c2-46eb-a2d4-a7d35161e8f8");
         assertNotNull(component);
 
-        wicketTester.clickLink(component.getPageRelativePath() + ":cells:3:cell:panelClone:cloneLink");
+        wicketTester.clickLink(component.getPageRelativePath() + ":cells:4:cell:panelClone:cloneLink");
 
         FormTester formTester = wicketTester.newFormTester(tabPanel + "outerObjectsRepeater:0:outer:form:content:form");
         assertNotNull(formTester);
@@ -87,7 +87,7 @@ public class AnyObjectsITCase extends AbstractConsoleITCase {
                 "8559d14d-58c2-46eb-a2d4-a7d35161e8f8");
         assertNotNull(component);
 
-        wicketTester.clickLink(component.getPageRelativePath() + ":cells:3:cell:panelEdit:editLink");
+        wicketTester.clickLink(component.getPageRelativePath() + ":cells:4:cell:panelEdit:editLink");
 
         wicketTester.assertComponent(tabPanel + "outerObjectsRepeater:0:outer:form:content:form:view:status:"
                 + "resources:firstLevelContainer:first:container:content:group:beans:0:fields:0", ListItem.class);
@@ -138,7 +138,7 @@ public class AnyObjectsITCase extends AbstractConsoleITCase {
                 "8559d14d-58c2-46eb-a2d4-a7d35161e8f8");
         assertNotNull(component);
 
-        wicketTester.assertComponent(component.getPageRelativePath() + ":cells:3:cell:panelDelete:deleteLink",
+        wicketTester.assertComponent(component.getPageRelativePath() + ":cells:4:cell:panelDelete:deleteLink",
                 IndicatingOnConfirmAjaxLink.class);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BulkActionITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BulkActionITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BulkActionITCase.java
index 2407a15..cf82980 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BulkActionITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/BulkActionITCase.java
@@ -236,7 +236,7 @@ public class BulkActionITCase extends AbstractConsoleITCase {
         assertNotNull(component);
 
         wicketTester.clickLink(component.getPageRelativePath()
-                + ":cells:3:cell:panelManageResources:manageResourcesLink");
+                + ":cells:4:cell:panelManageResources:manageResourcesLink");
 
         wicketTester.assertComponent(tabPanel + "outerObjectsRepeater:1:outer:form:content:status:"
                 + "firstLevelContainer:first:container:content:searchContainer:resultTable:tablePanel:groupForm:"

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
index 7627467..e0e02b9 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/DisplayAttributesITCase.java
@@ -42,7 +42,7 @@ public class DisplayAttributesITCase extends AbstractConsoleITCase {
         wicketTester.clickLink("body:content:body:tabbedPanel:panel:"
                 + "searchResult:container:content:searchContainer:resultTable:"
                 + "tablePanel:groupForm:checkgroup:dataTable:topToolbars:"
-                + "toolbars:1:headers:3:header:label:panelChangeView:changeViewLink");
+                + "toolbars:1:headers:4:header:label:panelChangeView:changeViewLink");
 
         wicketTester.assertComponent(
                 "body:content:body:tabbedPanel:panel:searchResult:outerObjectsRepeater:2:outer", Modal.class);
@@ -54,7 +54,7 @@ public class DisplayAttributesITCase extends AbstractConsoleITCase {
         wicketTester.clickLink("body:content:body:tabbedPanel:panel:"
                 + "searchResult:container:content:searchContainer:resultTable:"
                 + "tablePanel:groupForm:checkgroup:dataTable:topToolbars:"
-                + "toolbars:1:headers:3:header:label:panelChangeView:changeViewLink");
+                + "toolbars:1:headers:4:header:label:panelChangeView:changeViewLink");
 
         wicketTester.assertComponent(
                 "body:content:body:tabbedPanel:panel:searchResult:outerObjectsRepeater:2:outer", Modal.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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 b653de8..7356c5c 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
@@ -50,6 +50,7 @@ public class AnyObjectITCase extends AbstractITCase {
 
     public static AnyObjectTO getSampleTO(final String location) {
         AnyObjectTO anyObjectTO = new AnyObjectTO();
+        anyObjectTO.setName(location + getUUIDString());
         anyObjectTO.setRealm(SyncopeConstants.ROOT_REALM);
         anyObjectTO.setType("PRINTER");
         anyObjectTO.getPlainAttrs().add(attrTO("location", location + getUUIDString()));

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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 781f89b..61c9945 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
@@ -432,6 +432,7 @@ public class AuthenticationITCase extends AbstractITCase {
 
         // 3. attempt to create an instance of the type above: fail because no entitlement was assigned
         AnyObjectTO folder = new AnyObjectTO();
+        folder.setName("home");
         folder.setRealm(SyncopeConstants.ROOT_REALM);
         folder.setType(anyTypeKey);
         folder.getPlainAttrs().add(attrTO(path.getKey(), "/home"));

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
index 20c290f..b355799 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/CamelRouteITCase.java
@@ -24,7 +24,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
 import java.util.List;
-import org.apache.commons.collections4.IterableUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.CamelRouteTO;
@@ -123,8 +122,7 @@ public class CamelRouteITCase extends AbstractITCase {
                 + "    </setProperty>\n"
                 + "    <setBody>\n"
                 + "     <groovy>\n"
-                + "       org.apache.commons.collections4."
-                + "CollectionUtils.get(request.body.getPlainAttrs(), 3).getValues().set(0,\"true\")\n"
+                + "request.body.getPlainAttrMap().get(\"camelAttribute\").getValues().set(0,\"true\")\n"
                 + "       return request.body\n"
                 + "     </groovy>\n"
                 + "    </setBody>\n"
@@ -169,7 +167,7 @@ public class CamelRouteITCase extends AbstractITCase {
 
             userTO = createUser(userTO).getAny();
             assertNotNull(userTO);
-            assertEquals("true", IterableUtils.get(userTO.getPlainAttrs(), 3).getValues().get(0));
+            assertEquals("true", userTO.getPlainAttrMap().get("camelAttribute").getValues().get(0));
         } finally {
             doUpdate(oldRoute.getKey(), oldRoute.getContent());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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
new file mode 100644
index 0000000..09a560c
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
@@ -0,0 +1,162 @@
+/*
+ * 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.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.patch.AttrPatch;
+import org.apache.syncope.common.lib.patch.MembershipPatch;
+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.UserTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.PatchOperation;
+import org.apache.syncope.fit.AbstractITCase;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+@FixMethodOrder(MethodSorters.JVM)
+public class MembershipITCase extends AbstractITCase {
+
+    @Test
+    public void misc() {
+        UserTO user = UserITCase.getUniqueSampleTO("memb@apache.org");
+        user.setRealm("/even/two");
+        user.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("1976").build());
+        user.getPlainAttrs().remove(user.getPlainAttrMap().get("ctype"));
+
+        // the group 034740a9-fa10-453b-af37-dc7897e98fb1 has USER type extensions for 'csv' and 'other' 
+        // any type classes
+        MembershipTO membership = new MembershipTO.Builder().group("034740a9-fa10-453b-af37-dc7897e98fb1").build();
+        membership.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("1977").build());
+
+        // 'fullname' is in 'minimal user', so it is not allowed for this membership
+        membership.getPlainAttrs().add(new AttrTO.Builder().schema("fullname").value("discarded").build());
+
+        user.getMemberships().add(membership);
+
+        // user creation fails because of fullname
+        try {
+            createUser(user);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidUser, e.getType());
+            assertTrue(e.getMessage().contains("InvalidPlainAttr: fullname not allowed for membership of group"));
+        }
+
+        // remove fullname and try again
+        CollectionUtils.filterInverse(membership.getPlainAttrs(), new Predicate<AttrTO>() {
+
+            @Override
+            public boolean evaluate(final AttrTO object) {
+                return "fullname".equals(object.getSchema());
+            }
+        });
+        try {
+            user = createUser(user).getAny();
+
+            // 1. verify that 'aLong' is correctly populated for user
+            assertEquals(1, user.getPlainAttrMap().get("aLong").getValues().size());
+            assertEquals("1976", user.getPlainAttrMap().get("aLong").getValues().get(0));
+
+            // 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");
+            assertNotNull(membership);
+            assertEquals(1, membership.getPlainAttrMap().get("aLong").getValues().size());
+            assertEquals("1977", membership.getPlainAttrMap().get("aLong").getValues().get(0));
+
+            // 3. verify that derived attrbutes from 'csv' and 'other' are also populated for user's membership
+            assertFalse(membership.getDerAttrMap().get("csvuserid").getValues().isEmpty());
+            assertFalse(membership.getDerAttrMap().get("noschema").getValues().isEmpty());
+
+            // update user - change some values and add new membership attribute
+            UserPatch userPatch = new UserPatch();
+            userPatch.setKey(user.getKey());
+
+            userPatch.getPlainAttrs().add(new AttrPatch.Builder().
+                    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());
+            userPatch.getMemberships().add(membershipPatch);
+
+            user = updateUser(userPatch).getAny();
+
+            // 4. verify that 'aLong' is correctly populated for user
+            assertEquals(1, user.getPlainAttrMap().get("aLong").getValues().size());
+            assertEquals("1977", user.getPlainAttrMap().get("aLong").getValues().get(0));
+            assertFalse(user.getPlainAttrMap().containsKey("ctype"));
+
+            // 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");
+            assertNotNull(membership);
+            assertEquals(1, membership.getPlainAttrMap().get("aLong").getValues().size());
+            assertEquals("1976", membership.getPlainAttrMap().get("aLong").getValues().get(0));
+
+            // 6. verify that 'ctype' is correctly populated for user's membership
+            assertEquals("membership type", membership.getPlainAttrMap().get("ctype").getValues().get(0));
+
+            // finally remove membership
+            userPatch = new UserPatch();
+            userPatch.setKey(user.getKey());
+
+            membershipPatch = new MembershipPatch.Builder().group(membership.getGroupKey()).
+                    operation(PatchOperation.DELETE).build();
+            userPatch.getMemberships().add(membershipPatch);
+
+            user = updateUser(userPatch).getAny();
+
+            assertTrue(user.getMemberships().isEmpty());
+        } finally {
+            if (user.getKey() != null) {
+                userService.delete(user.getKey());
+            }
+        }
+    }
+
+    @Test
+    public void deleteUserWithMembership() {
+        UserTO user = UserITCase.getUniqueSampleTO("memb@apache.org");
+        user.setRealm("/even/two");
+        user.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("1976").build());
+
+        MembershipTO membership = new MembershipTO.Builder().group("034740a9-fa10-453b-af37-dc7897e98fb1").build();
+        membership.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("1977").build());
+        user.getMemberships().add(membership);
+
+        user = createUser(user).getAny();
+        assertNotNull(user.getKey());
+
+        userService.delete(user.getKey());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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 5a76218..4e4af92 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
@@ -646,10 +646,9 @@ public class UserITCase extends AbstractITCase {
         userPatch.getPlainAttrs().add(attrAddReplacePatch("fullname", newFullName));
 
         userPatch.getMemberships().add(new MembershipPatch.Builder().operation(PatchOperation.ADD_REPLACE).
-                membershipTO(new MembershipTO.Builder().
-                        group("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build()).build());
+                group("f779c0d4-633b-4be5-8f57-32eb478a3ca5").build());
         userPatch.getMemberships().add(new MembershipPatch.Builder().operation(PatchOperation.ADD_REPLACE).
-                membershipTO(userTO.getMemberships().get(0)).build());
+                group(userTO.getMemberships().get(0).getGroupKey()).build());
 
         userTO = updateUser(userPatch).getAny();
         assertNotNull(userTO);
@@ -1218,7 +1217,7 @@ public class UserITCase extends AbstractITCase {
         userPatch.setKey(userTO.getKey());
 
         userPatch.getMemberships().add(new MembershipPatch.Builder().
-                operation(PatchOperation.DELETE).membershipTO(userTO.getMemberships().get(0)).build());
+                operation(PatchOperation.DELETE).group(userTO.getMemberships().get(0).getGroupKey()).build());
 
         userTO = updateUser(userPatch).getAny();
         assertNotNull(userTO);
@@ -1253,7 +1252,7 @@ public class UserITCase extends AbstractITCase {
         userPatch.setKey(userTO.getKey());
 
         userPatch.getMemberships().add(new MembershipPatch.Builder().
-                operation(PatchOperation.DELETE).membershipTO(userTO.getMemberships().get(0)).build());
+                operation(PatchOperation.DELETE).group(userTO.getMemberships().get(0).getGroupKey()).build());
 
         userTO = updateUser(userPatch).getAny();
         assertNotNull(userTO);
@@ -1635,7 +1634,7 @@ public class UserITCase extends AbstractITCase {
         UserPatch userPatch = new UserPatch();
         userPatch.setKey(userTO.getKey());
         userPatch.getMemberships().add(new MembershipPatch.Builder().operation(PatchOperation.DELETE).
-                membershipTO(userTO.getMemberships().get(0)).build());
+                group(userTO.getMemberships().get(0).getGroupKey()).build());
 
         userTO = updateUser(userPatch).getAny();
         assertTrue(userTO.getResources().contains(RESOURCE_NAME_LDAP));
@@ -2503,7 +2502,7 @@ public class UserITCase extends AbstractITCase {
             UserPatch userPatch = new UserPatch();
             userPatch.setKey(userTO.getKey());
             userPatch.getMemberships().add(new MembershipPatch.Builder().operation(PatchOperation.ADD_REPLACE).
-                    membershipTO(new MembershipTO.Builder().group(group.getKey()).build()).build());
+                    group(group.getKey()).build());
 
             ProvisioningResult<UserTO> result = updateUser(userPatch);
             assertNotNull(result);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/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 6d412a8..beb6c6e 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
@@ -182,8 +182,7 @@ public class UserSelfITCase extends AbstractITCase {
         userPatch.setUsername(new StringReplacePatchItem.Builder().value(created.getUsername() + "XX").build());
         userPatch.getMemberships().add(new MembershipPatch.Builder().
                 operation(PatchOperation.ADD_REPLACE).
-                membershipTO(new MembershipTO.Builder().
-                        group("bf825fe1-7320-4a54-bd64-143b5c18ab97").build()).
+                group("bf825fe1-7320-4a54-bd64-143b5c18ab97").
                 build());
         userPatch.getResources().add(new StringPatchItem.Builder().
                 operation(PatchOperation.ADD_REPLACE).value(RESOURCE_NAME_TESTDB).build());

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/resources/scriptedsql/CreateScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/scriptedsql/CreateScript.groovy b/fit/core-reference/src/test/resources/scriptedsql/CreateScript.groovy
index 5ee8d55..a5e1a5e 100644
--- a/fit/core-reference/src/test/resources/scriptedsql/CreateScript.groovy
+++ b/fit/core-reference/src/test/resources/scriptedsql/CreateScript.groovy
@@ -37,9 +37,10 @@ def sql = new Sql(connection);
 
 switch ( objectClass ) {  
 case "__PRINTER__":
-  sql.execute("INSERT INTO TESTPRINTER (id, location, lastmodification) values (?,?,?)",
+  sql.execute("INSERT INTO TESTPRINTER (id, printername, location, lastmodification) values (?,?,?,?)",
     [
       id,
+      attributes.get("PRINTERNAME").get(0),
       attributes.get("LOCATION").get(0),
       new Date()
     ])

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/resources/scriptedsql/SchemaScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/scriptedsql/SchemaScript.groovy b/fit/core-reference/src/test/resources/scriptedsql/SchemaScript.groovy
index 18ba61d..e13f058 100644
--- a/fit/core-reference/src/test/resources/scriptedsql/SchemaScript.groovy
+++ b/fit/core-reference/src/test/resources/scriptedsql/SchemaScript.groovy
@@ -42,6 +42,7 @@ idAIB.setRequired(true);
 
 orgAttrsInfo = new HashSet<AttributeInfo>();
 orgAttrsInfo.add(idAIB.build());
+orgAttrsInfo.add(AttributeInfoBuilder.build("PRINTERNAME", String.class));
 orgAttrsInfo.add(AttributeInfoBuilder.build("LOCATION", String.class));
 // Create the organization Object class
 ObjectClassInfo ociOrg = new ObjectClassInfoBuilder().setType("__PRINTER__").addAllAttributeInfo(orgAttrsInfo).build();

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/resources/scriptedsql/SearchScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/scriptedsql/SearchScript.groovy b/fit/core-reference/src/test/resources/scriptedsql/SearchScript.groovy
index 3e65581..bb02d80 100644
--- a/fit/core-reference/src/test/resources/scriptedsql/SearchScript.groovy
+++ b/fit/core-reference/src/test/resources/scriptedsql/SearchScript.groovy
@@ -84,7 +84,7 @@ if (query != null)  {
 switch ( objectClass ) {
 case "__PRINTER__":
   sql.eachRow("SELECT * FROM TESTPRINTER " + where, 
-    {result.add([__UID__:it.id, __NAME__:it.id, ID:it.id, LOCATION:it.location])} );
+    {result.add([__UID__:it.id, __NAME__:it.id, ID:it.id, PRINTERNAME:it.printername, LOCATION:it.location])} );
   break
 
 default:

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/resources/scriptedsql/SyncScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/scriptedsql/SyncScript.groovy b/fit/core-reference/src/test/resources/scriptedsql/SyncScript.groovy
index 69f8d79..f7ff18f 100644
--- a/fit/core-reference/src/test/resources/scriptedsql/SyncScript.groovy
+++ b/fit/core-reference/src/test/resources/scriptedsql/SyncScript.groovy
@@ -71,7 +71,7 @@ if (action.equalsIgnoreCase("GET_LATEST_SYNC_TOKEN")) {
   }
 
   switch (objectClass) {
-  case "__PRINTER__":    
+  case "__PRINTER__":
     sql.eachRow("SELECT * FROM TESTPRINTER WHERE lastmodification > ${lastmodification}",
       {
         result.add([
@@ -82,6 +82,7 @@ if (action.equalsIgnoreCase("GET_LATEST_SYNC_TOKEN")) {
               __UID__:it.id.toString(),
               __NAME__:it.id.toString(),
               ID:it.id.toString(),
+              PRINTERNAME:it.printername,
               LOCATION:it.location
             ]
           ]);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/resources/scriptedsql/TestScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/scriptedsql/TestScript.groovy b/fit/core-reference/src/test/resources/scriptedsql/TestScript.groovy
index 5b8f4b5..1de9d9f 100644
--- a/fit/core-reference/src/test/resources/scriptedsql/TestScript.groovy
+++ b/fit/core-reference/src/test/resources/scriptedsql/TestScript.groovy
@@ -28,4 +28,4 @@ import groovy.sql.DataSet;
 log.info("Entering " + action + " Script");
 def sql = new Sql(connection);
 
-sql.eachRow("select * from TESTPRINTER", { println it.uid} );
\ No newline at end of file
+sql.eachRow("select * from TESTPRINTER", { println it.id} );
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1adcc1e/fit/core-reference/src/test/resources/scriptedsql/UpdateScript.groovy
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/resources/scriptedsql/UpdateScript.groovy b/fit/core-reference/src/test/resources/scriptedsql/UpdateScript.groovy
index 4d1ce5e..9df30f8 100644
--- a/fit/core-reference/src/test/resources/scriptedsql/UpdateScript.groovy
+++ b/fit/core-reference/src/test/resources/scriptedsql/UpdateScript.groovy
@@ -51,8 +51,11 @@ def sql = new Sql(connection);
 switch (action) {
 case "UPDATE":
   if (attributes.get("LOCATION").get(0) != null) {
-    sql.executeUpdate("UPDATE TESTPRINTER SET location = ?, lastmodification = ? where id = ?", 
-      [attributes.get("LOCATION").get(0), new Date(), attributes.get("__NAME__").get(0)])
+    sql.executeUpdate("UPDATE TESTPRINTER SET printername = ?, location = ?, lastmodification = ? where id = ?", 
+      [attributes.get("PRINTERNAME").get(0), 
+        attributes.get("LOCATION").get(0), 
+        new Date(), 
+        attributes.get("__NAME__").get(0)])
     
     return attributes.get("__NAME__").get(0);
   }