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/06/14 15:59:52 UTC

[01/15] syncope git commit: Upgrading Activiti [Forced Update!]

Repository: syncope
Updated Branches:
  refs/heads/SYNCOPE-862 394f8c98c -> 8e162494e (forced update)


Upgrading Activiti


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

Branch: refs/heads/SYNCOPE-862
Commit: befa49c32d73a10f6865d7cc13737c9d7a539d51
Parents: 339f9d5
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Mon Jun 13 17:39:49 2016 +0200
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Mon Jun 13 17:39:49 2016 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/befa49c3/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index aa76443..15be564 100644
--- a/pom.xml
+++ b/pom.xml
@@ -353,7 +353,7 @@ under the License.
 
     <groovy.version>2.4.7</groovy.version>
 
-    <activiti.version>5.20.0</activiti.version>
+    <activiti.version>5.21.0</activiti.version>
 
     <slf4j.version>1.7.21</slf4j.version>
     <log4j.version>2.6.1</log4j.version>


[10/15] syncope git commit: [SYNCOPE-862] Features complete

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 e2f793a..7d38624 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
@@ -21,24 +21,21 @@ package org.apache.syncope.core.provisioning.java;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 import org.apache.commons.collections4.ListUtils;
-import org.apache.commons.jexl3.JexlContext;
-import org.apache.commons.jexl3.MapContext;
-import org.apache.commons.lang3.ClassUtils;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 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.MembershipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.provisioning.api.utils.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
@@ -48,53 +45,46 @@ import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
 import org.apache.syncope.core.spring.security.Encryptor;
-import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
 import org.apache.syncope.core.spring.security.PasswordGenerator;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Schema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
-import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
-import org.apache.syncope.core.provisioning.java.data.JEXLMappingItemTransformer;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.FrameworkUtil;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
-import org.identityconnectors.framework.common.objects.Name;
-import org.identityconnectors.framework.common.objects.OperationOptions;
-import org.identityconnectors.framework.common.objects.OperationOptionsBuilder;
 import org.identityconnectors.framework.common.objects.OperationalAttributes;
-import org.identityconnectors.framework.common.objects.Uid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.support.AbstractBeanDefinition;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 
 @Component
 public class MappingManagerImpl implements MappingManager {
@@ -116,10 +106,10 @@ public class MappingManagerImpl implements MappingManager {
     private VirSchemaDAO virSchemaDAO;
 
     @Autowired
-    private UserDAO userDAO;
+    private AnyObjectDAO anyObjectDAO;
 
     @Autowired
-    private AnyObjectDAO anyObjectDAO;
+    private GroupDAO groupDAO;
 
     @Autowired
     private DerAttrHandler derAttrHandler;
@@ -139,201 +129,9 @@ public class MappingManagerImpl implements MappingManager {
     @Autowired
     private AnyUtilsFactory anyUtilsFactory;
 
-    public static MappingItem getConnObjectKeyItem(final Provision provision) {
-        Mapping mapping = null;
-        if (provision != null) {
-            mapping = provision.getMapping();
-        }
-
-        return mapping == null
-                ? null
-                : mapping.getConnObjectKeyItem();
-    }
-
-    private static List<MappingItem> getMappingItems(final Provision provision, final MappingPurpose purpose) {
-        List<? extends MappingItem> items = Collections.<MappingItem>emptyList();
-        if (provision != null) {
-            items = provision.getMapping().getItems();
-        }
-
-        List<MappingItem> result = new ArrayList<>();
-
-        switch (purpose) {
-            case PULL:
-                for (MappingItem item : items) {
-                    if (MappingPurpose.PROPAGATION != item.getPurpose()
-                            && MappingPurpose.NONE != item.getPurpose()) {
-
-                        result.add(item);
-                    }
-                }
-                break;
-
-            case PROPAGATION:
-                for (MappingItem item : items) {
-                    if (MappingPurpose.PULL != item.getPurpose()
-                            && MappingPurpose.NONE != item.getPurpose()) {
-
-                        result.add(item);
-                    }
-                }
-                break;
-
-            case BOTH:
-                for (MappingItem item : items) {
-                    if (MappingPurpose.NONE != item.getPurpose()) {
-                        result.add(item);
-                    }
-                }
-                break;
-
-            case NONE:
-                for (MappingItem item : items) {
-                    if (MappingPurpose.NONE == item.getPurpose()) {
-                        result.add(item);
-                    }
-                }
-                break;
-
-            default:
-        }
-
-        return result;
-    }
-
-    public static List<MappingItem> getBothMappingItems(final Provision provision) {
-        return getMappingItems(provision, MappingPurpose.BOTH);
-    }
-
-    public static List<MappingItem> getPropagationMappingItems(final Provision provision) {
-        return getMappingItems(provision, MappingPurpose.PROPAGATION);
-    }
-
-    public static List<MappingItem> getPullMappingItems(final Provision provision) {
-        return getMappingItems(provision, MappingPurpose.PULL);
-    }
-
-    /**
-     * Build __NAME__ for propagation. First look if there ia a defined connObjectLink for the given resource (and in
-     * this case evaluate as JEXL); otherwise, take given connObjectKey.
-     *
-     * @param any given any object
-     * @param provision external resource
-     * @param connObjectKey connector object key
-     * @return the value to be propagated as __NAME__
-     */
-    public static Name evaluateNAME(final Any<?> any, final Provision provision, final String connObjectKey) {
-        if (StringUtils.isBlank(connObjectKey)) {
-            // LOG error but avoid to throw exception: leave it to the external resource
-            LOG.error("Missing ConnObjectKey for '{}': ", provision.getResource());
-        }
-
-        // Evaluate connObjectKey expression
-        String connObjectLink = provision == null || provision.getMapping() == null
-                ? null
-                : provision.getMapping().getConnObjectLink();
-        String evalConnObjectLink = null;
-        if (StringUtils.isNotBlank(connObjectLink)) {
-            JexlContext jexlContext = new MapContext();
-            JexlUtils.addFieldsToContext(any, jexlContext);
-            JexlUtils.addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
-            JexlUtils.addDerAttrsToContext(any, jexlContext);
-            evalConnObjectLink = JexlUtils.evaluate(connObjectLink, jexlContext);
-        }
-
-        // If connObjectLink evaluates to an empty string, just use the provided connObjectKey as Name(),
-        // otherwise evaluated connObjectLink expression is taken as Name().
-        Name name;
-        if (StringUtils.isBlank(evalConnObjectLink)) {
-            // add connObjectKey as __NAME__ attribute ...
-            LOG.debug("Add connObjectKey [{}] as __NAME__", connObjectKey);
-            name = new Name(connObjectKey);
-        } else {
-            LOG.debug("Add connObjectLink [{}] as __NAME__", evalConnObjectLink);
-            name = new Name(evalConnObjectLink);
-
-            // connObjectKey not propagated: it will be used to set the value for __UID__ attribute
-            LOG.debug("connObjectKey will be used just as __UID__ attribute");
-        }
-
-        return name;
-    }
-
-    public static List<MappingItemTransformer> getMappingItemTransformers(final MappingItem mappingItem) {
-        List<MappingItemTransformer> result = new ArrayList<>();
-
-        // First consider the JEXL transformation expressions
-        JEXLMappingItemTransformer jexlTransformer = null;
-        if (StringUtils.isNotBlank(mappingItem.getPropagationJEXLTransformer())
-                || StringUtils.isNotBlank(mappingItem.getPullJEXLTransformer())) {
-
-            try {
-                jexlTransformer = (JEXLMappingItemTransformer) ApplicationContextProvider.getBeanFactory().
-                        createBean(JEXLMappingItemTransformer.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
-
-                jexlTransformer.setPropagationJEXL(mappingItem.getPropagationJEXLTransformer());
-                jexlTransformer.setPullJEXL(mappingItem.getPullJEXLTransformer());
-            } catch (Exception e) {
-                LOG.error("Could not instantiate {}, ignoring...", JEXLMappingItemTransformer.class.getName(), e);
-            }
-        }
-        if (jexlTransformer != null) {
-            result.add(jexlTransformer);
-        }
-
-        // Then other custom tranaformers
-        for (String className : mappingItem.getMappingItemTransformerClassNames()) {
-            try {
-                Class<?> transformerClass = ClassUtils.getClass(className);
-
-                result.add((MappingItemTransformer) ApplicationContextProvider.getBeanFactory().
-                        createBean(transformerClass, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false));
-            } catch (Exception e) {
-                LOG.error("Could not instantiate {}, ignoring...", className, e);
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Build options for requesting all mapped connector attributes.
-     *
-     * @param mapItems mapping items
-     * @return options for requesting all mapped connector attributes
-     * @see OperationOptions
-     */
-    public static OperationOptions buildOperationOptions(final Iterator<? extends MappingItem> mapItems) {
-        OperationOptionsBuilder builder = new OperationOptionsBuilder();
-
-        Set<String> attrsToGet = new HashSet<>();
-        attrsToGet.add(Name.NAME);
-        attrsToGet.add(Uid.NAME);
-        attrsToGet.add(OperationalAttributes.ENABLE_NAME);
-
-        while (mapItems.hasNext()) {
-            MappingItem mapItem = mapItems.next();
-            if (mapItem.getPurpose() != MappingPurpose.NONE) {
-                attrsToGet.add(mapItem.getExtAttrName());
-            }
-        }
-
-        builder.setAttributesToGet(attrsToGet);
-        // -------------------------------------
-
-        return builder.build();
-    }
+    @Autowired
+    private IntAttrNameParser intAttrNameParser;
 
-    /**
-     * Prepare attributes for sending to a connector instance.
-     *
-     * @param any given any object
-     * @param password clear-text password
-     * @param changePwd whether password should be included for propagation attributes or not
-     * @param enable whether any object must be enabled or not
-     * @param provision provision information
-     * @return connObjectLink + prepared attributes
-     */
     @Transactional(readOnly = true)
     @Override
     public Pair<String, Set<Attribute>> prepareAttrs(
@@ -349,42 +147,44 @@ public class MappingManagerImpl implements MappingManager {
         Set<Attribute> attributes = new HashSet<>();
         String connObjectKey = null;
 
-        for (MappingItem mappingItem : getMappingItems(provision, MappingPurpose.PROPAGATION)) {
-            LOG.debug("Processing expression '{}'", mappingItem.getIntAttrName());
+        for (MappingItem mapItem : MappingUtils.getPropagationMappingItems(provision)) {
+            LOG.debug("Processing expression '{}'", mapItem.getIntAttrName());
 
             try {
-                Pair<String, Attribute> preparedAttr = prepareAttr(provision, mappingItem, any, password);
-
-                if (preparedAttr != null && preparedAttr.getKey() != null) {
-                    connObjectKey = preparedAttr.getKey();
-                }
+                Pair<String, Attribute> preparedAttr = prepareAttr(provision, mapItem, any, password);
+                if (preparedAttr != null) {
+                    if (preparedAttr.getKey() != null) {
+                        connObjectKey = preparedAttr.getKey();
+                    }
 
-                if (preparedAttr != null && preparedAttr.getValue() != null) {
-                    Attribute alreadyAdded = AttributeUtil.find(preparedAttr.getValue().getName(), attributes);
+                    if (preparedAttr.getValue() != null) {
+                        Attribute alreadyAdded = AttributeUtil.find(preparedAttr.getValue().getName(), attributes);
 
-                    if (alreadyAdded == null) {
-                        attributes.add(preparedAttr.getValue());
-                    } else {
-                        attributes.remove(alreadyAdded);
+                        if (alreadyAdded == null) {
+                            attributes.add(preparedAttr.getValue());
+                        } else {
+                            attributes.remove(alreadyAdded);
 
-                        Set<Object> values = new HashSet<>(alreadyAdded.getValue());
-                        values.addAll(preparedAttr.getValue().getValue());
+                            Set<Object> values = new HashSet<>(alreadyAdded.getValue());
+                            values.addAll(preparedAttr.getValue().getValue());
 
-                        attributes.add(AttributeBuilder.build(preparedAttr.getValue().getName(), values));
+                            attributes.add(AttributeBuilder.build(preparedAttr.getValue().getName(), values));
+                        }
                     }
                 }
             } catch (Exception e) {
-                LOG.debug("Expression '{}' processing failed", mappingItem.getIntAttrName(), e);
+                LOG.error("Expression '{}' processing failed", mapItem.getIntAttrName(), e);
             }
         }
 
         Attribute connObjectKeyExtAttr =
-                AttributeUtil.find(getConnObjectKeyItem(provision).getExtAttrName(), attributes);
+                AttributeUtil.find(MappingUtils.getConnObjectKeyItem(provision).getExtAttrName(), attributes);
         if (connObjectKeyExtAttr != null) {
             attributes.remove(connObjectKeyExtAttr);
-            attributes.add(AttributeBuilder.build(getConnObjectKeyItem(provision).getExtAttrName(), connObjectKey));
+            attributes.add(AttributeBuilder.build(
+                    MappingUtils.getConnObjectKeyItem(provision).getExtAttrName(), connObjectKey));
         }
-        attributes.add(evaluateNAME(any, provision, connObjectKey));
+        attributes.add(MappingUtils.evaluateNAME(any, provision, connObjectKey));
 
         if (enable != null) {
             attributes.add(AttributeBuilder.buildEnabled(enable));
@@ -404,7 +204,7 @@ public class MappingManagerImpl implements MappingManager {
      *
      * @param provision external resource
      * @param mapItem mapping item for the given attribute
-     * @param any any object
+     * @param any given any object
      * @param password clear-text password
      * @return connObjectKey + prepared attribute
      */
@@ -412,63 +212,33 @@ public class MappingManagerImpl implements MappingManager {
             final Provision provision, final MappingItem mapItem, final Any<?> any, final String password) {
 
         IntAttrName intAttrName =
-                IntAttrNameParser.parse(mapItem.getIntAttrName(), anyUtilsFactory, provision.getAnyType().getKind());
-
-        List<Any<?>> anys = new ArrayList<>();
-
-        switch (intAttrName.getAnyTypeKind()) {
-            case USER:
-                if (any instanceof User) {
-                    anys.add(any);
-                }
-                break;
-
-            case GROUP:
-                if (any instanceof User) {
-                    anys.addAll(userDAO.findAllGroups((User) any));
-                } else if (any instanceof AnyObject) {
-                    anys.addAll(anyObjectDAO.findAllGroups((AnyObject) any));
-                } else if (any instanceof Group) {
-                    anys.add(any);
-                }
-                break;
+                intAttrNameParser.parse(mapItem.getIntAttrName(), provision.getAnyType().getKind());
 
-            case ANY_OBJECT:
-                if (any instanceof AnyObject) {
-                    anys.add(any);
-                }
-                break;
-
-            default:
-        }
-
-        Schema schema = null;
         boolean readOnlyVirSchema = false;
-        AttrSchemaType schemaType;
-        Pair<String, Attribute> result;
-
-        switch (intAttrName.getSchemaType()) {
-            case PLAIN:
-                schema = plainSchemaDAO.find(intAttrName.getSchemaName());
-                schemaType = schema == null ? AttrSchemaType.String : schema.getType();
-                break;
+        Schema schema = null;
+        AttrSchemaType schemaType = AttrSchemaType.String;
+        if (intAttrName.getSchemaType() != null) {
+            switch (intAttrName.getSchemaType()) {
+                case PLAIN:
+                    schema = plainSchemaDAO.find(intAttrName.getSchemaName());
+                    if (schema != null) {
+                        schemaType = schema.getType();
+                    }
+                    break;
 
-            case VIRTUAL:
-                schema = virSchemaDAO.find(intAttrName.getSchemaName());
-                readOnlyVirSchema = (schema != null && schema.isReadonly());
-                schemaType = AttrSchemaType.String;
-                break;
+                case VIRTUAL:
+                    schema = virSchemaDAO.find(intAttrName.getSchemaName());
+                    readOnlyVirSchema = (schema != null && schema.isReadonly());
+                    break;
 
-            default:
-                schemaType = AttrSchemaType.String;
+                default:
+            }
         }
 
-        String extAttrName = mapItem.getExtAttrName();
-
-        List<PlainAttrValue> values = getIntValues(provision, mapItem, anys);
+        List<PlainAttrValue> values = getIntValues(provision, mapItem, intAttrName, any);
 
         LOG.debug("Define mapping for: "
-                + "\n* ExtAttrName " + extAttrName
+                + "\n* ExtAttrName " + mapItem.getExtAttrName()
                 + "\n* is connObjectKey " + mapItem.isConnObjectKey()
                 + "\n* is password " + mapItem.isPassword()
                 + "\n* mandatory condition " + mapItem.getMandatoryCondition()
@@ -476,6 +246,7 @@ public class MappingManagerImpl implements MappingManager {
                 + "\n* ClassType " + schemaType.getType().getName()
                 + "\n* Values " + values);
 
+        Pair<String, Attribute> result;
         if (readOnlyVirSchema) {
             result = null;
         } else {
@@ -516,78 +287,103 @@ public class MappingManagerImpl implements MappingManager {
                     result = new ImmutablePair<>(
                             null, AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
                 }
-            } else if ((schema != null && schema.isMultivalue())
-                    || anyUtilsFactory.getInstance(any).getAnyTypeKind() != intAttrName.getAnyTypeKind()) {
-
+            } else if (schema != null && schema.isMultivalue()) {
                 result = new ImmutablePair<>(
-                        null, AttributeBuilder.build(extAttrName, objValues));
+                        null, AttributeBuilder.build(mapItem.getExtAttrName(), objValues));
             } else {
                 result = new ImmutablePair<>(
                         null, objValues.isEmpty()
-                                ? AttributeBuilder.build(extAttrName)
-                                : AttributeBuilder.build(extAttrName, objValues.iterator().next()));
+                                ? AttributeBuilder.build(mapItem.getExtAttrName())
+                                : AttributeBuilder.build(mapItem.getExtAttrName(), objValues.iterator().next()));
             }
         }
 
         return result;
     }
 
-    private String getGroupOwnerValue(final Provision provision, final Any<?> any) {
-        Pair<String, Attribute> preparedAttr = prepareAttr(provision, getConnObjectKeyItem(provision), any, null);
-        String connObjectKey = preparedAttr.getKey();
-
-        return evaluateNAME(any, provision, connObjectKey).getNameValue();
-    }
-
     @Transactional(readOnly = true)
     @Override
     public List<PlainAttrValue> getIntValues(
-            final Provision provision, final MappingItem mapItem, final List<Any<?>> anys) {
+            final Provision provision,
+            final MappingItem mapItem,
+            final IntAttrName intAttrName,
+            final Any<?> any) {
 
-        LOG.debug("Get attributes for '{}' and intAttrName '{}'", anys, mapItem.getIntAttrName());
+        LOG.debug("Get internal values for {} as '{}' on {}", any, mapItem.getIntAttrName(), provision.getResource());
 
-        IntAttrName intAttrName =
-                IntAttrNameParser.parse(mapItem.getIntAttrName(), anyUtilsFactory, provision.getAnyType().getKind());
+        Any<?> reference = null;
+        Membership<?> membership = null;
+        if (intAttrName.getEnclosingGroup() == null && intAttrName.getRelatedAnyObject() == null) {
+            reference = any;
+        }
+        if (any instanceof GroupableRelatable) {
+            GroupableRelatable<?, ?, ?, ?, ?> groupableRelatable = (GroupableRelatable<?, ?, ?, ?, ?>) any;
+
+            if (intAttrName.getEnclosingGroup() != null) {
+                Group group = groupDAO.findByName(intAttrName.getEnclosingGroup());
+                if (group == null || groupableRelatable.getMembership(group.getKey()) == null) {
+                    LOG.warn("No membership for {} in {}, ignoring",
+                            intAttrName.getEnclosingGroup(), groupableRelatable);
+                } else {
+                    reference = group;
+                }
+            } else if (intAttrName.getRelatedAnyObject() != null) {
+                AnyObject anyObject = anyObjectDAO.findByName(intAttrName.getRelatedAnyObject());
+                if (anyObject == null || groupableRelatable.getRelationships(anyObject.getKey()).isEmpty()) {
+                    LOG.warn("No relationship for {} in {}, ignoring",
+                            intAttrName.getRelatedAnyObject(), groupableRelatable);
+                } else {
+                    reference = anyObject;
+                }
+            } else if (intAttrName.getMembershipOfGroup() != null) {
+                Group group = groupDAO.findByName(intAttrName.getMembershipOfGroup());
+                membership = groupableRelatable.getMembership(group.getKey());
+            }
+        }
+        if (reference == null) {
+            LOG.warn("Could not determine the reference instance for {}", mapItem.getIntAttrName());
+            return Collections.emptyList();
+        }
 
         List<PlainAttrValue> values = new ArrayList<>();
         boolean transform = true;
 
         if (intAttrName.getField() != null) {
+            AnyUtils anyUtils = anyUtilsFactory.getInstance(reference);
+            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+
             switch (intAttrName.getField()) {
                 case "key":
-                    for (Any<?> any : anys) {
-                        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                        PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                        attrValue.setStringValue(any.getKey());
-                        values.add(attrValue);
-                    }
+                    attrValue.setStringValue(reference.getKey());
+                    values.add(attrValue);
+                    break;
+
+                case "password":
+                    // ignore
                     break;
 
                 case "username":
-                    for (Any<?> any : anys) {
-                        if (any instanceof User) {
-                            UPlainAttrValue attrValue = entityFactory.newEntity(UPlainAttrValue.class);
-                            attrValue.setStringValue(((User) any).getUsername());
-                            values.add(attrValue);
-                        }
+                    if (reference instanceof User) {
+                        attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                        attrValue.setStringValue(((User) reference).getUsername());
+                        values.add(attrValue);
                     }
                     break;
 
                 case "name":
-                    for (Any<?> any : anys) {
-                        if (any instanceof Group) {
-                            GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
-                            attrValue.setStringValue(((Group) any).getName());
-                            values.add(attrValue);
-                        } else if (any instanceof AnyObject) {
-                            APlainAttrValue attrValue = entityFactory.newEntity(APlainAttrValue.class);
-                            attrValue.setStringValue(((AnyObject) any).getName());
-                            values.add(attrValue);
-                        }
+                    if (reference instanceof Group) {
+                        attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                        attrValue.setStringValue(((Group) reference).getName());
+                        values.add(attrValue);
+                    } else if (reference instanceof AnyObject) {
+                        attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                        attrValue.setStringValue(((AnyObject) reference).getName());
+                        values.add(attrValue);
                     }
                     break;
 
-                case "owner":
+                case "userOwner":
+                case "groupOwner":
                     Mapping uMapping = provision.getAnyType().equals(anyTypeDAO.findUser())
                             ? provision.getMapping()
                             : null;
@@ -595,44 +391,53 @@ public class MappingManagerImpl implements MappingManager {
                             ? provision.getMapping()
                             : null;
 
-                    for (Any<?> any : anys) {
-                        if (any instanceof Group) {
-                            Group group = (Group) any;
-                            String groupOwnerValue = null;
-                            if (group.getUserOwner() != null && uMapping != null) {
-                                groupOwnerValue = getGroupOwnerValue(provision, group.getUserOwner());
-                            }
-                            if (group.getGroupOwner() != null && gMapping != null) {
-                                groupOwnerValue = getGroupOwnerValue(provision, group.getGroupOwner());
-                            }
+                    if (reference instanceof Group) {
+                        Group group = (Group) reference;
+                        String groupOwnerValue = null;
+                        if (group.getUserOwner() != null && uMapping != null) {
+                            groupOwnerValue = getGroupOwnerValue(provision, group.getUserOwner());
+                        }
+                        if (group.getGroupOwner() != null && gMapping != null) {
+                            groupOwnerValue = getGroupOwnerValue(provision, group.getGroupOwner());
+                        }
 
-                            if (StringUtils.isNotBlank(groupOwnerValue)) {
-                                GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
-                                attrValue.setStringValue(groupOwnerValue);
-                                values.add(attrValue);
-                            }
+                        if (StringUtils.isNotBlank(groupOwnerValue)) {
+                            attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                            attrValue.setStringValue(groupOwnerValue);
+                            values.add(attrValue);
                         }
                     }
                     break;
 
                 default:
+                    try {
+                        attrValue.setStringValue(FieldUtils.readField(
+                                reference, intAttrName.getField(), true).toString());
+                        values.add(attrValue);
+                    } catch (IllegalAccessException e) {
+                        LOG.error("Could not read value of '{}' from {}", intAttrName.getField(), reference, e);
+                    }
             }
         } else if (intAttrName.getSchemaType() != null) {
             switch (intAttrName.getSchemaType()) {
                 case PLAIN:
-                    for (Any<?> any : anys) {
-                        PlainAttr<?> attr = any.getPlainAttr(intAttrName.getSchemaName());
-                        if (attr != null) {
-                            if (attr.getUniqueValue() != null) {
-                                PlainAttrUniqueValue value = SerializationUtils.clone(attr.getUniqueValue());
-                                value.setAttr(null);
-                                values.add(value);
-                            } else if (attr.getValues() != null) {
-                                for (PlainAttrValue value : attr.getValues()) {
-                                    PlainAttrValue shadow = SerializationUtils.clone(value);
-                                    shadow.setAttr(null);
-                                    values.add(shadow);
-                                }
+                    PlainAttr<?> attr;
+                    if (membership == null) {
+                        attr = reference.getPlainAttr(intAttrName.getSchemaName());
+                    } else {
+                        attr = ((GroupableRelatable<?, ?, ?, ?, ?>) reference).getPlainAttr(
+                                intAttrName.getSchemaName(), membership);
+                    }
+                    if (attr != null) {
+                        if (attr.getUniqueValue() != null) {
+                            PlainAttrUniqueValue value = SerializationUtils.clone(attr.getUniqueValue());
+                            value.setAttr(null);
+                            values.add(value);
+                        } else if (attr.getValues() != null) {
+                            for (PlainAttrValue value : attr.getValues()) {
+                                PlainAttrValue shadow = SerializationUtils.clone(value);
+                                shadow.setAttr(null);
+                                values.add(shadow);
                             }
                         }
                     }
@@ -641,14 +446,14 @@ public class MappingManagerImpl implements MappingManager {
                 case DERIVED:
                     DerSchema derSchema = derSchemaDAO.find(intAttrName.getSchemaName());
                     if (derSchema != null) {
-                        for (Any<?> any : anys) {
-                            String value = derAttrHandler.getValue(any, derSchema);
-                            if (value != null) {
-                                AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                                PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                                attrValue.setStringValue(value);
-                                values.add(attrValue);
-                            }
+                        String value = membership == null
+                                ? derAttrHandler.getValue(reference, derSchema)
+                                : derAttrHandler.getValue(reference, membership, derSchema);
+                        if (value != null) {
+                            AnyUtils anyUtils = anyUtilsFactory.getInstance(reference);
+                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                            attrValue.setStringValue(value);
+                            values.add(attrValue);
                         }
                     }
                     break;
@@ -659,16 +464,18 @@ public class MappingManagerImpl implements MappingManager {
 
                     VirSchema virSchema = virSchemaDAO.find(intAttrName.getSchemaName());
                     if (virSchema != null) {
-                        for (Any<?> any : anys) {
-                            LOG.debug("Expire entry cache {}-{}", any.getKey(), intAttrName.getSchemaName());
-                            virAttrCache.expire(any.getType().getKey(), any.getKey(), intAttrName.getSchemaName());
-
-                            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                            for (String value : virAttrHandler.getValues(any, virSchema)) {
-                                PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                                attrValue.setStringValue(value);
-                                values.add(attrValue);
-                            }
+                        LOG.debug("Expire entry cache {}-{}", reference, intAttrName.getSchemaName());
+                        virAttrCache.expire(
+                                reference.getType().getKey(), reference.getKey(), intAttrName.getSchemaName());
+
+                        AnyUtils anyUtils = anyUtilsFactory.getInstance(reference);
+                        List<String> virValues = membership == null
+                                ? virAttrHandler.getValues(reference, virSchema)
+                                : virAttrHandler.getValues(reference, membership, virSchema);
+                        for (String value : virValues) {
+                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                            attrValue.setStringValue(value);
+                            values.add(attrValue);
                         }
                     }
                     break;
@@ -677,14 +484,14 @@ public class MappingManagerImpl implements MappingManager {
             }
         }
 
-        LOG.debug("Values for propagation: {}", values);
+        LOG.debug("Internal values: {}", values);
 
         List<PlainAttrValue> transformed = values;
         if (transform) {
-            for (MappingItemTransformer transformer : getMappingItemTransformers(mapItem)) {
-                transformed = transformer.beforePropagation(mapItem, anys, transformed);
+            for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(mapItem)) {
+                transformed = transformer.beforePropagation(mapItem, any, transformed);
             }
-            LOG.debug("Transformed values for propagation: {}", values);
+            LOG.debug("Transformed values: {}", values);
         } else {
             LOG.debug("No transformation occurred");
         }
@@ -692,12 +499,24 @@ public class MappingManagerImpl implements MappingManager {
         return transformed;
     }
 
+    private String getGroupOwnerValue(final Provision provision, final Any<?> any) {
+        Pair<String, Attribute> preparedAttr =
+                prepareAttr(provision, MappingUtils.getConnObjectKeyItem(provision), any, null);
+        String connObjectKey = preparedAttr.getKey();
+
+        return MappingUtils.evaluateNAME(any, provision, connObjectKey).getNameValue();
+    }
+
     @Transactional(readOnly = true)
     @Override
     public String getConnObjectKeyValue(final Any<?> any, final Provision provision) {
-        List<PlainAttrValue> values = getIntValues(provision, provision.getMapping().getConnObjectKeyItem(),
-                Collections.<Any<?>>singletonList(any));
-        return values == null || values.isEmpty()
+        MappingItem mapItem = provision.getMapping().getConnObjectKeyItem();
+        List<PlainAttrValue> values = getIntValues(
+                provision,
+                mapItem,
+                intAttrNameParser.parse(mapItem.getIntAttrName(), provision.getAnyType().getKind()),
+                any);
+        return values.isEmpty()
                 ? null
                 : values.get(0).getValueAsString();
     }
@@ -710,20 +529,17 @@ public class MappingManagerImpl implements MappingManager {
         List<Object> values = null;
         if (attr != null) {
             values = attr.getValue();
-            for (MappingItemTransformer transformer : getMappingItemTransformers(mapItem)) {
+            for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(mapItem)) {
                 values = transformer.beforePull(mapItem, anyTO, values);
             }
         }
         values = ListUtils.emptyIfNull(values);
 
         IntAttrName intAttrName =
-                IntAttrNameParser.parse(mapItem.getIntAttrName(), anyUtilsFactory, anyUtils.getAnyTypeKind());
+                intAttrNameParser.parse(mapItem.getIntAttrName(), anyUtils.getAnyTypeKind());
 
         if (intAttrName.getField() != null) {
             switch (intAttrName.getField()) {
-                case "key":
-                    break;
-
                 case "password":
                     if (anyTO instanceof UserTO && !values.isEmpty()) {
                         ((UserTO) anyTO).setPassword(ConnObjectUtils.getPassword(values.get(0)));
@@ -750,7 +566,8 @@ public class MappingManagerImpl implements MappingManager {
                     }
                     break;
 
-                case "owner":
+                case "userOwner":
+                case "groupOwner":
                     if (anyTO instanceof GroupTO && attr != null) {
                         // using a special attribute (with schema "", that will be ignored) for carrying the
                         // GroupOwnerSchema value
@@ -769,6 +586,13 @@ public class MappingManagerImpl implements MappingManager {
                 default:
             }
         } else if (intAttrName.getSchemaType() != null) {
+            GroupableRelatableTO groupableTO = null;
+            Group group = null;
+            if (anyTO instanceof GroupableRelatableTO && intAttrName.getMembershipOfGroup() != null) {
+                groupableTO = (GroupableRelatableTO) anyTO;
+                group = groupDAO.findByName(intAttrName.getMembershipOfGroup());
+            }
+
             switch (intAttrName.getSchemaType()) {
                 case PLAIN:
                     AttrTO attrTO = new AttrTO();
@@ -803,13 +627,31 @@ public class MappingManagerImpl implements MappingManager {
                         }
                     }
 
-                    anyTO.getPlainAttrs().add(attrTO);
+                    if (groupableTO == null || group == null) {
+                        anyTO.getPlainAttrs().add(attrTO);
+                    } else {
+                        MembershipTO membership = groupableTO.getMembershipMap().get(group.getKey());
+                        if (membership == null) {
+                            membership = new MembershipTO.Builder().group(group.getKey(), group.getName()).build();
+                            groupableTO.getMemberships().add(membership);
+                        }
+                        membership.getPlainAttrs().add(attrTO);
+                    }
                     break;
 
                 case DERIVED:
                     attrTO = new AttrTO();
                     attrTO.setSchema(intAttrName.getSchemaName());
-                    anyTO.getDerAttrs().add(attrTO);
+                    if (groupableTO == null || group == null) {
+                        anyTO.getDerAttrs().add(attrTO);
+                    } else {
+                        MembershipTO membership = groupableTO.getMembershipMap().get(group.getKey());
+                        if (membership == null) {
+                            membership = new MembershipTO.Builder().group(group.getKey(), group.getName()).build();
+                            groupableTO.getMemberships().add(membership);
+                        }
+                        membership.getDerAttrs().add(attrTO);
+                    }
                     break;
 
                 case VIRTUAL:
@@ -825,7 +667,16 @@ public class MappingManagerImpl implements MappingManager {
                         }
                     }
 
-                    anyTO.getVirAttrs().add(attrTO);
+                    if (groupableTO == null || group == null) {
+                        anyTO.getVirAttrs().add(attrTO);
+                    } else {
+                        MembershipTO membership = groupableTO.getMembershipMap().get(group.getKey());
+                        if (membership == null) {
+                            membership = new MembershipTO.Builder().group(group.getKey(), group.getName()).build();
+                            groupableTO.getMemberships().add(membership);
+                        }
+                        membership.getVirAttrs().add(attrTO);
+                    }
                     break;
 
                 default:

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
index 67a821c..85e6522 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -40,6 +40,7 @@ import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
 import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 import org.identityconnectors.framework.common.objects.Uid;
@@ -99,7 +100,7 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
         for (Map.Entry<Provision, Set<VirSchema>> entry : toRead.entrySet()) {
             LOG.debug("About to read from {}: {}", entry.getKey(), entry.getValue());
 
-            String connObjectKey = MappingManagerImpl.getConnObjectKeyItem(entry.getKey()) == null
+            String connObjectKey = MappingUtils.getConnObjectKeyItem(entry.getKey()) == null
                     ? null
                     : mappingManager.getConnObjectKeyValue(any, entry.getKey());
             if (StringUtils.isBlank(connObjectKey)) {
@@ -114,7 +115,7 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
                 try {
                     ConnectorObject connectorObject = connector.getObject(entry.getKey().getObjectClass(),
                             new Uid(connObjectKey),
-                            MappingManagerImpl.buildOperationOptions(linkingMappingItems.iterator()));
+                            MappingUtils.buildOperationOptions(linkingMappingItems.iterator()));
 
                     if (connectorObject == null) {
                         LOG.debug("No read from {} about {}", entry.getKey(), connObjectKey);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index ca94e16..b826b63 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -37,7 +37,6 @@ 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.ClientExceptionType;
-import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
@@ -59,7 +58,6 @@ import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -89,6 +87,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 
 abstract class AbstractAnyDataBinder {
 
@@ -154,6 +155,9 @@ abstract class AbstractAnyDataBinder {
     @Autowired
     protected MappingManager mappingManager;
 
+    @Autowired
+    protected IntAttrNameParser intAttrNameParser;
+
     protected void setRealm(final Any<?> any, final AnyPatch anyPatch) {
         if (anyPatch.getRealm() != null && StringUtils.isNotBlank(anyPatch.getRealm().getValue())) {
             Realm newRealm = realmDAO.findByFullPath(anyPatch.getRealm().getValue());
@@ -215,14 +219,13 @@ abstract class AbstractAnyDataBinder {
     private List<String> evaluateMandatoryCondition(final Provision provision, final Any<?> any) {
         List<String> missingAttrNames = new ArrayList<>();
 
-        if (provision != null) {
-            for (MappingItem item : provision.getMapping().getItems()) {
-                if ((item.getPurpose() == MappingPurpose.PROPAGATION || item.getPurpose() == MappingPurpose.BOTH)) {
-                    List<PlainAttrValue> values = mappingManager.getIntValues(
-                            provision, item, Collections.<Any<?>>singletonList(any));
-                    if (values.isEmpty() && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
-                        missingAttrNames.add(item.getIntAttrName());
-                    }
+        for (MappingItem mapItem : MappingUtils.getPropagationMappingItems(provision)) {
+            IntAttrName intAttrName =
+                    intAttrNameParser.parse(mapItem.getIntAttrName(), provision.getAnyType().getKind());
+            if (intAttrName.getSchemaType() != null) {
+                List<PlainAttrValue> values = mappingManager.getIntValues(provision, mapItem, intAttrName, any);
+                if (values.isEmpty() && JexlUtils.evaluateMandatoryCondition(mapItem.getMandatoryCondition(), any)) {
+                    missingAttrNames.add(mapItem.getIntAttrName());
                 }
             }
         }
@@ -230,9 +233,7 @@ abstract class AbstractAnyDataBinder {
         return missingAttrNames;
     }
 
-    private SyncopeClientException checkMandatoryOnResources(
-            final Any<?> any, final Set<ExternalResource> resources) {
-
+    private SyncopeClientException checkMandatoryOnResources(final Any<?> any, final Set<ExternalResource> resources) {
         SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
         for (ExternalResource resource : resources) {
@@ -338,13 +339,11 @@ abstract class AbstractAnyDataBinder {
         }
 
         for (ExternalResource resource : resources) {
-            for (MappingItem mapItem
-                    : MappingManagerImpl.getPropagationMappingItems(resource.getProvision(any.getType()))) {
-
-                if (schema.getKey().equals(mapItem.getIntAttrName())) {
+            for (MappingItem item : MappingUtils.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+                if (schema.getKey().equals(item.getIntAttrName())) {
                     propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 
-                    if (mapItem.isConnObjectKey() && !attr.getValuesAsStrings().isEmpty()) {
+                    if (item.isConnObjectKey() && !attr.getValuesAsStrings().isEmpty()) {
                         propByRes.addOldConnObjectKey(resource.getKey(), attr.getValuesAsStrings().get(0));
                     }
                 }
@@ -646,7 +645,7 @@ abstract class AbstractAnyDataBinder {
         for (ExternalResource resource : iterable) {
             Provision provision = resource.getProvision(any.getType());
             if (provision != null && provision.getMapping() != null) {
-                MappingItem connObjectKeyItem = MappingManagerImpl.getConnObjectKeyItem(provision);
+                MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
                 if (connObjectKeyItem == null) {
                     throw new NotFoundException(
                             "ConnObjectKey mapping for " + any.getType().getKey() + " " + any.getKey()

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
index 7ed913d..37a471c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/DefaultMappingItemTransformer.java
@@ -35,7 +35,7 @@ public class DefaultMappingItemTransformer implements MappingItemTransformer {
     @Override
     public List<PlainAttrValue> beforePropagation(
             final MappingItem mappingItem,
-            final List<Any<?>> anys,
+            final Any<?> any,
             final List<PlainAttrValue> values) {
 
         return values;

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformer.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformer.java
index e4e155a..6fef0bb 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformer.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/JEXLMappingItemTransformer.java
@@ -20,18 +20,13 @@ package org.apache.syncope.core.provisioning.java.data;
 
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.commons.collections4.IterableUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.jexl3.JexlContext;
 import org.apache.commons.jexl3.MapContext;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
 
 /**
@@ -55,47 +50,10 @@ public class JEXLMappingItemTransformer extends DefaultMappingItemTransformer {
     @Override
     public List<PlainAttrValue> beforePropagation(
             final MappingItem mappingItem,
-            final List<Any<?>> anys,
+            final Any<?> any,
             final List<PlainAttrValue> values) {
 
         if (StringUtils.isNotBlank(propagationJEXL) && values != null) {
-            Any<?> any = null;
-            if (!anys.isEmpty()) {
-                switch (mappingItem.getMapping().getProvision().getAnyType().getKind()) {
-                    case USER:
-                        any = IterableUtils.find(anys, new Predicate<Any<?>>() {
-
-                            @Override
-                            public boolean evaluate(final Any<?> object) {
-                                return object instanceof User;
-                            }
-                        });
-                        break;
-
-                    case GROUP:
-                        any = IterableUtils.find(anys, new Predicate<Any<?>>() {
-
-                            @Override
-                            public boolean evaluate(final Any<?> object) {
-                                return object instanceof Group;
-                            }
-                        });
-                        break;
-
-                    case ANY_OBJECT:
-                        any = IterableUtils.find(anys, new Predicate<Any<?>>() {
-
-                            @Override
-                            public boolean evaluate(final Any<?> object) {
-                                return object instanceof AnyObject;
-                            }
-                        });
-                        break;
-
-                    default:
-                }
-            }
-
             for (PlainAttrValue value : values) {
                 JexlContext jexlContext = new MapContext();
                 if (any != null) {
@@ -111,7 +69,7 @@ public class JEXLMappingItemTransformer extends DefaultMappingItemTransformer {
             return values;
         }
 
-        return super.beforePropagation(mappingItem, anys, values);
+        return super.beforePropagation(mappingItem, any, values);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
index a9de5bd..11b4cb0 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
@@ -34,9 +34,8 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.MailTemplateDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.MailTemplate;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -59,7 +58,7 @@ public class NotificationDataBinderImpl implements NotificationDataBinder {
     private EntityFactory entityFactory;
 
     @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
+    private IntAttrNameParser intAttrNameParser;
 
     @Override
     public NotificationTO getNotificationTO(final Notification notification) {
@@ -126,6 +125,6 @@ public class NotificationDataBinderImpl implements NotificationDataBinder {
         });
 
         // 3. verify recipientAttrName
-        IntAttrNameParser.parse(notification.getRecipientAttrName(), anyUtilsFactory, AnyTypeKind.USER);
+        intAttrNameParser.parse(notification.getRecipientAttrName(), AnyTypeKind.USER);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index ddf5a14..7eea744 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -31,6 +31,7 @@ import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
@@ -48,14 +49,13 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.identityconnectors.framework.common.objects.ObjectClass;
@@ -90,7 +90,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
     private EntityFactory entityFactory;
 
     @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
+    private IntAttrNameParser intAttrNameParser;
 
     @Override
     public ExternalResource create(final ResourceTO resourceTO) {
@@ -268,30 +268,29 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             if (itemTO == null) {
                 LOG.error("Null {}", MappingItemTO.class.getSimpleName());
                 invalidMapping.getElements().add("Null " + MappingItemTO.class.getSimpleName());
+            } else if (itemTO.getIntAttrName() == null) {
+                requiredValuesMissing.getElements().add("intAttrName");
+                scce.addException(requiredValuesMissing);
             } else {
-                if (itemTO.getIntAttrName() == null) {
-                    requiredValuesMissing.getElements().add("intAttrName");
-                    scce.addException(requiredValuesMissing);
-                }
-
-                IntAttrName intAttrName = IntAttrNameParser.parse(
+                IntAttrName intAttrName = intAttrNameParser.parse(
                         itemTO.getIntAttrName(),
-                        anyUtilsFactory,
                         mapping.getProvision().getAnyType().getKind());
 
                 boolean allowed = true;
-                if (intAttrName.getSchemaType() != null) {
+                if (intAttrName.getSchemaType() != null
+                        && intAttrName.getEnclosingGroup() == null && intAttrName.getRelatedAnyObject() == null) {
+
                     switch (intAttrName.getSchemaType()) {
                         case PLAIN:
-                            allowed = allowedSchemas.getPlainSchemas().contains(itemTO.getIntAttrName());
+                            allowed = allowedSchemas.getPlainSchemas().contains(intAttrName.getSchemaName());
                             break;
 
                         case DERIVED:
-                            allowed = allowedSchemas.getDerSchemas().contains(itemTO.getIntAttrName());
+                            allowed = allowedSchemas.getDerSchemas().contains(intAttrName.getSchemaName());
                             break;
 
                         case VIRTUAL:
-                            allowed = allowedSchemas.getVirSchemas().contains(itemTO.getIntAttrName());
+                            allowed = allowedSchemas.getVirSchemas().contains(intAttrName.getSchemaName());
                             break;
 
                         default:
@@ -324,6 +323,37 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                     } else {
                         mapping.add(item);
                     }
+
+                    if (intAttrName.getEnclosingGroup() != null
+                            && item.getPurpose() != MappingPurpose.PROPAGATION) {
+
+                        invalidMapping.getElements().add(
+                                "Only " + MappingPurpose.PROPAGATION.name() + " allowed when referring to groups");
+                    }
+                    if (intAttrName.getRelatedAnyObject() != null
+                            && item.getPurpose() != MappingPurpose.PROPAGATION) {
+
+                        invalidMapping.getElements().add(
+                                "Only " + MappingPurpose.PROPAGATION.name() + " allowed when referring to any objects");
+                    }
+                    if (intAttrName.getSchemaType() == SchemaType.DERIVED
+                            && item.getPurpose() != MappingPurpose.PROPAGATION) {
+
+                        invalidMapping.getElements().add(
+                                "Only " + MappingPurpose.PROPAGATION.name() + " allowed for derived");
+                    }
+                    if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
+                        if (item.getPurpose() != MappingPurpose.PROPAGATION) {
+                            invalidMapping.getElements().add(
+                                    "Only " + MappingPurpose.PROPAGATION.name() + " allowed for virtual");
+                        }
+
+                        VirSchema schema = virSchemaDAO.find(item.getIntAttrName());
+                        if (schema != null && schema.getProvision().equals(item.getMapping().getProvision())) {
+                            invalidMapping.getElements().add(
+                                    "No need to map virtual schema on linking resource");
+                        }
+                    }
                 } else {
                     LOG.error("{} not allowed", itemTO.getIntAttrName());
                     invalidMapping.getElements().add(itemTO.getIntAttrName() + " not allowed");

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 1581463..5a532d7 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
@@ -159,8 +159,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             CipherAlgorithm predefined = CipherAlgorithm.valueOf(algorithm);
             user.setPassword(password, predefined);
         } catch (IllegalArgumentException e) {
-            final SyncopeClientException invalidCiperAlgorithm =
-                    SyncopeClientException.build(ClientExceptionType.NotFound);
+            SyncopeClientException invalidCiperAlgorithm = SyncopeClientException.build(ClientExceptionType.NotFound);
             invalidCiperAlgorithm.getElements().add(e.getMessage());
             scce.addException(invalidCiperAlgorithm);
 
@@ -305,7 +304,7 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
     @Override
     public PropagationByResource update(final User toBeUpdated, final UserPatch userPatch) {
         // Re-merge any pending change from workflow tasks
-        final User user = userDAO.save(toBeUpdated);
+        User user = userDAO.save(toBeUpdated);
 
         PropagationByResource propByRes = new PropagationByResource();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index d0229f9..3509bfe 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -62,13 +62,13 @@ import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
@@ -153,7 +153,7 @@ public class NotificationManagerImpl implements NotificationManager {
     private EntityFactory entityFactory;
 
     @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
+    private IntAttrNameParser intAttrNameParser;
 
     @Transactional(readOnly = true)
     @Override
@@ -346,14 +346,24 @@ public class NotificationManagerImpl implements NotificationManager {
     private String getRecipientEmail(final String recipientAttrName, final User user) {
         String email = null;
 
-        IntAttrName intAttrName = IntAttrNameParser.parse(recipientAttrName, anyUtilsFactory, AnyTypeKind.USER);
+        IntAttrName intAttrName = intAttrNameParser.parse(recipientAttrName, AnyTypeKind.USER);
 
         if ("username".equals(intAttrName.getField())) {
             email = user.getUsername();
         } else if (intAttrName.getSchemaType() != null) {
+            UMembership membership = null;
+            if (intAttrName.getMembershipOfGroup() != null) {
+                Group group = groupDAO.findByName(intAttrName.getMembershipOfGroup());
+                if (group != null) {
+                    membership = user.getMembership(group.getKey());
+                }
+            }
+
             switch (intAttrName.getSchemaType()) {
                 case PLAIN:
-                    UPlainAttr attr = user.getPlainAttr(recipientAttrName);
+                    UPlainAttr attr = membership == null
+                            ? user.getPlainAttr(recipientAttrName)
+                            : user.getPlainAttr(recipientAttrName, membership);
                     if (attr != null) {
                         email = attr.getValuesAsStrings().isEmpty() ? null : attr.getValuesAsStrings().get(0);
                     }
@@ -364,7 +374,9 @@ public class NotificationManagerImpl implements NotificationManager {
                     if (schema == null) {
                         LOG.warn("Ignoring non existing {} {}", DerSchema.class.getSimpleName(), recipientAttrName);
                     } else {
-                        email = derAttrHander.getValue(user, schema);
+                        email = membership == null
+                                ? derAttrHander.getValue(user, schema)
+                                : derAttrHander.getValue(user, membership, schema);
                     }
                     break;
 
@@ -373,7 +385,9 @@ public class NotificationManagerImpl implements NotificationManager {
                     if (virSchema == null) {
                         LOG.warn("Ignoring non existing {} {}", VirSchema.class.getSimpleName(), recipientAttrName);
                     } else {
-                        List<String> virAttrValues = virAttrHander.getValues(user, virSchema);
+                        List<String> virAttrValues = membership == null
+                                ? virAttrHander.getValues(user, virSchema)
+                                : virAttrHander.getValues(user, membership, virSchema);
                         email = virAttrValues.isEmpty() ? null : virAttrValues.get(0);
                     }
                     break;

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
index 9069b7a..a1b5434 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
@@ -47,7 +47,6 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecu
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
 import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
@@ -63,6 +62,7 @@ import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
 import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.exceptions.ConnectorException;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -599,8 +599,8 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         try {
             obj = connector.getObject(new ObjectClass(task.getObjectClassName()),
                     new Uid(connObjectKey),
-                    MappingManagerImpl.buildOperationOptions(IteratorUtils.chainedIterator(
-                            MappingManagerImpl.getPropagationMappingItems(provision).iterator(),
+                    MappingUtils.buildOperationOptions(IteratorUtils.chainedIterator(
+                            MappingUtils.getPropagationMappingItems(provision).iterator(),
                             linkingMappingItems.iterator())));
 
             for (MappingItem item : linkingMappingItems) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
index 96b37c7..a0007f1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
@@ -44,7 +44,6 @@ import org.apache.syncope.core.provisioning.api.WorkflowResult;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -59,6 +58,7 @@ import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.MappingManager;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -375,7 +375,7 @@ public class PropagationManagerImpl implements PropagationManager {
             Provision provision = resource == null ? null : resource.getProvision(any.getType());
             List<MappingItem> mappingItems = provision == null
                     ? Collections.<MappingItem>emptyList()
-                    : MappingManagerImpl.getPropagationMappingItems(provision);
+                    : MappingUtils.getPropagationMappingItems(provision);
 
             if (resource == null) {
                 LOG.error("Invalid resource name specified: {}, ignoring...", entry.getKey());

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
index 41edc94..31732fd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java
@@ -37,7 +37,6 @@ import org.apache.syncope.core.persistence.api.entity.task.PushTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
 import org.apache.syncope.core.provisioning.api.pushpull.PushActions;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
@@ -48,6 +47,7 @@ import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.TimeoutException;
 import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException;
 import org.apache.syncope.core.provisioning.api.pushpull.SyncopePushResultHandler;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.identityconnectors.framework.common.objects.Uid;
@@ -134,7 +134,7 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
 
             obj = profile.getConnector().getObject(objectClass,
                     uid,
-                    MappingManagerImpl.buildOperationOptions(IteratorUtils.<MappingItem>emptyIterator()));
+                    MappingUtils.buildOperationOptions(IteratorUtils.<MappingItem>emptyIterator()));
         } catch (TimeoutException toe) {
             LOG.debug("Request timeout", toe);
             throw toe;

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
index 990127a..e5a1c88 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PlainAttrsPullCorrelationRule.java
@@ -22,7 +22,6 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
 import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
@@ -32,6 +31,7 @@ import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 
 public class PlainAttrsPullCorrelationRule implements PullCorrelationRule {
 
@@ -47,7 +47,7 @@ public class PlainAttrsPullCorrelationRule implements PullCorrelationRule {
     @Override
     public SearchCond getSearchCond(final ConnectorObject connObj) {
         Map<String, MappingItem> mappingItems = new HashMap<>();
-        for (MappingItem item : MappingManagerImpl.getPullMappingItems(provision)) {
+        for (MappingItem item : MappingUtils.getPullMappingItems(provision)) {
             mappingItems.put(item.getIntAttrName(), item);
         }
 
@@ -65,7 +65,7 @@ public class PlainAttrsPullCorrelationRule implements PullCorrelationRule {
             }
 
             List<Object> values = attr.getValue();
-            for (MappingItemTransformer transformer : MappingManagerImpl.getMappingItemTransformers(mappingItem)) {
+            for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(mappingItem)) {
                 values = transformer.beforePull(mappingItem, null, values);
             }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
index 4c1b3cb..b5a7dfe 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -28,7 +28,6 @@ import java.util.Set;
 import org.apache.commons.collections4.IteratorUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.policy.PullPolicySpec;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
@@ -52,6 +51,7 @@ import org.apache.syncope.core.provisioning.api.pushpull.GroupPullResultHandler;
 import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullExecutor;
 import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullResultHandler;
 import org.apache.syncope.core.provisioning.api.pushpull.UserPullResultHandler;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 import org.identityconnectors.framework.common.objects.SyncToken;
 
@@ -157,7 +157,7 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
         ghandler.setPullExecutor(this);
 
         latestSyncTokens.clear();
-        
+
         if (!profile.isDryRun()) {
             for (PullActions action : actions) {
                 action.beforeAll(profile);
@@ -196,7 +196,7 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
                                     provision.getObjectClass(),
                                     provision.getSyncToken(),
                                     handler,
-                                    MappingManagerImpl.buildOperationOptions(mapItems));
+                                    MappingUtils.buildOperationOptions(mapItems));
                             if (!dryRun) {
                                 provision.setSyncToken(latestSyncTokens.get(provision.getObjectClass()));
                                 resourceDAO.save(provision.getResource());
@@ -211,14 +211,14 @@ public class PullJobDelegate extends AbstractProvisioningJobDelegate<PullTask> i
                             connector.filteredReconciliation(provision.getObjectClass(),
                                     filterBuilder,
                                     handler,
-                                    MappingManagerImpl.buildOperationOptions(mapItems));
+                                    MappingUtils.buildOperationOptions(mapItems));
                             break;
 
                         case FULL_RECONCILIATION:
                         default:
                             connector.fullReconciliation(provision.getObjectClass(),
                                     handler,
-                                    MappingManagerImpl.buildOperationOptions(mapItems));
+                                    MappingUtils.buildOperationOptions(mapItems));
                             break;
                     }
                 } catch (Throwable t) {


[08/15] syncope git commit: Unique schema key across the three tables

Posted by il...@apache.org.
Unique schema key across the three tables


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

Branch: refs/heads/SYNCOPE-862
Commit: a4afd4a22daaff2c353de44d52dfc41412cdea4a
Parents: 579f4b0
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Thu Jun 9 18:20:30 2016 +0200
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Tue Jun 14 17:59:30 2016 +0200

----------------------------------------------------------------------
 .../notification/NotificationResultManager.java |   1 -
 .../resource/ResourceResultManager.java         |   1 -
 .../syncope/common/lib/EntityTOUtils.java       |  18 -
 .../lib/policy/DefaultAccountRuleConf.java      |   7 +-
 .../lib/policy/DefaultPasswordRuleConf.java     |   7 +-
 .../common/lib/report/GroupReportletConf.java   |   9 +-
 .../syncope/common/lib/report/Schema.java       |   7 +-
 .../common/lib/report/UserReportletConf.java    |   9 +-
 .../common/lib/search/SearchableFields.java     |  17 +
 .../syncope/common/lib/to/MappingItemTO.java    |  14 -
 .../apache/syncope/common/lib/to/MappingTO.java |  12 -
 .../syncope/common/lib/to/NotificationTO.java   |  11 -
 .../common/lib/types/EntityViolationType.java   |   2 +-
 .../common/lib/types/IntMappingType.java        | 203 --------
 .../api/dao/ExternalResourceDAO.java            |   3 +-
 .../core/persistence/api/entity/AnyUtils.java   |   9 +-
 .../api/entity/LinkingMappingItem.java          |  21 -
 .../persistence/api/entity/Notification.java    |   5 -
 .../api/entity/resource/MappingItem.java        |   5 -
 .../api/search/SearchCondVisitor.java           |   4 +-
 .../persistence/jpa/dao/JPADerSchemaDAO.java    |   8 +-
 .../jpa/dao/JPAExternalResourceDAO.java         |  10 +-
 .../persistence/jpa/dao/JPAPlainSchemaDAO.java  |   2 +-
 .../persistence/jpa/dao/JPAVirSchemaDAO.java    |  11 +-
 .../persistence/jpa/entity/AbstractSchema.java  |  40 ++
 .../persistence/jpa/entity/JPAAnyUtils.java     | 131 +++--
 .../persistence/jpa/entity/JPADerSchema.java    |   8 +-
 .../persistence/jpa/entity/JPANotification.java |  15 -
 .../persistence/jpa/entity/JPAPlainSchema.java  |   6 +-
 .../persistence/jpa/entity/JPAVirSchema.java    |   8 +-
 .../entity/anyobject/JPAAPlainAttrValue.java    |   3 -
 .../jpa/entity/conf/JPACPlainAttrValue.java     |   3 -
 .../jpa/entity/group/JPAGPlainAttrValue.java    |   3 -
 .../jpa/entity/resource/JPAMapping.java         |  23 +-
 .../jpa/entity/resource/JPAMappingItem.java     |  50 +-
 .../jpa/entity/user/JPAUPlainAttrValue.java     |   3 -
 .../validation/entity/AbstractValidator.java    |   2 +-
 .../jpa/validation/entity/DomainValidator.java  |  12 +-
 .../entity/ExternalResourceValidator.java       |  64 +--
 .../validation/entity/PlainSchemaValidator.java |  36 +-
 .../entity/RelationshipTypeValidator.java       |   4 +-
 .../jpa/validation/entity/RoleValidator.java    |   6 +-
 .../validation/entity/SchemaKeyValidator.java   |  62 +--
 .../main/resources/domains/MasterContent.xml    |  17 +-
 .../core/persistence/jpa/inner/ConfTest.java    |   2 +-
 .../persistence/jpa/inner/DerSchemaTest.java    |   2 +-
 .../persistence/jpa/inner/NotificationTest.java |   4 -
 .../persistence/jpa/inner/PlainSchemaTest.java  |   7 +-
 .../persistence/jpa/inner/ResourceTest.java     |  30 +-
 .../persistence/jpa/inner/VirSchemaTest.java    |   2 +-
 .../persistence/jpa/outer/PlainSchemaTest.java  |  24 +
 .../persistence/jpa/outer/ResourceTest.java     |   5 -
 .../persistence/jpa/outer/VirSchemaTest.java    |   2 -
 .../test/resources/domains/MasterContent.xml    | 187 ++++---
 .../src/test/resources/domains/TwoContent.xml   |  11 +
 .../provisioning/api/IntAttrNameParser.java     | 140 ++++++
 .../core/provisioning/api/MappingManager.java   |   8 +-
 .../provisioning/java/MappingManagerImpl.java   | 501 +++++++++----------
 .../java/data/AbstractAnyDataBinder.java        |  16 +-
 .../java/data/NotificationDataBinderImpl.java   |   9 +
 .../java/data/ResourceDataBinderImpl.java       |  76 +--
 .../notification/NotificationManagerImpl.java   |  76 +--
 .../provisioning/java/pushpull/PullUtils.java   | 126 ++---
 .../java/ResourceDataBinderTest.java            |   2 -
 .../syncope/fit/core/ConfigurationITCase.java   |   2 +-
 .../syncope/fit/core/ConnectorITCase.java       |   2 -
 .../syncope/fit/core/DerSchemaITCase.java       |   2 +-
 .../apache/syncope/fit/core/GroupITCase.java    |   3 -
 .../syncope/fit/core/MigrationITCase.java       |  17 -
 .../syncope/fit/core/MultitenancyITCase.java    |   7 +-
 .../syncope/fit/core/NotificationITCase.java    |   2 -
 .../fit/core/NotificationTaskITCase.java        |   3 -
 .../syncope/fit/core/PlainSchemaITCase.java     |   4 +-
 .../apache/syncope/fit/core/PushTaskITCase.java |   3 -
 .../apache/syncope/fit/core/ResourceITCase.java |  36 +-
 .../apache/syncope/fit/core/VirAttrITCase.java  |   4 -
 .../syncope/fit/core/VirSchemaITCase.java       |   2 +-
 77 files changed, 953 insertions(+), 1256 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationResultManager.java
index 951f1c1..a364316 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationResultManager.java
@@ -40,7 +40,6 @@ public class NotificationResultManager extends CommonsResultManager {
         System.out.println("    recipient attribute name: " + notificationTO.getRecipientAttrName());
         System.out.println("    template: " + notificationTO.getTemplate());
         System.out.println("    abouts: " + notificationTO.getAbouts());
-        System.out.println("    recipient attribute types: " + notificationTO.getRecipientAttrType());
         System.out.println("    static recipient: " + notificationTO.getStaticRecipients());
         System.out.println("    trace level: " + notificationTO.getTraceLevel());
         System.out.println("    active: " + notificationTO.isActive());

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
index e396316..ca7c87a 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
@@ -77,7 +77,6 @@ public class ResourceResultManager extends CommonsResultManager {
     private void printMappingItem(final List<MappingItemTO> mappingItemTOs) {
         for (final MappingItemTO mappingItemTO : mappingItemTOs) {
             System.out.println("             mapping key: " + mappingItemTO.getKey());
-            System.out.println("             mapping item type: " + mappingItemTO.getIntMappingType().name());
             System.out.println("             internal attribute name: " + mappingItemTO.getIntAttrName());
             System.out.println("             external attribute name: " + mappingItemTO.getExtAttrName());
             System.out.println("             mandatory condition: " + mappingItemTO.getMandatoryCondition());

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/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 a715992..001e569 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
@@ -18,29 +18,11 @@
  */
 package org.apache.syncope.common.lib;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
 import org.apache.commons.collections4.Transformer;
-import org.apache.syncope.common.lib.search.SearchableFields;
-import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.EntityTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.UserTO;
 
 public final class EntityTOUtils {
 
-    public static final List<String> ANY_FIELDS;
-
-    static {
-        List<String> anyFields = new ArrayList<>();
-        anyFields.addAll(SearchableFields.get(UserTO.class));
-        anyFields.addAll(SearchableFields.get(GroupTO.class));
-        anyFields.addAll(SearchableFields.get(AnyObjectTO.class));
-
-        ANY_FIELDS = Collections.unmodifiableList(anyFields);
-    }
-
     public static <E extends EntityTO> Transformer<E, String> keyTransformer() {
         return new Transformer<E, String>() {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
index 1d7cdb3..2788a4a 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultAccountRuleConf.java
@@ -26,7 +26,8 @@ import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.report.Schema;
-import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 
 @XmlRootElement(name = "defaultAccountRuleConf")
 @XmlType
@@ -67,8 +68,8 @@ public class DefaultAccountRuleConf extends AbstractAccountRuleConf implements A
     /**
      * User attribute values not permitted.
      */
-    @Schema(type
-            = { IntMappingType.UserPlainSchema, IntMappingType.UserDerivedSchema, IntMappingType.UserVirtualSchema })
+    @Schema(anyTypeKind = AnyTypeKind.USER,
+            type = { SchemaType.PLAIN, SchemaType.DERIVED, SchemaType.VIRTUAL })
     private final List<String> schemasNotPermitted = new ArrayList<>();
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
index b75ff9c..b622546 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/DefaultPasswordRuleConf.java
@@ -26,7 +26,8 @@ import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.report.Schema;
-import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 
 @XmlRootElement(name = "defaultPasswordRuleConf")
 @XmlType
@@ -142,8 +143,8 @@ public class DefaultPasswordRuleConf extends AbstractPasswordRuleConf {
     /**
      * User attribute values not permitted.
      */
-    @Schema(type
-            = { IntMappingType.UserPlainSchema, IntMappingType.UserDerivedSchema, IntMappingType.UserVirtualSchema })
+    @Schema(anyTypeKind = AnyTypeKind.USER,
+            type = { SchemaType.PLAIN, SchemaType.DERIVED, SchemaType.VIRTUAL })
     private final List<String> schemasNotPermitted = new ArrayList<>();
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/report/GroupReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/GroupReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/GroupReportletConf.java
index 6712b30..6f3800a 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/report/GroupReportletConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/GroupReportletConf.java
@@ -26,7 +26,8 @@ import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlEnum;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 
 @XmlRootElement(name = "groupReportletConf")
 @XmlType
@@ -47,13 +48,13 @@ public class GroupReportletConf extends AbstractAnyReportletConf {
 
     }
 
-    @Schema(type = IntMappingType.GroupPlainSchema)
+    @Schema(anyTypeKind = AnyTypeKind.GROUP, type = { SchemaType.PLAIN })
     private final List<String> plainAttrs = new ArrayList<>();
 
-    @Schema(type = IntMappingType.GroupDerivedSchema)
+    @Schema(anyTypeKind = AnyTypeKind.GROUP, type = { SchemaType.DERIVED })
     private final List<String> derAttrs = new ArrayList<>();
 
-    @Schema(type = IntMappingType.GroupVirtualSchema)
+    @Schema(anyTypeKind = AnyTypeKind.GROUP, type = { SchemaType.VIRTUAL })
     private final List<String> virAttrs = new ArrayList<>();
 
     @SearchCondition(type = "GROUP")

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/report/Schema.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/Schema.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/Schema.java
index 31844af..c1771ba 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/report/Schema.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/Schema.java
@@ -22,11 +22,14 @@ import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 
 @Target({ ElementType.FIELD })
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Schema {
 
-    IntMappingType[] type() default { IntMappingType.UserPlainSchema };
+    SchemaType[] type() default { SchemaType.PLAIN };
+
+    AnyTypeKind anyTypeKind();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
index 8f6de9f..0a5455d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
@@ -26,7 +26,8 @@ import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlEnum;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
 
 @XmlRootElement(name = "userReportletConf")
 @XmlType
@@ -34,13 +35,13 @@ public class UserReportletConf extends AbstractAnyReportletConf {
 
     private static final long serialVersionUID = 6602717600064602764L;
 
-    @Schema(type = IntMappingType.UserPlainSchema)
+    @Schema(anyTypeKind = AnyTypeKind.USER, type = { SchemaType.PLAIN })
     private final List<String> plainAttrs = new ArrayList<>();
 
-    @Schema(type = IntMappingType.UserDerivedSchema)
+    @Schema(anyTypeKind = AnyTypeKind.USER, type = { SchemaType.DERIVED })
     private final List<String> derAttrs = new ArrayList<>();
 
-    @Schema(type = IntMappingType.UserVirtualSchema)
+    @Schema(anyTypeKind = AnyTypeKind.USER, type = { SchemaType.VIRTUAL })
     private final List<String> virAttrs = new ArrayList<>();
 
     @XmlEnum

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
index 6443eea..0912cf9 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
@@ -22,10 +22,15 @@ import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 public final class SearchableFields {
@@ -34,6 +39,18 @@ public final class SearchableFields {
         "serialVersionUID", "password"
     };
 
+    private static final Set<String> ANY_FIELDS = new HashSet<>();
+
+    static {
+        ANY_FIELDS.addAll(SearchableFields.get(UserTO.class));
+        ANY_FIELDS.addAll(SearchableFields.get(GroupTO.class));
+        ANY_FIELDS.addAll(SearchableFields.get(AnyObjectTO.class));
+    }
+
+    public static boolean contains(final String schema) {
+        return ANY_FIELDS.contains(schema);
+    }
+
     public static List<String> get(final AnyTypeKind anyTypeKind) {
         return get(anyTypeKind.getToClass());
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
index 696941d..c078950 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingItemTO.java
@@ -26,7 +26,6 @@ import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 
 @XmlRootElement(name = "mappingItem")
@@ -44,11 +43,6 @@ public class MappingItemTO extends AbstractBaseBean implements EntityTO {
     private String intAttrName;
 
     /**
-     * Schema type to be mapped.
-     */
-    private IntMappingType intMappingType;
-
-    /**
      * External resource's field to be mapped.
      */
     private String extAttrName;
@@ -135,14 +129,6 @@ public class MappingItemTO extends AbstractBaseBean implements EntityTO {
         this.intAttrName = intAttrName;
     }
 
-    public IntMappingType getIntMappingType() {
-        return intMappingType;
-    }
-
-    public void setIntMappingType(final IntMappingType intMappingType) {
-        this.intMappingType = intMappingType;
-    }
-
     public MappingPurpose getPurpose() {
         return purpose;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
index e69cb95..a9048c7 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MappingTO.java
@@ -28,7 +28,6 @@ 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.types.IntMappingType;
 
 @XmlRootElement(name = "mapping")
 @XmlType
@@ -61,17 +60,6 @@ public class MappingTO extends AbstractBaseBean {
     }
 
     protected boolean addConnObjectKeyItem(final MappingItemTO connObjectItem) {
-        if (IntMappingType.UserVirtualSchema == connObjectItem.getIntMappingType()
-                || IntMappingType.GroupVirtualSchema == connObjectItem.getIntMappingType()
-                || IntMappingType.AnyObjectVirtualSchema == connObjectItem.getIntMappingType()
-                || IntMappingType.Password == connObjectItem.getIntMappingType()) {
-
-            throw new IllegalArgumentException("Virtual attributes cannot be set as connObjectKey");
-        }
-        if (IntMappingType.Password == connObjectItem.getIntMappingType()) {
-            throw new IllegalArgumentException("Password attributes cannot be set as connObjectKey");
-        }
-
         connObjectItem.setMandatoryCondition("true");
         connObjectItem.setConnObjectKey(true);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
index 6f4a73c..428efde 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
@@ -32,7 +32,6 @@ import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.AbstractBaseBean;
 import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 
 @XmlRootElement(name = "notification")
@@ -53,8 +52,6 @@ public class NotificationTO extends AbstractBaseBean implements EntityTO {
 
     private final List<String> staticRecipients = new ArrayList<>();
 
-    private IntMappingType recipientAttrType;
-
     private String recipientAttrName;
 
     private boolean selfAsRecipient;
@@ -117,14 +114,6 @@ public class NotificationTO extends AbstractBaseBean implements EntityTO {
         this.recipientAttrName = recipientAttrName;
     }
 
-    public IntMappingType getRecipientAttrType() {
-        return recipientAttrType;
-    }
-
-    public void setRecipientAttrType(final IntMappingType recipientAttrType) {
-        this.recipientAttrType = recipientAttrType;
-    }
-
     public boolean isSelfAsRecipient() {
         return selfAsRecipient;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
index db3e329..149cc81 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
@@ -29,7 +29,7 @@ public enum EntityViolationType {
     InvalidConnInstanceLocation("org.apache.syncope.core.persistence.validation.conninstance.location"),
     InvalidConnPoolConf("org.apache.syncope.core.persistence.validation.conninstance.poolConf"),
     InvalidMapping("org.apache.syncope.core.persistence.validation.mapping"),
-    InvalidName("org.apache.syncope.core.persistence.validation.name"),
+    InvalidKey("org.apache.syncope.core.persistence.validation.key"),
     InvalidNotification("org.apache.syncope.core.persistence.validation.notification"),
     InvalidPassword("org.apache.syncope.core.persistence.validation.user.password"),
     InvalidPolicy("org.apache.syncope.core.persistence.validation.policy"),

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
deleted file mode 100644
index 8553348..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.common.lib.types;
-
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.xml.bind.annotation.XmlEnum;
-
-/**
- * Internal attribute mapping type.
- */
-@XmlEnum
-public enum IntMappingType {
-
-    // Unfortunately enum type cannot be extended ...
-    // -------------------------
-    // User attribute types (the same in UserMappingType)
-    // -------------------------
-    UserPlainSchema(AnyTypeKind.USER),
-    UserDerivedSchema(AnyTypeKind.USER),
-    UserVirtualSchema(AnyTypeKind.USER),
-    UserKey(AnyTypeKind.USER),
-    Username(AnyTypeKind.USER),
-    Password(AnyTypeKind.USER),
-    // -------------------------
-    // Group attribute types (the same in GroupMappingType)
-    // -------------------------
-    GroupPlainSchema(AnyTypeKind.GROUP),
-    GroupDerivedSchema(AnyTypeKind.GROUP),
-    GroupVirtualSchema(AnyTypeKind.GROUP),
-    GroupKey(AnyTypeKind.GROUP),
-    GroupName(AnyTypeKind.GROUP),
-    GroupOwnerSchema(AnyTypeKind.GROUP),
-    // -------------------------
-    // Any attribute types (the same in AnyMappingType)
-    // -------------------------
-    AnyObjectPlainSchema(AnyTypeKind.ANY_OBJECT),
-    AnyObjectDerivedSchema(AnyTypeKind.ANY_OBJECT),
-    AnyObjectVirtualSchema(AnyTypeKind.ANY_OBJECT),
-    AnyObjectKey(AnyTypeKind.ANY_OBJECT),
-    AnyObjectName(AnyTypeKind.ANY_OBJECT);
-
-    private final AnyTypeKind anyTypeKind;
-
-    IntMappingType(final AnyTypeKind anyTypeKind) {
-        this.anyTypeKind = anyTypeKind;
-    }
-
-    public AnyTypeKind getAnyTypeKind() {
-        return anyTypeKind;
-    }
-
-    /**
-     * Get attribute types for a certain any object type.
-     *
-     * @param anyTypeKind any object type
-     * @param toBeFiltered types to be filtered from the result.
-     * @return set of attribute types.
-     */
-    public static Set<IntMappingType> getAttributeTypes(
-            final AnyTypeKind anyTypeKind, final Collection<IntMappingType> toBeFiltered) {
-
-        final Set<IntMappingType> res = getAttributeTypes(anyTypeKind);
-        res.removeAll(toBeFiltered);
-
-        return res;
-    }
-
-    /**
-     * Get attribute types for a certain any object type.
-     *
-     * @param anyTypeKind any object type
-     * @return set of attribute types.
-     */
-    public static Set<IntMappingType> getAttributeTypes(final AnyTypeKind anyTypeKind) {
-        EnumSet<?> enumset;
-
-        switch (anyTypeKind) {
-            case GROUP:
-                enumset = EnumSet.allOf(GroupMappingType.class);
-                break;
-
-            case ANY_OBJECT:
-                enumset = EnumSet.allOf(AnyMappingType.class);
-                break;
-
-            case USER:
-            default:
-                enumset = EnumSet.allOf(UserMappingType.class);
-                break;
-        }
-
-        final Set<IntMappingType> result = new HashSet<>(enumset.size());
-        for (Object obj : enumset) {
-            result.add(IntMappingType.valueOf(obj.toString()));
-        }
-
-        return result;
-    }
-
-    public static Set<IntMappingType> getEmbedded() {
-        return EnumSet.of(IntMappingType.UserKey, IntMappingType.Username, IntMappingType.Password,
-                IntMappingType.GroupKey, IntMappingType.GroupName, IntMappingType.GroupOwnerSchema,
-                IntMappingType.AnyObjectKey, IntMappingType.AnyObjectName);
-    }
-
-    /**
-     * Check if attribute type belongs to the specified any object type set.
-     *
-     * @param anyTypeKind any object type.
-     * @param type attribute type.
-     * @return true if attribute type belongs to the specified any object type set.
-     */
-    public static boolean contains(final AnyTypeKind anyTypeKind, final String type) {
-        switch (anyTypeKind) {
-            case GROUP:
-                for (GroupMappingType c : GroupMappingType.values()) {
-                    if (c.name().equals(type)) {
-                        return true;
-                    }
-                }
-                break;
-
-            case ANY_OBJECT:
-                for (AnyMappingType c : AnyMappingType.values()) {
-                    if (c.name().equals(type)) {
-                        return true;
-                    }
-                }
-                break;
-
-            case USER:
-            default:
-                for (UserMappingType c : UserMappingType.values()) {
-                    if (c.name().equals(type)) {
-                        return true;
-                    }
-                }
-                break;
-        }
-        return false;
-    }
-
-    /**
-     * User attribute types.
-     */
-    private enum UserMappingType {
-
-        UserPlainSchema,
-        UserDerivedSchema,
-        UserVirtualSchema,
-        UserKey,
-        Username,
-        Password;
-
-    }
-
-    /**
-     * Group attribute types.
-     */
-    private enum GroupMappingType {
-
-        GroupPlainSchema,
-        GroupDerivedSchema,
-        GroupVirtualSchema,
-        GroupKey,
-        GroupName,
-        GroupOwnerSchema;
-
-    }
-
-    /**
-     * Any attribute types.
-     */
-    private enum AnyMappingType {
-
-        AnyObjectPlainSchema,
-        AnyObjectDerivedSchema,
-        AnyObjectVirtualSchema,
-        AnyObjectKey,
-        AnyObjectName;
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
index 51dd04b..6afa771 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
@@ -43,7 +42,7 @@ public interface ExternalResourceDAO extends DAO<ExternalResource> {
 
     ExternalResource save(ExternalResource resource);
 
-    void deleteMapping(String schemaName, IntMappingType intMappingType);
+    void deleteMapping(String schemaName);
 
     void delete(String key);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
index 0e0c8cc..84812b2 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
@@ -21,7 +21,6 @@ package org.apache.syncope.core.persistence.api.entity;
 import java.util.Set;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 
@@ -31,6 +30,8 @@ public interface AnyUtils {
 
     <T extends Any<?>> Class<T> anyClass();
 
+    boolean isFieldName(String name);
+
     <T extends PlainAttr<?>> Class<T> plainAttrClass();
 
     <T extends PlainAttr<?>> T newPlainAttr();
@@ -43,12 +44,6 @@ public interface AnyUtils {
 
     <T extends PlainAttrValue> T newPlainAttrUniqueValue();
 
-    IntMappingType plainIntMappingType();
-
-    IntMappingType derIntMappingType();
-
-    IntMappingType virIntMappingType();
-
     <T extends AnyTO> T newAnyTO();
 
     Set<ExternalResource> getAllResources(Any<?> any);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
index 6fb320f..8b2cc2d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/LinkingMappingItem.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.Collections;
 import java.util.List;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -74,26 +73,6 @@ public class LinkingMappingItem implements MappingItem {
     }
 
     @Override
-    public IntMappingType getIntMappingType() {
-        switch (virSchema.getProvision().getAnyType().getKind()) {
-            case ANY_OBJECT:
-                return IntMappingType.AnyObjectVirtualSchema;
-
-            case GROUP:
-                return IntMappingType.GroupVirtualSchema;
-
-            case USER:
-            default:
-                return IntMappingType.UserVirtualSchema;
-        }
-    }
-
-    @Override
-    public void setIntMappingType(final IntMappingType intMappingType) {
-        // RO instance, nothing to do
-    }
-
-    @Override
     public String getMandatoryCondition() {
         return virSchema.getMandatoryCondition();
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
index 38a053f..9046ccf 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Notification.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.api.entity;
 
 import java.util.List;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 
 public interface Notification extends Entity {
@@ -36,10 +35,6 @@ public interface Notification extends Entity {
 
     void setRecipientAttrName(String recipientAttrName);
 
-    IntMappingType getRecipientAttrType();
-
-    void setRecipientAttrType(IntMappingType recipientAttrType);
-
     String getRecipientsFIQL();
 
     void setRecipientsFIQL(String recipientsFIQL);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
index af751e2..461eaa1 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/resource/MappingItem.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.api.entity.resource;
 
 import java.util.List;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.Entity;
 
@@ -37,10 +36,6 @@ public interface MappingItem extends Entity {
 
     void setIntAttrName(String intAttrName);
 
-    IntMappingType getIntMappingType();
-
-    void setIntMappingType(IntMappingType intMappingType);
-
     String getMandatoryCondition();
 
     void setMandatoryCondition(String condition);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
index d5c7bcc..ead74ac 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/search/SearchCondVisitor.java
@@ -25,7 +25,7 @@ import org.apache.cxf.jaxrs.ext.search.SearchBean;
 import org.apache.cxf.jaxrs.ext.search.SearchCondition;
 import org.apache.cxf.jaxrs.ext.search.SearchUtils;
 import org.apache.cxf.jaxrs.ext.search.visitor.AbstractSearchConditionVisitor;
-import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.search.SearchableFields;
 import org.apache.syncope.common.lib.search.SpecialAttr;
 import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
 import org.apache.syncope.core.persistence.api.dao.search.MembershipCond;
@@ -56,7 +56,7 @@ public class SearchCondVisitor extends AbstractSearchConditionVisitor<SearchBean
     }
 
     private AttributeCond createAttributeCond(final String schema) {
-        AttributeCond attributeCond = EntityTOUtils.ANY_FIELDS.contains(schema)
+        AttributeCond attributeCond = SearchableFields.contains(schema)
                 ? new AnyCond()
                 : new AttributeCond();
         attributeCond.setSchema(schema);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
index 3cce4b5..3894adb 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
@@ -21,13 +21,10 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.util.Collection;
 import java.util.List;
 import javax.persistence.TypedQuery;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
-import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
 import org.apache.syncope.core.persistence.jpa.entity.JPADerSchema;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
@@ -77,10 +74,7 @@ public class JPADerSchemaDAO extends AbstractDAO<DerSchema> implements DerSchema
             return;
         }
 
-        AnyUtilsFactory anyUtilsFactory = new JPAAnyUtilsFactory();
-        for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
-            resourceDAO.deleteMapping(key, anyUtilsFactory.getInstance(anyTypeKind).derIntMappingType());
-        }
+        resourceDAO.deleteMapping(key);
 
         if (schema.getAnyTypeClass() != null) {
             schema.getAnyTypeClass().getDerSchemas().remove(schema);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
index 9692782..0658179 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
@@ -23,7 +23,6 @@ import java.util.List;
 import java.util.Set;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
@@ -160,16 +159,11 @@ public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource> implem
 
     @Override
     @SuppressWarnings("unchecked")
-    public void deleteMapping(final String intAttrName, final IntMappingType intMappingType) {
-        if (IntMappingType.getEmbedded().contains(intMappingType)) {
-            return;
-        }
-
+    public void deleteMapping(final String intAttrName) {
         TypedQuery<MappingItem> query = entityManager().createQuery(
                 "SELECT m FROM " + JPAMappingItem.class.getSimpleName()
-                + " m WHERE m.intAttrName=:intAttrName AND m.intMappingType=:intMappingType", MappingItem.class);
+                + " m WHERE m.intAttrName=:intAttrName", MappingItem.class);
         query.setParameter("intAttrName", intAttrName);
-        query.setParameter("intMappingType", intMappingType);
 
         Set<String> itemKeys = new HashSet<>();
         for (MappingItem item : query.getResultList()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
index 1b88c82..2e3bef5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
@@ -101,7 +101,7 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema> implements Plain
                 plainAttrDAO.delete(attr.getKey(), anyUtils.plainAttrClass());
             }
 
-            resourceDAO.deleteMapping(key, anyUtils.plainIntMappingType());
+            resourceDAO.deleteMapping(key);
         }
 
         if (schema.getAnyTypeClass() != null) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
index 61db7b3..4636f7d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -23,17 +23,13 @@ import java.util.Collection;
 import java.util.List;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyType;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyTypeClass;
-import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
 import org.apache.syncope.core.persistence.jpa.entity.JPAConnInstance;
 import org.apache.syncope.core.persistence.jpa.entity.JPAVirSchema;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
@@ -122,12 +118,7 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema> implements VirSchema
             return;
         }
 
-        AnyUtilsFactory anyUtilsFactory = new JPAAnyUtilsFactory();
-        for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
-            AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
-
-            resourceDAO.deleteMapping(key, anyUtils.virIntMappingType());
-        }
+        resourceDAO.deleteMapping(key);
 
         if (schema.getAnyTypeClass() != null) {
             schema.getAnyTypeClass().getVirSchemas().remove(schema);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractSchema.java
new file mode 100644
index 0000000..81c972b
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractSchema.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.Schema;
+import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaKeyCheck;
+
+@Entity
+@Inheritance(strategy = InheritanceType.JOINED)
+@Table(name = AbstractSchema.TABLE)
+@Cacheable
+@SchemaKeyCheck
+public abstract class AbstractSchema extends AbstractProvidedKeyEntity implements Schema {
+
+    public static final String TABLE = "SyncopeSchema";
+
+    private static final long serialVersionUID = -9222344997225831269L;
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
index 5c1b203..b13b19d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
@@ -18,14 +18,18 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import java.lang.reflect.Field;
+import java.util.Collection;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import org.apache.commons.lang3.ClassUtils;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
@@ -57,6 +61,40 @@ import org.springframework.transaction.annotation.Transactional;
 @SuppressWarnings({ "unchecked", "rawtypes" })
 public class JPAAnyUtils implements AnyUtils {
 
+    private static final Set<String> USER_FIELD_NAMES = new HashSet<>();
+
+    private static final Set<String> GROUP_FIELD_NAMES = new HashSet<>();
+
+    private static final Set<String> ANY_OBJECT_FIELD_NAMES = new HashSet<>();
+
+    static {
+        initFieldNames(JPAUser.class, USER_FIELD_NAMES);
+        initFieldNames(JPAGroup.class, GROUP_FIELD_NAMES);
+        initFieldNames(JPAAnyObject.class, ANY_OBJECT_FIELD_NAMES);
+    }
+
+    private static void initFieldNames(final Class<?> entityClass, final Set<String> keys) {
+        List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
+        if (!classes.contains(JPAUser.class)) {
+            classes.add(JPAUser.class);
+        }
+        for (Class<?> clazz : classes) {
+            for (Field field : clazz.getDeclaredFields()) {
+                if (!Collection.class.isAssignableFrom(field.getType())
+                        && !Map.class.isAssignableFrom(field.getType())) {
+
+                    keys.add(field.getName());
+                }
+            }
+        }
+    }
+
+    public static boolean matchesFieldName(final String candidate) {
+        return USER_FIELD_NAMES.contains(candidate)
+                || GROUP_FIELD_NAMES.contains(candidate)
+                || ANY_OBJECT_FIELD_NAMES.contains(candidate);
+    }
+
     private final AnyTypeKind anyTypeKind;
 
     @Autowired
@@ -99,6 +137,28 @@ public class JPAAnyUtils implements AnyUtils {
     }
 
     @Override
+    public boolean isFieldName(final String name) {
+        Set<String> names;
+
+        switch (anyTypeKind) {
+            case GROUP:
+                names = GROUP_FIELD_NAMES;
+                break;
+
+            case ANY_OBJECT:
+                names = ANY_OBJECT_FIELD_NAMES;
+                break;
+
+            case USER:
+            default:
+                names = USER_FIELD_NAMES;
+                break;
+        }
+
+        return names.contains(name);
+    }
+
+    @Override
     public <T extends PlainAttr<?>> Class<T> plainAttrClass() {
         Class result;
 
@@ -234,75 +294,6 @@ public class JPAAnyUtils implements AnyUtils {
     }
 
     @Override
-    public IntMappingType plainIntMappingType() {
-        IntMappingType result = null;
-
-        switch (anyTypeKind) {
-            case GROUP:
-                result = IntMappingType.GroupPlainSchema;
-                break;
-
-            case ANY_OBJECT:
-                result = IntMappingType.AnyObjectPlainSchema;
-                break;
-
-            case USER:
-                result = IntMappingType.UserPlainSchema;
-                break;
-
-            default:
-        }
-
-        return result;
-    }
-
-    @Override
-    public IntMappingType derIntMappingType() {
-        IntMappingType result = null;
-
-        switch (anyTypeKind) {
-            case GROUP:
-                result = IntMappingType.GroupDerivedSchema;
-                break;
-
-            case ANY_OBJECT:
-                result = IntMappingType.AnyObjectDerivedSchema;
-                break;
-
-            case USER:
-                result = IntMappingType.UserDerivedSchema;
-                break;
-
-            default:
-        }
-
-        return result;
-    }
-
-    @Override
-    public IntMappingType virIntMappingType() {
-        IntMappingType result = null;
-
-        switch (anyTypeKind) {
-            case GROUP:
-                result = IntMappingType.GroupVirtualSchema;
-                break;
-
-            case ANY_OBJECT:
-                result = IntMappingType.AnyObjectVirtualSchema;
-                break;
-
-            case USER:
-                result = IntMappingType.UserVirtualSchema;
-                break;
-
-            default:
-        }
-
-        return result;
-    }
-
-    @Override
     public <T extends AnyTO> T newAnyTO() {
         T result = null;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
index 7270093..e01fc99 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPADerSchema.java
@@ -18,22 +18,20 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
-import javax.persistence.Cacheable;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.OneToOne;
+import javax.persistence.PrimaryKeyJoinColumn;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
-import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaKeyCheck;
 
 @Entity
 @Table(name = JPADerSchema.TABLE)
-@Cacheable
-@SchemaKeyCheck
-public class JPADerSchema extends AbstractProvidedKeyEntity implements DerSchema {
+@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
+public class JPADerSchema extends AbstractSchema implements DerSchema {
 
     private static final long serialVersionUID = -6173643493348674060L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
index 7d186cd..392c8af 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
@@ -38,7 +38,6 @@ import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
@@ -75,10 +74,6 @@ public class JPANotification extends AbstractGeneratedKeyEntity implements Notif
     private List<String> staticRecipients;
 
     @NotNull
-    @Enumerated(EnumType.STRING)
-    private IntMappingType recipientAttrType;
-
-    @NotNull
     private String recipientAttrName;
 
     private String recipientsProviderClassName;
@@ -139,16 +134,6 @@ public class JPANotification extends AbstractGeneratedKeyEntity implements Notif
     }
 
     @Override
-    public IntMappingType getRecipientAttrType() {
-        return recipientAttrType;
-    }
-
-    @Override
-    public void setRecipientAttrType(final IntMappingType recipientAttrType) {
-        this.recipientAttrType = recipientAttrType;
-    }
-
-    @Override
     public String getRecipientsProviderClassName() {
         return recipientsProviderClassName;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
index 02b3ff7..4515517 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
@@ -27,6 +27,7 @@ import javax.persistence.Enumerated;
 import javax.persistence.FetchType;
 import javax.persistence.Lob;
 import javax.persistence.OneToOne;
+import javax.persistence.PrimaryKeyJoinColumn;
 import javax.persistence.Table;
 import javax.persistence.Transient;
 import javax.validation.constraints.Max;
@@ -40,13 +41,12 @@ import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.jpa.attrvalue.validation.BasicValidator;
 import org.apache.syncope.core.persistence.jpa.validation.entity.PlainSchemaCheck;
-import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaKeyCheck;
 
 @Entity
 @Table(name = JPAPlainSchema.TABLE)
+@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
 @PlainSchemaCheck
-@SchemaKeyCheck
-public class JPAPlainSchema extends AbstractProvidedKeyEntity implements PlainSchema {
+public class JPAPlainSchema extends AbstractSchema implements PlainSchema {
 
     private static final long serialVersionUID = -8621028596062054739L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
index 8cf70ff..1325ca7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
@@ -19,11 +19,11 @@
 package org.apache.syncope.core.persistence.jpa.entity;
 
 import javax.persistence.Basic;
-import javax.persistence.Cacheable;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToOne;
+import javax.persistence.PrimaryKeyJoinColumn;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
@@ -35,13 +35,11 @@ import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAProvision;
-import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaKeyCheck;
 
 @Entity
 @Table(name = JPAVirSchema.TABLE)
-@Cacheable
-@SchemaKeyCheck
-public class JPAVirSchema extends AbstractProvidedKeyEntity implements VirSchema {
+@PrimaryKeyJoinColumn(name = "id", referencedColumnName = "id")
+public class JPAVirSchema extends AbstractSchema implements VirSchema {
 
     private static final long serialVersionUID = 3274006935328590141L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
index d7048fa..ee11d59 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
@@ -19,8 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import javax.persistence.Entity;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
@@ -31,7 +29,6 @@ import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
 
 @Entity
 @Table(name = JPAAPlainAttrValue.TABLE)
-@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
 public class JPAAPlainAttrValue extends AbstractPlainAttrValue implements APlainAttrValue {
 
     private static final long serialVersionUID = -2965487882824889272L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
index ac72983..f4cbbca 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrValue.java
@@ -19,8 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.entity.conf;
 
 import javax.persistence.Entity;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
@@ -31,7 +29,6 @@ import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
 
 @Entity
 @Table(name = JPACPlainAttrValue.TABLE)
-@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
 public class JPACPlainAttrValue extends AbstractPlainAttrValue implements CPlainAttrValue {
 
     private static final long serialVersionUID = -4029895248193486171L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
index 8c9f383..bf2cd6f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttrValue.java
@@ -19,8 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.entity.group;
 
 import javax.persistence.Entity;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
@@ -31,7 +29,6 @@ import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
 
 @Entity
 @Table(name = JPAGPlainAttrValue.TABLE)
-@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
 public class JPAGPlainAttrValue extends AbstractPlainAttrValue implements GPlainAttrValue {
 
     private static final long serialVersionUID = -766808291128424707L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
index 0bd2440..3894994 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMapping.java
@@ -30,7 +30,6 @@ import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
@@ -92,26 +91,8 @@ public class JPAMapping extends AbstractGeneratedKeyEntity implements Mapping {
 
     @Override
     public void setConnObjectKeyItem(final MappingItem item) {
-        checkType(item, JPAMappingItem.class);
-        this.addConnObjectKeyItem((JPAMappingItem) item);
-    }
-
-    protected boolean addConnObjectKeyItem(final MappingItem connObjectKeyItem) {
-        if (IntMappingType.UserVirtualSchema == connObjectKeyItem.getIntMappingType()
-                || IntMappingType.GroupVirtualSchema == connObjectKeyItem.getIntMappingType()
-                || IntMappingType.AnyObjectVirtualSchema == connObjectKeyItem.getIntMappingType()
-                || IntMappingType.Password == connObjectKeyItem.getIntMappingType()) {
-
-            throw new IllegalArgumentException("Virtual attributes cannot be set as ConnObjectKey");
-        }
-        if (IntMappingType.Password == connObjectKeyItem.getIntMappingType()) {
-            throw new IllegalArgumentException("Password attributes cannot be set as ConnObjectKey");
-        }
-
-        connObjectKeyItem.setExtAttrName(connObjectKeyItem.getExtAttrName());
-        connObjectKeyItem.setConnObjectKey(true);
-
-        return this.add(connObjectKeyItem);
+        item.setConnObjectKey(true);
+        this.add(item);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 1d00f89..7c89dec 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -35,7 +35,6 @@ import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -56,10 +55,6 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
     @Column(nullable = true)
     private String intAttrName;
 
-    @NotNull
-    @Enumerated(EnumType.STRING)
-    private IntMappingType intMappingType;
-
     /**
      * Target resource's field to be mapped.
      */
@@ -158,40 +153,7 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
 
     @Override
     public String getIntAttrName() {
-        final String name;
-
-        switch (getIntMappingType()) {
-            case UserKey:
-            case GroupKey:
-            case AnyObjectKey:
-                name = "id";
-                break;
-
-            case Username:
-                name = "username";
-                break;
-
-            case Password:
-                name = "password";
-                break;
-
-            case GroupName:
-                name = "groupName";
-                break;
-
-            case GroupOwnerSchema:
-                name = "groupOwnerSchema";
-                break;
-
-            case AnyObjectName:
-                name = "anyObjectName";
-                break;
-                
-            default:
-                name = intAttrName;
-        }
-
-        return name;
+        return intAttrName;
     }
 
     @Override
@@ -200,16 +162,6 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
     }
 
     @Override
-    public IntMappingType getIntMappingType() {
-        return intMappingType;
-    }
-
-    @Override
-    public void setIntMappingType(final IntMappingType intMappingType) {
-        this.intMappingType = intMappingType;
-    }
-
-    @Override
     public boolean isConnObjectKey() {
         return isBooleanAsInteger(connObjectKey);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
index ce1607a..99ea4ee 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttrValue.java
@@ -19,8 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import javax.persistence.Entity;
-import javax.persistence.Inheritance;
-import javax.persistence.InheritanceType;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
@@ -31,7 +29,6 @@ import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
 
 @Entity
 @Table(name = JPAUPlainAttrValue.TABLE)
-@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
 public class JPAUPlainAttrValue extends AbstractPlainAttrValue implements UPlainAttrValue {
 
     private static final long serialVersionUID = -6259576015647897446L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
index f1a70dc..5eeae0d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AbstractValidator.java
@@ -29,7 +29,7 @@ public abstract class AbstractValidator<A extends Annotation, T> implements Cons
 
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractValidator.class);
 
-    protected static final Pattern NAME_PATTERN =
+    protected static final Pattern KEY_PATTERN =
             Pattern.compile("^[\\w \\-@.]+", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE);
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
index 2e585e4..2829e69 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/DomainValidator.java
@@ -29,14 +29,14 @@ public class DomainValidator extends AbstractValidator<DomainCheck, Domain> {
     public boolean isValid(final Domain object, final ConstraintValidatorContext context) {
         context.disableDefaultConstraintViolation();
 
-        boolean isValid = !SyncopeConstants.MASTER_DOMAIN.equals(object.getKey());
-
-        if (!isValid) {
+        if (SyncopeConstants.MASTER_DOMAIN.equals(object.getKey())) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Reserved: " + SyncopeConstants.MASTER_DOMAIN)).
-                    addPropertyNode("name").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidKey, "Reserved: " + SyncopeConstants.MASTER_DOMAIN)).
+                    addPropertyNode("key").addConstraintViolation();
+
+            return false;
         }
 
-        return isValid;
+        return true;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
index 7b145d4..99a8ec8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
@@ -25,22 +25,28 @@ import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
 import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 
 public class ExternalResourceValidator extends AbstractValidator<ExternalResourceCheck, ExternalResource> {
 
+    private static final AnyUtilsFactory ANY_UTILS_FACTORY = new JPAAnyUtilsFactory();
+
     private boolean isValid(final MappingItem item, final ConstraintValidatorContext context) {
         if (StringUtils.isBlank(item.getExtAttrName())) {
             context.buildConstraintViolationWithTemplate(
@@ -50,6 +56,14 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
             return false;
         }
 
+        if (item.getPurpose() == null) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping, item + " - purpose is null")).
+                    addPropertyNode("purpose").addConstraintViolation();
+
+            return false;
+        }
+
         if (StringUtils.isBlank(item.getIntAttrName())) {
             context.buildConstraintViolationWithTemplate(
                     getTemplate(EntityViolationType.InvalidMapping, item + " - intAttrName is null")).
@@ -58,32 +72,32 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
             return false;
         }
 
-        if (item.getPurpose() == null) {
+        IntAttrName intAttrName = null;
+        try {
+            intAttrName = IntAttrNameParser.parse(
+                    item.getIntAttrName(),
+                    ANY_UTILS_FACTORY,
+                    item.getMapping().getProvision().getAnyType().getKind());
+        } catch (IllegalArgumentException e) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + " - purpose is null")).
-                    addPropertyNode("purpose").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidMapping, item + " - " + e.getMessage())).
+                    addPropertyNode("intAttrName").addConstraintViolation();
 
             return false;
         }
 
-        if (item.getIntMappingType() == IntMappingType.AnyObjectDerivedSchema
-                || item.getIntMappingType() == IntMappingType.GroupDerivedSchema
-                || item.getIntMappingType() == IntMappingType.UserDerivedSchema) {
+        if (intAttrName.getSchemaType() == SchemaType.DERIVED
+                && item.getPurpose() != MappingPurpose.PROPAGATION) {
 
-            if (item.getPurpose() != MappingPurpose.PROPAGATION) {
-                context.buildConstraintViolationWithTemplate(
-                        getTemplate(EntityViolationType.InvalidMapping,
-                                " - only " + MappingPurpose.PROPAGATION.name() + " allowed for derived")).
-                        addPropertyNode("purpose").addConstraintViolation();
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidMapping,
+                            " - only " + MappingPurpose.PROPAGATION.name() + " allowed for derived")).
+                    addPropertyNode("purpose").addConstraintViolation();
 
-                return false;
-            }
+            return false;
         }
 
-        if (item.getIntMappingType() == IntMappingType.AnyObjectVirtualSchema
-                || item.getIntMappingType() == IntMappingType.GroupVirtualSchema
-                || item.getIntMappingType() == IntMappingType.UserVirtualSchema) {
-
+        if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
             if (item.getPurpose() != MappingPurpose.PROPAGATION) {
                 context.buildConstraintViolationWithTemplate(
                         getTemplate(EntityViolationType.InvalidMapping,
@@ -136,14 +150,6 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
             return false;
         }
 
-        MappingItem connObjectKey = mapping.getConnObjectKeyItem();
-        if (connObjectKey.getIntMappingType().getAnyTypeKind() != anyType.getKind()) {
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, "ConnObjectKey must be from the same AnyTypeKind")).
-                    addPropertyNode("anyTypeKind").addConstraintViolation();
-            return false;
-        }
-
         boolean isValid = true;
 
         int passwords = 0;
@@ -189,10 +195,10 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
     public boolean isValid(final ExternalResource resource, final ConstraintValidatorContext context) {
         context.disableDefaultConstraintViolation();
 
-        if (resource.getKey() == null || !NAME_PATTERN.matcher(resource.getKey()).matches()) {
+        if (resource.getKey() == null || !KEY_PATTERN.matcher(resource.getKey()).matches()) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Invalid Resource name")).
-                    addPropertyNode("name").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidKey, "Invalid resource key")).
+                    addPropertyNode("key").addConstraintViolation();
             return false;
         }
 


[02/15] syncope git commit: [SYNCOPE-860] provides role and group members inspecting feature

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
index 681744e..7dc90bf 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.java
@@ -73,6 +73,7 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
         super.add(new Fragment("panelEnable", "emptyFragment", this));
         super.add(new Fragment("panelNotFound", "emptyFragment", this));
         super.add(new Fragment("panelView", "emptyFragment", this));
+        super.add(new Fragment("panelMembers", "emptyFragment", this));
         super.add(new Fragment("panelSearch", "emptyFragment", this));
         super.add(new Fragment("panelDelete", "emptyFragment", this));
         super.add(new Fragment("panelExecute", "emptyFragment", this));
@@ -127,7 +128,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -146,7 +148,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -165,7 +168,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -184,7 +188,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -203,7 +208,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -222,7 +228,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -241,7 +248,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -260,7 +268,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -279,7 +288,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -298,7 +308,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -317,7 +328,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -336,7 +348,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -355,7 +368,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -374,7 +388,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -393,7 +408,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -412,7 +428,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -431,7 +448,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -450,7 +468,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -469,7 +488,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -488,7 +508,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -510,7 +531,27 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                    }
+                }.setVisible(link.isEnabled(model.getObject())));
+                break;
+
+            case MEMBERS:
+                fragment = new Fragment("panelMembers", "fragmentMembers", this);
+                fragment.addOrReplace(new IndicatingAjaxLink<Void>("membersLink") {
+
+                    private static final long serialVersionUID = -1876519166660008562L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target) {
+                        link.onClick(target, model.getObject());
+                    }
+
+                    @Override
+                    public String getAjaxIndicatorMarkupId() {
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -529,7 +570,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -548,7 +590,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -567,7 +610,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -586,7 +630,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }).setVisible(link.isEnabled(model.getObject()));
 
@@ -606,7 +651,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }).setVisible(link.isEnabled(model.getObject()));
 
@@ -625,7 +671,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }).setVisible(link.isEnabled(model.getObject()));
 
@@ -645,7 +692,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -664,7 +712,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -683,7 +732,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -702,7 +752,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -721,7 +772,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -740,7 +792,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -759,7 +812,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -778,7 +832,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -797,7 +852,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -816,7 +872,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -835,7 +892,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -854,7 +912,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -874,7 +933,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -893,7 +953,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -912,7 +973,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -931,7 +993,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -950,7 +1013,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -969,7 +1033,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -988,7 +1053,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -1007,7 +1073,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -1026,7 +1093,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -1045,7 +1113,8 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
 
                     @Override
                     public String getAjaxIndicatorMarkupId() {
-                        return disableIndicator ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
+                        return disableIndicator || !link.isIndicatorEnabled()
+                                ? StringUtils.EMPTY : super.getAjaxIndicatorMarkupId();
                     }
                 }.setVisible(link.isEnabled(model.getObject())));
                 break;
@@ -1135,6 +1204,10 @@ public final class ActionLinksPanel<T extends Serializable> extends Panel {
                 super.addOrReplace(new Fragment("panelView", "emptyFragment", this));
                 break;
 
+            case MEMBERS:
+                super.addOrReplace(new Fragment("panelMembers", "emptyFragment", this));
+                break;
+
             case SEARCH:
                 super.addOrReplace(new Fragment("panelSearch", "emptyFragment", this));
                 break;

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java b/client/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
index 99f928e..4f6d019 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/widgets/JobWidget.java
@@ -201,8 +201,8 @@ public class JobWidget extends BaseWidget {
                 private static final long serialVersionUID = 8769126634538601689L;
 
                 @Override
-                protected WizardMgtPanel<JobTO> newInstance(final String id) {
-                    return new AvailableJobsPanel(id, pageRef);
+                protected WizardMgtPanel<JobTO> newInstance(final String id, final boolean wizardInModal) {
+                    throw new UnsupportedOperationException();
                 }
             }.disableCheckBoxes().hidePaginator());
 
@@ -308,8 +308,8 @@ public class JobWidget extends BaseWidget {
                 private static final long serialVersionUID = 8769126634538601689L;
 
                 @Override
-                protected WizardMgtPanel<ExecTO> newInstance(final String id) {
-                    return new RecentExecPanel(id, pageRef);
+                protected WizardMgtPanel<ExecTO> newInstance(final String id, final boolean wizardInModal) {
+                    throw new UnsupportedOperationException();
                 }
             }.disableCheckBoxes().hidePaginator());
 
@@ -399,8 +399,8 @@ public class JobWidget extends BaseWidget {
                 ThreadContext.setSession(session);
 
                 WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
-                WebSocketPushBroadcaster broadcaster =
-                        new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
+                WebSocketPushBroadcaster broadcaster = new WebSocketPushBroadcaster(webSocketSettings.
+                        getConnectionRegistry());
                 broadcaster.broadcast(
                         new ConnectedMessage(application, session.getId(), key),
                         new JobWidgetMessage(getAvailable(session), getRecent(session)));

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationDetailsModalPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationDetailsModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationDetailsModalPanel.java
index 34d72f6..5fd1e62 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationDetailsModalPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationDetailsModalPanel.java
@@ -82,8 +82,8 @@ public class ReconciliationDetailsModalPanel extends AbstractModalPanel<Any> {
                 private static final long serialVersionUID = 8769126634538601689L;
 
                 @Override
-                protected WizardMgtPanel<Misaligned> newInstance(final String id) {
-                    return new DiffPanel(id, pageRef);
+                protected WizardMgtPanel<Misaligned> newInstance(final String id, final boolean wizardInModal) {
+                    throw new UnsupportedOperationException();
                 }
             }.disableCheckBoxes().hidePaginator());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java b/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
index fc7e078..3fec490 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/widgets/ReconciliationWidget.java
@@ -158,7 +158,7 @@ public class ReconciliationWidget extends BaseWidget {
                     SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));
                 } catch (Exception e) {
                     LOG.error("While starting reconciliation report", e);
-                   SyncopeConsoleSession.get().error("Could not start reconciliation report");
+                    SyncopeConsoleSession.get().error("Could not start reconciliation report");
                 }
                 SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
             }
@@ -313,8 +313,8 @@ public class ReconciliationWidget extends BaseWidget {
                 private static final long serialVersionUID = 8769126634538601689L;
 
                 @Override
-                protected WizardMgtPanel<Any> newInstance(final String id) {
-                    return new AnysReconciliationPanel(id, anys, pageRef);
+                protected WizardMgtPanel<Any> newInstance(final String id, final boolean wizardInModal) {
+                    throw new UnsupportedOperationException();
                 }
             }.disableCheckBoxes().hidePaginator());
 
@@ -508,8 +508,8 @@ public class ReconciliationWidget extends BaseWidget {
                                 SyncopeConsoleApplication.class.cast(application).getReconciliationReportKey());
 
                         WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
-                        WebSocketPushBroadcaster broadcaster =
-                                new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
+                        WebSocketPushBroadcaster broadcaster = new WebSocketPushBroadcaster(webSocketSettings.
+                                getConnectionRegistry());
                         broadcaster.broadcast(
                                 new ConnectedMessage(application, session.getId(), key),
                                 new ReconciliationJobNotRunningMessage());

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
index 9b5520d..c6a5f01 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/WizardMgtPanel.java
@@ -61,7 +61,7 @@ public abstract class WizardMgtPanel<T extends Serializable> extends Panel imple
 
     private final Fragment initialFragment;
 
-    private final boolean wizardInModal;
+    protected final boolean wizardInModal;
 
     private boolean containerAutoRefresh = true;
 
@@ -375,11 +375,13 @@ public abstract class WizardMgtPanel<T extends Serializable> extends Panel imple
 
         private boolean showResultPage = false;
 
+        private boolean wizardInModal = false;
+
         protected Builder(final PageReference pageRef) {
             this.pageRef = pageRef;
         }
 
-        protected abstract WizardMgtPanel<T> newInstance(final String id);
+        protected abstract WizardMgtPanel<T> newInstance(final String id, final boolean wizardInModal);
 
         /**
          * Builds a list view.
@@ -388,7 +390,7 @@ public abstract class WizardMgtPanel<T extends Serializable> extends Panel imple
          * @return List view.
          */
         public WizardMgtPanel<T> build(final String id) {
-            return newInstance(id).
+            return newInstance(id, wizardInModal).
                     setPageRef(this.pageRef).
                     setShowResultPage(this.showResultPage).
                     addNewItemPanelBuilder(this.newItemPanelBuilder, this.newItemDefaultButtonEnabled).
@@ -428,6 +430,17 @@ public abstract class WizardMgtPanel<T extends Serializable> extends Panel imple
             this.notificationPanel = notificationPanel;
             return this;
         }
+
+        /**
+         * Specifies to open an edit item wizard into a new modal page.
+         *
+         * @param wizardInModal TRUE to request to open wizard in a new modal.
+         * @return the current builder.
+         */
+        public Builder<T> setWizardInModal(final boolean wizardInModal) {
+            this.wizardInModal = wizardInModal;
+            return this;
+        }
     }
 
     public static class ExitEvent {

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
index c57557b..e41cdea 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
@@ -341,7 +341,7 @@ public class Relationships extends WizardStep {
                                 pageRef).setFiltered(true).
                                 setFiql(SyncopeClient.getAnyObjectSearchConditionBuilder(anyType.getKey()).
                                         is("key").notNullValue().query()).
-                                build("searchResultPanel");
+                                setWizardInModal(true).build("searchResultPanel");
                         fragment.add(anyObjectDirectoryPanel.setRenderBodyOnly(true));
                     }
                     target.add(container);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel.properties
index 51ada13..13f6c3c 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel.properties
@@ -15,3 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 any.edit=Edit ${anyTO.type} ${anyTO.name}
+group.members='${right}' members of group '${left.name}' 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_it.properties
index 624f59d..f851f3d 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_it.properties
@@ -15,3 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 any.edit=Modifica ${anyTO.type} ${anyTO.name}
+group.members='${right}' membri del gruppo '${left.name}' 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_pt_BR.properties
index 70a509d..dee981b 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_pt_BR.properties
@@ -15,3 +15,4 @@
 # specific language governing permissions and limitations
 # under the License.
 any.edit=Alterar ${anyTO.type} ${anyTO.name}
+group.members='${right}' members of group '${left.name}' 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_ru.properties
index b881032..de2959b 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/GroupDirectoryPanel_ru.properties
@@ -17,3 +17,4 @@
 #
 # any.edit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c ${anyTO.type} ${anyTO.key}
 any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c ${anyTO.type} ${anyTO.name}
+group.members='${right}' members of group '${left.name}' 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/MembersTogglePanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/MembersTogglePanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/MembersTogglePanel.html
new file mode 100644
index 0000000..340c0e6
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/MembersTogglePanel.html
@@ -0,0 +1,32 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <div id="startAtContainer">
+      <form wicket:id="membersForm">
+        <div class="input-group">
+          <span wicket:id="type"/>
+          <div class="input-group-addon">
+            <a wicket:id="changeit"><i class="fa fa-users" alt="members icon" title="Members"></i></a>
+          </div>
+        </div>
+      </form>
+    </div>
+  </wicket:extend>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel.properties
index 441110e..3a27730 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel.properties
@@ -16,3 +16,4 @@
 # under the License.
 any.edit=Edit role ${roleTO.key}
 any.new=New role
+role.members=Role '${key}' members

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_it.properties
index b048546..04a466e 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_it.properties
@@ -16,3 +16,4 @@
 # under the License.
 any.edit=Modifica ruolo ${roleTO.key}
 any.new=Nuovo ruolo
+role.members=Utenti membri del rulo '${key}'

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_pt_BR.properties
index 9ae44c5..1de6e43 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_pt_BR.properties
@@ -16,3 +16,4 @@
 # under the License.
 any.edit=Alterar fun\u00e7\u00e3o ${roleTO.key}
 any.new=Novo fun\u00e7\u00e3o
+role.members=Role '${key}' members

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_ru.properties
index fe402df..36f5cbf 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/RoleDirectoryPanel_ru.properties
@@ -15,7 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u043e\u043b\u044c ${roleTO.key}
+# any.edit=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c ${roleTO.key}
 any.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u043e\u043b\u044c ${roleTO.key}
-# any.new=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u043e\u043b\u044c
+# any.new=\u00d0\u00a1\u00d0\u00be\u00d0\u00b7\u00d0\u00b4\u00d0\u00b0\u00d1\u0082\u00d1\u008c \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d1\u008c
 any.new=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0440\u043e\u043b\u044c
+role.members=Role '${key}' members

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
index 5b20816..9903f98 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wicket/markup/html/form/ActionLinksPanel.html
@@ -37,6 +37,7 @@ under the License.
     <span wicket:id="panelSearch">[plus]</span>
     <span wicket:id="panelNotFound">[plus]</span>
     <span wicket:id="panelView">[plus]</span>
+    <span wicket:id="panelMembers">[plus]</span>
     <span wicket:id="panelMapping">[plus]</span>
     <span wicket:id="panelSetLatestSyncToken">[plus]</span>
     <span wicket:id="panelRemoveSyncToken">[plus]</span>
@@ -125,6 +126,10 @@ under the License.
       <a href="#" wicket:id="viewLink" class="btn"><i class="fa fa-eye" alt="view icon" title="View"></i></a>
     </wicket:fragment>
 
+    <wicket:fragment wicket:id="fragmentMembers">
+      <a href="#" wicket:id="membersLink" class="btn"><i class="fa fa-users" alt="members icon" title="Members"></i></a>
+    </wicket:fragment>
+
     <wicket:fragment wicket:id="fragmentSearch">
       <a href="#" wicket:id="searchLink" class="btn"><i class="glyphicon glyphicon-search" alt="search icon" title="Search"></i></a>
     </wicket:fragment>

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/ext/camel/client-console/src/main/java/org/apache/syncope/client/console/panels/CamelRoutesDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/ext/camel/client-console/src/main/java/org/apache/syncope/client/console/panels/CamelRoutesDirectoryPanel.java b/ext/camel/client-console/src/main/java/org/apache/syncope/client/console/panels/CamelRoutesDirectoryPanel.java
index b40e466..8568b1a 100644
--- a/ext/camel/client-console/src/main/java/org/apache/syncope/client/console/panels/CamelRoutesDirectoryPanel.java
+++ b/ext/camel/client-console/src/main/java/org/apache/syncope/client/console/panels/CamelRoutesDirectoryPanel.java
@@ -64,8 +64,8 @@ public class CamelRoutesDirectoryPanel extends DirectoryPanel<
             private static final long serialVersionUID = 8769126634538601689L;
 
             @Override
-            protected WizardMgtPanel<CamelRouteTO> newInstance(final String id) {
-                return new CamelRoutesDirectoryPanel(id, this, anyTypeKind);
+            protected WizardMgtPanel<CamelRouteTO> newInstance(final String id, final boolean wizardInModal) {
+                throw new UnsupportedOperationException();
             }
         }.disableCheckBoxes());
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
index cc55b6b..0b6ff9c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/GroupsITCase.java
@@ -44,6 +44,34 @@ public class GroupsITCase extends AbstractConsoleITCase {
     }
 
     @Test
+    public void read() {
+        wicketTester.clickLink("body:realmsLI:realms");
+        wicketTester.clickLink("body:content:body:tabbedPanel:tabs-container:tabs:2:link");
+
+        Component component = findComponentByProp("name", searchResultContainer
+                + ":searchContainer:resultTable:tablePanel:groupForm:checkgroup:dataTable", "artDirector");
+        assertNotNull(component);
+
+        wicketTester.clickLink(component.getPageRelativePath() + ":cells:4:cell:panelMembers:membersLink");
+
+        FormTester formTester = wicketTester.newFormTester("body:content:body:tabbedPanel:panel:searchResult:"
+                + "outerObjectsRepeater:6:outer:container:content:togglePanelContainer:membersForm");
+
+        formTester.select("type:dropDownChoiceField", 0);
+        formTester.submit("changeit");
+
+        wicketTester.assertModelValue("body:content:body:tabbedPanel:panel:searchResult:outerObjectsRepeater:5:outer:"
+                + "dialog:header:header-label", "'USER' members of group 'artDirector' ");
+
+        assertNotNull(findComponentByProp("username", "body:content:body:tabbedPanel:panel:searchResult:"
+                + "outerObjectsRepeater:5:outer:form:content:searchResult:container:content:searchContainer:"
+                + "resultTable:tablePanel:groupForm:checkgroup:dataTable", "puccini"));
+
+        wicketTester.executeAjaxEvent("body:content:body:tabbedPanel:panel:searchResult:outerObjectsRepeater:5:"
+                + "outer:dialog:footer:buttons:0:button", Constants.ON_CLICK);
+    }
+
+    @Test
     public void filteredSearch() {
         wicketTester.clickLink("body:realmsLI:realms");
         wicketTester.clickLink("body:content:body:tabbedPanel:tabs-container:tabs:2:link");

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
index da619e1..d5991da 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/RolesITCase.java
@@ -18,9 +18,11 @@
  */
 package org.apache.syncope.fit.console;
 
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.dialog.Modal;
+import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.pages.Roles;
 import org.apache.wicket.Component;
 import org.apache.wicket.util.tester.FormTester;
@@ -66,6 +68,21 @@ public class RolesITCase extends AbstractConsoleITCase {
     public void read() {
         assertNull(findComponentByProp(KEY, "body:content:rolesPanel:container:content:searchContainer:"
                 + "resultTable:tablePanel:groupForm:checkgroup:dataTable", "OTHER"));
+
+        wicketTester.clickLink("body:content:rolesPanel:container:content:searchContainer:resultTable:tablePanel:"
+                + "groupForm:checkgroup:dataTable:body:rows:1:cells:4:cell:panelMembers:membersLink");
+
+        wicketTester.assertModelValue(
+                "body:content:rolesPanel:outerObjectsRepeater:4:outer:dialog:header:header-label",
+                "Role 'Other' members");
+
+        assertNotNull(findComponentByProp("username", "body:content:rolesPanel:outerObjectsRepeater:4:outer:form:"
+                + "content:searchResult:container:content:searchContainer:resultTable:tablePanel:groupForm:"
+                + "checkgroup:dataTable", "rossini"));
+
+        wicketTester.executeAjaxEvent(
+                "body:content:rolesPanel:outerObjectsRepeater:4:outer:dialog:footer:buttons:0:button",
+                Constants.ON_CLICK);
     }
 
     @Test


[06/15] syncope git commit: Unique schema key across the three tables

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
index a24431e..3d8d0a5 100644
--- a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
@@ -22,6 +22,7 @@ under the License.
 
   <SyncopeConf id="cd64d66f-6fff-4008-b966-a06b1cc1436d"/>
 
+  <SyncopeSchema id="password.cipher.algorithm"/>
   <PlainSchema id="password.cipher.algorithm" type="String"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="56db89b9-119e-4923-a16e-f42823b90c66" 
@@ -29,6 +30,7 @@ under the License.
   <CPlainAttrValue id="870323e8-8db6-4a64-b512-15f9fa094905" 
                    attribute_id="56db89b9-119e-4923-a16e-f42823b90c66" stringValue="SHA1"/>
 
+  <SyncopeSchema id="token.length"/>
   <PlainSchema id="token.length" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="58977caa-dcf7-4ae3-8591-7e3d0a395200"
@@ -36,6 +38,7 @@ under the License.
   <CPlainAttrValue id="372e28e0-3af1-4774-b668-81aa84903b75"
                    attribute_id="58977caa-dcf7-4ae3-8591-7e3d0a395200" longValue="256"/>
 
+  <SyncopeSchema id="token.expireTime"/>
   <PlainSchema id="token.expireTime" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="01f69abd-df85-4e1b-bb88-ad570594e045"
@@ -43,6 +46,7 @@ under the License.
   <CPlainAttrValue id="963970cf-4af6-46bb-875b-a1b758ac8d05"
                    attribute_id="01f69abd-df85-4e1b-bb88-ad570594e045" longValue="60"/>
 
+  <SyncopeSchema id="selfRegistration.allowed"/>
   <PlainSchema id="selfRegistration.allowed" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="7b19cefa-d606-477c-8431-c9464f53fe8b"
@@ -50,6 +54,7 @@ under the License.
   <CPlainAttrValue id="c8b9a0f1-0168-4e2a-95b8-4819fc70e620"
                    attribute_id="7b19cefa-d606-477c-8431-c9464f53fe8b" booleanValue="1"/>
 
+  <SyncopeSchema id="passwordReset.allowed"/>
   <PlainSchema id="passwordReset.allowed" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="dc35cc97-6ed9-4bb2-bb3b-509f4cd8f3d3"
@@ -57,6 +62,7 @@ under the License.
   <CPlainAttrValue id="b1ecea41-ab7c-4dd3-9e3e-b6baf0f98046"
                    attribute_id="dc35cc97-6ed9-4bb2-bb3b-509f4cd8f3d3" booleanValue="1"/>
 
+  <SyncopeSchema id="passwordReset.securityQuestion"/>
   <PlainSchema id="passwordReset.securityQuestion" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="e5a712ad-53fd-4102-ba55-fb45caed5f7b"
@@ -64,6 +70,7 @@ under the License.
   <CPlainAttrValue id="b5e8e79d-8039-4318-9698-fe5e181ebe98"
                    attribute_id="e5a712ad-53fd-4102-ba55-fb45caed5f7b" booleanValue="1"/>
 
+  <SyncopeSchema id="authentication.statuses"/>
   <PlainSchema id="authentication.statuses" type="String" multivalue="1" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="888ae8e1-a295-4ee2-a15e-31dbf6dfc3f9"
               owner_id="cd64d66f-6fff-4008-b966-a06b1cc1436d" schema_id="authentication.statuses"/>
@@ -73,6 +80,7 @@ under the License.
                    attribute_id="888ae8e1-a295-4ee2-a15e-31dbf6dfc3f9" stringValue="active"/>
 
   <!-- Save user login date upon successful authentication -->
+  <SyncopeSchema id="log.lastlogindate"/>
   <PlainSchema id="log.lastlogindate" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="9891c0a7-27ee-4215-9eea-ca32e580b4e4"
@@ -80,6 +88,7 @@ under the License.
   <CPlainAttrValue id="162dd874-0417-4bb9-9724-db1ff2952dd1"
                    attribute_id="9891c0a7-27ee-4215-9eea-ca32e580b4e4" booleanValue="1"/>
 
+  <SyncopeSchema id="tasks.interruptMaxRetries"/>
   <PlainSchema id="tasks.interruptMaxRetries" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db"
@@ -88,6 +97,7 @@ under the License.
                    attribute_id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db" longValue="20"/>
   
   <!-- Return hashed password values when reading users -->
+  <SyncopeSchema id="return.password.value"/>
   <PlainSchema id="return.password.value" type="Boolean"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="bcfd7efc-0605-4b5e-b4bb-85c1d5f6493a"
@@ -101,6 +111,7 @@ under the License.
 
   <AnyType id="GROUP" kind="GROUP"/>
         
+  <SyncopeSchema id="email"/>
   <PlainSchema id="email" type="String" anyTypeClass_id="BaseUser"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                validatorClass="org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
new file mode 100644
index 0000000..4beb5ce
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+
+public final class IntAttrNameParser {
+
+    private static final Pattern ENCLOSING_GROUP_PATTERN = Pattern.compile("^groups\\[[\\w]+\\]\\.[\\w]+");
+
+    private static final Pattern RELATED_ANY_OBJECT_PATTERN = Pattern.compile("^anyObjects\\[[\\w]+\\]\\.[\\w]+");
+
+    private static final Pattern MEMBERSHIP_PATTERN = Pattern.compile("^\\[[\\w]+\\]\\.[\\w]+");
+
+    public static class IntAttrName {
+
+        private AnyTypeKind anyTypeKind;
+
+        private String field;
+
+        private SchemaType schemaType;
+
+        private String schemaName;
+
+        private String enclosingGroup;
+
+        private String relatedAnyObject;
+
+        private String membershipOfGroup;
+
+        public AnyTypeKind getAnyTypeKind() {
+            return anyTypeKind;
+        }
+
+        public String getField() {
+            return field;
+        }
+
+        public SchemaType getSchemaType() {
+            return schemaType;
+        }
+
+        public String getSchemaName() {
+            return schemaName;
+        }
+
+        public String getEnclosingGroup() {
+            return enclosingGroup;
+        }
+
+        public String getRelatedAnyObject() {
+            return relatedAnyObject;
+        }
+
+        public String getMembershipOfGroup() {
+            return membershipOfGroup;
+        }
+
+        @Override
+        public String toString() {
+            return ToStringBuilder.reflectionToString(field, ToStringStyle.MULTI_LINE_STYLE);
+        }
+
+    }
+
+    private static void setFieldOrSchemaName(
+            final String fieldOrSchemaName, final AnyUtils anyUtils, final IntAttrName result) {
+
+        if (anyUtils.isFieldName(fieldOrSchemaName)) {
+            result.field = fieldOrSchemaName;
+        } else {
+            result.schemaName = fieldOrSchemaName;
+        }
+    }
+
+    public static IntAttrName parse(
+            final String intAttrName,
+            final AnyUtilsFactory anyUtilsFactory,
+            final AnyTypeKind provisionAnyTypeKind) {
+
+        IntAttrName result = new IntAttrName();
+
+        if (intAttrName.indexOf('.') == -1) {
+            result.anyTypeKind = provisionAnyTypeKind;
+            setFieldOrSchemaName(intAttrName, anyUtilsFactory.getInstance(provisionAnyTypeKind), result);
+        } else {
+            Matcher matcher = ENCLOSING_GROUP_PATTERN.matcher(intAttrName);
+            if (matcher.matches()) {
+                result.anyTypeKind = AnyTypeKind.GROUP;
+                result.enclosingGroup = matcher.group(1);
+                setFieldOrSchemaName(matcher.group(2), anyUtilsFactory.getInstance(AnyTypeKind.GROUP), result);
+            } else {
+                matcher = RELATED_ANY_OBJECT_PATTERN.matcher(intAttrName);
+                if (matcher.matches()) {
+                    result.anyTypeKind = AnyTypeKind.ANY_OBJECT;
+                    result.relatedAnyObject = matcher.group(1);
+                    setFieldOrSchemaName(matcher.group(2), anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), result);
+                } else {
+                    matcher = MEMBERSHIP_PATTERN.matcher(intAttrName);
+                    if (matcher.matches()) {
+                        result.anyTypeKind = AnyTypeKind.USER;
+                        result.membershipOfGroup = matcher.group(1);
+                        setFieldOrSchemaName(matcher.group(2), anyUtilsFactory.getInstance(AnyTypeKind.USER), result);
+                    } else {
+                        throw new IllegalArgumentException("Unparsable expression: " + intAttrName);
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private IntAttrNameParser() {
+        // private constructor for static utility class
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
index 4600f9a..99c1ba8 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
@@ -44,11 +44,11 @@ public interface MappingManager {
      * Get attribute values for the given {@link MappingItem} and any objects.
      *
      * @param provision provision information
-     * @param mappingItem mapping item
+     * @param mapItem mapping item
      * @param anys any objects
      * @return attribute values.
      */
-    List<PlainAttrValue> getIntValues(Provision provision, MappingItem mappingItem, List<Any<?>> anys);
+    List<PlainAttrValue> getIntValues(Provision provision, MappingItem mapItem, List<Any<?>> anys);
 
     /**
      * Prepare attributes for sending to a connector instance.
@@ -68,11 +68,11 @@ public interface MappingManager {
      * connector.
      *
      * @param <T> any object
-     * @param mappingItem mapping item
+     * @param mapItem mapping item
      * @param attr attribute received from connector
      * @param anyTO any object
      * @param anyUtils any utils
      */
-    <T extends AnyTO> void setIntValues(MappingItem mappingItem, Attribute attr, T anyTO, AnyUtils anyUtils);
+    <T extends AnyTO> void setIntValues(MappingItem mapItem, Attribute attr, T anyTO, AnyUtils anyUtils);
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/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 b84799a..e2f793a 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
@@ -38,7 +38,6 @@ import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.provisioning.api.utils.policy.InvalidPasswordRuleConf;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
@@ -74,6 +73,8 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
 import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
@@ -349,7 +350,7 @@ public class MappingManagerImpl implements MappingManager {
         String connObjectKey = null;
 
         for (MappingItem mappingItem : getMappingItems(provision, MappingPurpose.PROPAGATION)) {
-            LOG.debug("Processing schema {}", mappingItem.getIntAttrName());
+            LOG.debug("Processing expression '{}'", mappingItem.getIntAttrName());
 
             try {
                 Pair<String, Attribute> preparedAttr = prepareAttr(provision, mappingItem, any, password);
@@ -373,7 +374,7 @@ public class MappingManagerImpl implements MappingManager {
                     }
                 }
             } catch (Exception e) {
-                LOG.debug("Attribute '{}' processing failed", mappingItem.getIntAttrName(), e);
+                LOG.debug("Expression '{}' processing failed", mappingItem.getIntAttrName(), e);
             }
         }
 
@@ -410,9 +411,12 @@ public class MappingManagerImpl implements MappingManager {
     private Pair<String, Attribute> prepareAttr(
             final Provision provision, final MappingItem mapItem, final Any<?> any, final String password) {
 
+        IntAttrName intAttrName =
+                IntAttrNameParser.parse(mapItem.getIntAttrName(), anyUtilsFactory, provision.getAnyType().getKind());
+
         List<Any<?>> anys = new ArrayList<>();
 
-        switch (mapItem.getIntMappingType().getAnyTypeKind()) {
+        switch (intAttrName.getAnyTypeKind()) {
             case USER:
                 if (any instanceof User) {
                     anys.add(any);
@@ -443,18 +447,14 @@ public class MappingManagerImpl implements MappingManager {
         AttrSchemaType schemaType;
         Pair<String, Attribute> result;
 
-        switch (mapItem.getIntMappingType()) {
-            case UserPlainSchema:
-            case GroupPlainSchema:
-            case AnyObjectPlainSchema:
-                schema = plainSchemaDAO.find(mapItem.getIntAttrName());
+        switch (intAttrName.getSchemaType()) {
+            case PLAIN:
+                schema = plainSchemaDAO.find(intAttrName.getSchemaName());
                 schemaType = schema == null ? AttrSchemaType.String : schema.getType();
                 break;
 
-            case UserVirtualSchema:
-            case GroupVirtualSchema:
-            case AnyObjectVirtualSchema:
-                schema = virSchemaDAO.find(mapItem.getIntAttrName());
+            case VIRTUAL:
+                schema = virSchemaDAO.find(intAttrName.getSchemaName());
                 readOnlyVirSchema = (schema != null && schema.isReadonly());
                 schemaType = AttrSchemaType.String;
                 break;
@@ -470,10 +470,9 @@ public class MappingManagerImpl implements MappingManager {
         LOG.debug("Define mapping for: "
                 + "\n* ExtAttrName " + extAttrName
                 + "\n* is connObjectKey " + mapItem.isConnObjectKey()
-                + "\n* is password " + (mapItem.isPassword() || mapItem.getIntMappingType() == IntMappingType.Password)
+                + "\n* is password " + mapItem.isPassword()
                 + "\n* mandatory condition " + mapItem.getMandatoryCondition()
-                + "\n* Schema " + mapItem.getIntAttrName()
-                + "\n* IntMappingType " + mapItem.getIntMappingType().toString()
+                + "\n* Schema " + intAttrName.getSchemaName()
                 + "\n* ClassType " + schemaType.getType().getName()
                 + "\n* Values " + values);
 
@@ -518,8 +517,7 @@ public class MappingManagerImpl implements MappingManager {
                             null, AttributeBuilder.buildPassword(passwordAttrValue.toCharArray()));
                 }
             } else if ((schema != null && schema.isMultivalue())
-                    || anyUtilsFactory.getInstance(any).getAnyTypeKind()
-                    != mapItem.getIntMappingType().getAnyTypeKind()) {
+                    || anyUtilsFactory.getInstance(any).getAnyTypeKind() != intAttrName.getAnyTypeKind()) {
 
                 result = new ImmutablePair<>(
                         null, AttributeBuilder.build(extAttrName, objValues));
@@ -541,184 +539,150 @@ public class MappingManagerImpl implements MappingManager {
         return evaluateNAME(any, provision, connObjectKey).getNameValue();
     }
 
-    /**
-     * Get attribute values for the given {@link MappingItem} and any objects.
-     *
-     * @param provision provision information
-     * @param mappingItem mapping item
-     * @param anys any objects
-     * @return attribute values.
-     */
     @Transactional(readOnly = true)
     @Override
     public List<PlainAttrValue> getIntValues(
-            final Provision provision, final MappingItem mappingItem, final List<Any<?>> anys) {
+            final Provision provision, final MappingItem mapItem, final List<Any<?>> anys) {
 
-        LOG.debug("Get attributes for '{}' and mapping type '{}'", anys, mappingItem.getIntMappingType());
+        LOG.debug("Get attributes for '{}' and intAttrName '{}'", anys, mapItem.getIntAttrName());
 
-        boolean transform = true;
+        IntAttrName intAttrName =
+                IntAttrNameParser.parse(mapItem.getIntAttrName(), anyUtilsFactory, provision.getAnyType().getKind());
 
         List<PlainAttrValue> values = new ArrayList<>();
-        switch (mappingItem.getIntMappingType()) {
-            case UserPlainSchema:
-            case GroupPlainSchema:
-            case AnyObjectPlainSchema:
-                for (Any<?> any : anys) {
-                    PlainAttr<?> attr = any.getPlainAttr(mappingItem.getIntAttrName());
-                    if (attr != null) {
-                        if (attr.getUniqueValue() != null) {
-                            PlainAttrUniqueValue value = SerializationUtils.clone(attr.getUniqueValue());
-                            value.setAttr(null);
-                            values.add(value);
-                        } else if (attr.getValues() != null) {
-                            for (PlainAttrValue value : attr.getValues()) {
-                                PlainAttrValue shadow = SerializationUtils.clone(value);
-                                shadow.setAttr(null);
-                                values.add(shadow);
-                            }
-                        }
-                    }
-
-                    LOG.debug("Retrieved attribute {}"
-                            + "\n* IntAttrName {}"
-                            + "\n* IntMappingType {}"
-                            + "\n* Attribute values {}",
-                            attr, mappingItem.getIntAttrName(), mappingItem.getIntMappingType(), values);
-                }
+        boolean transform = true;
 
-                break;
+        if (intAttrName.getField() != null) {
+            switch (intAttrName.getField()) {
+                case "key":
+                    for (Any<?> any : anys) {
+                        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+                        PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                        attrValue.setStringValue(any.getKey());
+                        values.add(attrValue);
+                    }
+                    break;
 
-            case UserDerivedSchema:
-            case GroupDerivedSchema:
-            case AnyObjectDerivedSchema:
-                DerSchema derSchema = derSchemaDAO.find(mappingItem.getIntAttrName());
-                if (derSchema != null) {
+                case "username":
                     for (Any<?> any : anys) {
-                        String value = derAttrHandler.getValue(any, derSchema);
-                        if (value != null) {
-                            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                            attrValue.setStringValue(value);
+                        if (any instanceof User) {
+                            UPlainAttrValue attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                            attrValue.setStringValue(((User) any).getUsername());
                             values.add(attrValue);
-
-                            LOG.debug("Retrieved values for {}"
-                                    + "\n* IntAttrName {}"
-                                    + "\n* IntMappingType {}"
-                                    + "\n* Attribute values {}",
-                                    derSchema.getKey(), mappingItem.getIntAttrName(), mappingItem.getIntMappingType(),
-                                    values);
                         }
                     }
-                }
-                break;
-
-            case UserVirtualSchema:
-            case GroupVirtualSchema:
-            case AnyObjectVirtualSchema:
-                // virtual attributes don't get transformed
-                transform = false;
+                    break;
 
-                VirSchema virSchema = virSchemaDAO.find(mappingItem.getIntAttrName());
-                if (virSchema != null) {
+                case "name":
                     for (Any<?> any : anys) {
-                        LOG.debug("Expire entry cache {}-{}", any.getKey(), mappingItem.getIntAttrName());
-                        virAttrCache.expire(any.getType().getKey(), any.getKey(), mappingItem.getIntAttrName());
-
-                        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                        for (String value : virAttrHandler.getValues(any, virSchema)) {
-                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                            attrValue.setStringValue(value);
+                        if (any instanceof Group) {
+                            GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
+                            attrValue.setStringValue(((Group) any).getName());
+                            values.add(attrValue);
+                        } else if (any instanceof AnyObject) {
+                            APlainAttrValue attrValue = entityFactory.newEntity(APlainAttrValue.class);
+                            attrValue.setStringValue(((AnyObject) any).getName());
                             values.add(attrValue);
                         }
-
-                        LOG.debug("Retrieved values for {}"
-                                + "\n* IntAttrName {}"
-                                + "\n* IntMappingType {}"
-                                + "\n* Attribute values {}",
-                                virSchema.getKey(), mappingItem.getIntAttrName(), mappingItem.getIntMappingType(),
-                                values);
                     }
-                }
-                break;
+                    break;
 
-            case UserKey:
-            case GroupKey:
-            case AnyObjectKey:
-                for (Any<?> any : anys) {
-                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-                    PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                    attrValue.setStringValue(any.getKey());
-                    values.add(attrValue);
-                }
-                break;
+                case "owner":
+                    Mapping uMapping = provision.getAnyType().equals(anyTypeDAO.findUser())
+                            ? provision.getMapping()
+                            : null;
+                    Mapping gMapping = provision.getAnyType().equals(anyTypeDAO.findGroup())
+                            ? provision.getMapping()
+                            : null;
 
-            case Username:
-                for (Any<?> any : anys) {
-                    if (any instanceof User) {
-                        UPlainAttrValue attrValue = entityFactory.newEntity(UPlainAttrValue.class);
-                        attrValue.setStringValue(((User) any).getUsername());
-                        values.add(attrValue);
-                    }
-                }
-                break;
+                    for (Any<?> any : anys) {
+                        if (any instanceof Group) {
+                            Group group = (Group) any;
+                            String groupOwnerValue = null;
+                            if (group.getUserOwner() != null && uMapping != null) {
+                                groupOwnerValue = getGroupOwnerValue(provision, group.getUserOwner());
+                            }
+                            if (group.getGroupOwner() != null && gMapping != null) {
+                                groupOwnerValue = getGroupOwnerValue(provision, group.getGroupOwner());
+                            }
 
-            case GroupName:
-                for (Any<?> any : anys) {
-                    if (any instanceof Group) {
-                        GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
-                        attrValue.setStringValue(((Group) any).getName());
-                        values.add(attrValue);
+                            if (StringUtils.isNotBlank(groupOwnerValue)) {
+                                GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
+                                attrValue.setStringValue(groupOwnerValue);
+                                values.add(attrValue);
+                            }
+                        }
                     }
-                }
-                break;
+                    break;
 
-            case GroupOwnerSchema:
-                Mapping uMapping = provision.getAnyType().equals(anyTypeDAO.findUser())
-                        ? provision.getMapping()
-                        : null;
-                Mapping gMapping = provision.getAnyType().equals(anyTypeDAO.findGroup())
-                        ? provision.getMapping()
-                        : null;
-
-                for (Any<?> any : anys) {
-                    if (any instanceof Group) {
-                        Group group = (Group) any;
-                        String groupOwnerValue = null;
-                        if (group.getUserOwner() != null && uMapping != null) {
-                            groupOwnerValue = getGroupOwnerValue(provision, group.getUserOwner());
-                        }
-                        if (group.getGroupOwner() != null && gMapping != null) {
-                            groupOwnerValue = getGroupOwnerValue(provision, group.getGroupOwner());
+                default:
+            }
+        } else if (intAttrName.getSchemaType() != null) {
+            switch (intAttrName.getSchemaType()) {
+                case PLAIN:
+                    for (Any<?> any : anys) {
+                        PlainAttr<?> attr = any.getPlainAttr(intAttrName.getSchemaName());
+                        if (attr != null) {
+                            if (attr.getUniqueValue() != null) {
+                                PlainAttrUniqueValue value = SerializationUtils.clone(attr.getUniqueValue());
+                                value.setAttr(null);
+                                values.add(value);
+                            } else if (attr.getValues() != null) {
+                                for (PlainAttrValue value : attr.getValues()) {
+                                    PlainAttrValue shadow = SerializationUtils.clone(value);
+                                    shadow.setAttr(null);
+                                    values.add(shadow);
+                                }
+                            }
                         }
-
-                        if (StringUtils.isNotBlank(groupOwnerValue)) {
-                            GPlainAttrValue attrValue = entityFactory.newEntity(GPlainAttrValue.class);
-                            attrValue.setStringValue(groupOwnerValue);
-                            values.add(attrValue);
+                    }
+                    break;
+
+                case DERIVED:
+                    DerSchema derSchema = derSchemaDAO.find(intAttrName.getSchemaName());
+                    if (derSchema != null) {
+                        for (Any<?> any : anys) {
+                            String value = derAttrHandler.getValue(any, derSchema);
+                            if (value != null) {
+                                AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+                                PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                                attrValue.setStringValue(value);
+                                values.add(attrValue);
+                            }
                         }
                     }
-                }
-                break;
+                    break;
 
-            case AnyObjectName:
-                for (Any<?> any : anys) {
-                    if (any instanceof AnyObject) {
-                        APlainAttrValue attrValue = entityFactory.newEntity(APlainAttrValue.class);
-                        attrValue.setStringValue(((AnyObject) any).getName());
-                        values.add(attrValue);
+                case VIRTUAL:
+                    // virtual attributes don't get transformed
+                    transform = false;
+
+                    VirSchema virSchema = virSchemaDAO.find(intAttrName.getSchemaName());
+                    if (virSchema != null) {
+                        for (Any<?> any : anys) {
+                            LOG.debug("Expire entry cache {}-{}", any.getKey(), intAttrName.getSchemaName());
+                            virAttrCache.expire(any.getType().getKey(), any.getKey(), intAttrName.getSchemaName());
+
+                            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+                            for (String value : virAttrHandler.getValues(any, virSchema)) {
+                                PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                                attrValue.setStringValue(value);
+                                values.add(attrValue);
+                            }
+                        }
                     }
-                }
-                break;
+                    break;
 
-            default:
+                default:
+            }
         }
 
         LOG.debug("Values for propagation: {}", values);
 
         List<PlainAttrValue> transformed = values;
         if (transform) {
-            for (MappingItemTransformer transformer : getMappingItemTransformers(mappingItem)) {
-                transformed = transformer.beforePropagation(mappingItem, anys, transformed);
+            for (MappingItemTransformer transformer : getMappingItemTransformers(mapItem)) {
+                transformed = transformer.beforePropagation(mapItem, anys, transformed);
             }
             LOG.debug("Transformed values for propagation: {}", values);
         } else {
@@ -728,13 +692,6 @@ public class MappingManagerImpl implements MappingManager {
         return transformed;
     }
 
-    /**
-     * Get connObjectKey internal value.
-     *
-     * @param any any object
-     * @param provision provision information
-     * @return connObjectKey internal value
-     */
     @Transactional(readOnly = true)
     @Override
     public String getConnObjectKeyValue(final Any<?> any, final Provision provision) {
@@ -745,146 +702,134 @@ public class MappingManagerImpl implements MappingManager {
                 : values.get(0).getValueAsString();
     }
 
-    /**
-     * Set attribute values, according to the given {@link MappingItem}, to any object from attribute received from
-     * connector.
-     *
-     * @param mappingItem mapping item
-     * @param attr attribute received from connector
-     * @param anyTO any object
-     * @param anyUtils any utils
-     */
     @Transactional(readOnly = true)
     @Override
     public void setIntValues(
-            final MappingItem mappingItem, final Attribute attr, final AnyTO anyTO, final AnyUtils anyUtils) {
+            final MappingItem mapItem, final Attribute attr, final AnyTO anyTO, final AnyUtils anyUtils) {
 
         List<Object> values = null;
         if (attr != null) {
             values = attr.getValue();
-            for (MappingItemTransformer transformer : getMappingItemTransformers(mappingItem)) {
-                values = transformer.beforePull(mappingItem, anyTO, values);
+            for (MappingItemTransformer transformer : getMappingItemTransformers(mapItem)) {
+                values = transformer.beforePull(mapItem, anyTO, values);
             }
         }
         values = ListUtils.emptyIfNull(values);
 
-        switch (mappingItem.getIntMappingType()) {
-            case UserKey:
-            case GroupKey:
-            case AnyObjectKey:
-                break;
-
-            case Password:
-                if (anyTO instanceof UserTO && !values.isEmpty()) {
-                    ((UserTO) anyTO).setPassword(ConnObjectUtils.getPassword(values.get(0)));
-                }
-                break;
-
-            case Username:
-                if (anyTO instanceof UserTO) {
-                    ((UserTO) anyTO).setUsername(values.isEmpty() || values.get(0) == null
-                            ? null
-                            : values.get(0).toString());
-                }
-                break;
+        IntAttrName intAttrName =
+                IntAttrNameParser.parse(mapItem.getIntAttrName(), anyUtilsFactory, anyUtils.getAnyTypeKind());
 
-            case GroupName:
-                if (anyTO instanceof GroupTO) {
-                    ((GroupTO) anyTO).setName(values.isEmpty() || values.get(0) == null
-                            ? null
-                            : values.get(0).toString());
-                }
-                break;
+        if (intAttrName.getField() != null) {
+            switch (intAttrName.getField()) {
+                case "key":
+                    break;
 
-            case GroupOwnerSchema:
-                if (anyTO instanceof GroupTO && attr != null) {
-                    // using a special attribute (with schema "", that will be ignored) for carrying the
-                    // GroupOwnerSchema value
-                    AttrTO attrTO = new AttrTO();
-                    attrTO.setSchema(StringUtils.EMPTY);
-                    if (values.isEmpty() || values.get(0) == null) {
-                        attrTO.getValues().add(StringUtils.EMPTY);
-                    } else {
-                        attrTO.getValues().add(values.get(0).toString());
+                case "password":
+                    if (anyTO instanceof UserTO && !values.isEmpty()) {
+                        ((UserTO) anyTO).setPassword(ConnObjectUtils.getPassword(values.get(0)));
                     }
+                    break;
 
-                    ((GroupTO) anyTO).getPlainAttrs().add(attrTO);
-                }
-                break;
+                case "username":
+                    if (anyTO instanceof UserTO) {
+                        ((UserTO) anyTO).setUsername(values.isEmpty() || values.get(0) == null
+                                ? null
+                                : values.get(0).toString());
+                    }
+                    break;
+
+                case "name":
+                    if (anyTO instanceof GroupTO) {
+                        ((GroupTO) anyTO).setName(values.isEmpty() || values.get(0) == null
+                                ? null
+                                : values.get(0).toString());
+                    } else if (anyTO instanceof AnyObjectTO) {
+                        ((AnyObjectTO) anyTO).setName(values.isEmpty() || values.get(0) == null
+                                ? null
+                                : values.get(0).toString());
+                    }
+                    break;
+
+                case "owner":
+                    if (anyTO instanceof GroupTO && attr != null) {
+                        // using a special attribute (with schema "", that will be ignored) for carrying the
+                        // GroupOwnerSchema value
+                        AttrTO attrTO = new AttrTO();
+                        attrTO.setSchema(StringUtils.EMPTY);
+                        if (values.isEmpty() || values.get(0) == null) {
+                            attrTO.getValues().add(StringUtils.EMPTY);
+                        } else {
+                            attrTO.getValues().add(values.get(0).toString());
+                        }
 
-            case AnyObjectName:
-                if (anyTO instanceof AnyObjectTO) {
-                    ((AnyObjectTO) anyTO).setName(values.isEmpty() || values.get(0) == null
-                            ? null
-                            : values.get(0).toString());
-                }
-                break;
+                        ((GroupTO) anyTO).getPlainAttrs().add(attrTO);
+                    }
+                    break;
 
-            case UserPlainSchema:
-            case GroupPlainSchema:
-            case AnyObjectPlainSchema:
-                AttrTO attrTO = new AttrTO();
-                attrTO.setSchema(mappingItem.getIntAttrName());
+                default:
+            }
+        } else if (intAttrName.getSchemaType() != null) {
+            switch (intAttrName.getSchemaType()) {
+                case PLAIN:
+                    AttrTO attrTO = new AttrTO();
+                    attrTO.setSchema(intAttrName.getSchemaName());
 
-                PlainSchema schema = plainSchemaDAO.find(mappingItem.getIntAttrName());
+                    PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
 
-                for (Object value : values) {
-                    AttrSchemaType schemaType = schema == null ? AttrSchemaType.String : schema.getType();
-                    if (value != null) {
-                        PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
-                        switch (schemaType) {
-                            case String:
-                                attrValue.setStringValue(value.toString());
-                                break;
-
-                            case Binary:
-                                attrValue.setBinaryValue((byte[]) value);
-                                break;
-
-                            default:
-                                try {
-                                    attrValue.parseValue(schema, value.toString());
-                                } catch (ParsingValidationException e) {
-                                    LOG.error("While parsing provided value {}", value, e);
+                    for (Object value : values) {
+                        AttrSchemaType schemaType = schema == null ? AttrSchemaType.String : schema.getType();
+                        if (value != null) {
+                            PlainAttrValue attrValue = anyUtils.newPlainAttrValue();
+                            switch (schemaType) {
+                                case String:
                                     attrValue.setStringValue(value.toString());
-                                    schemaType = AttrSchemaType.String;
-                                }
-                                break;
+                                    break;
+
+                                case Binary:
+                                    attrValue.setBinaryValue((byte[]) value);
+                                    break;
+
+                                default:
+                                    try {
+                                        attrValue.parseValue(schema, value.toString());
+                                    } catch (ParsingValidationException e) {
+                                        LOG.error("While parsing provided value {}", value, e);
+                                        attrValue.setStringValue(value.toString());
+                                        schemaType = AttrSchemaType.String;
+                                    }
+                                    break;
+                            }
+                            attrTO.getValues().add(attrValue.getValueAsString(schemaType));
                         }
-                        attrTO.getValues().add(attrValue.getValueAsString(schemaType));
                     }
-                }
 
-                anyTO.getPlainAttrs().add(attrTO);
-                break;
+                    anyTO.getPlainAttrs().add(attrTO);
+                    break;
 
-            case UserDerivedSchema:
-            case GroupDerivedSchema:
-            case AnyObjectDerivedSchema:
-                attrTO = new AttrTO();
-                attrTO.setSchema(mappingItem.getIntAttrName());
-                anyTO.getDerAttrs().add(attrTO);
-                break;
+                case DERIVED:
+                    attrTO = new AttrTO();
+                    attrTO.setSchema(intAttrName.getSchemaName());
+                    anyTO.getDerAttrs().add(attrTO);
+                    break;
 
-            case UserVirtualSchema:
-            case GroupVirtualSchema:
-            case AnyObjectVirtualSchema:
-                attrTO = new AttrTO();
-                attrTO.setSchema(mappingItem.getIntAttrName());
+                case VIRTUAL:
+                    attrTO = new AttrTO();
+                    attrTO.setSchema(intAttrName.getSchemaName());
 
-                // virtual attributes don't get transformed, iterate over original attr.getValue()
-                for (Object value : (attr == null || attr.getValue() == null)
-                        ? Collections.emptyList() : attr.getValue()) {
+                    // virtual attributes don't get transformed, iterate over original attr.getValue()
+                    for (Object value : (attr == null || attr.getValue() == null)
+                            ? Collections.emptyList() : attr.getValue()) {
 
-                    if (value != null) {
-                        attrTO.getValues().add(value.toString());
+                        if (value != null) {
+                            attrTO.getValues().add(value.toString());
+                        }
                     }
-                }
 
-                anyTO.getVirAttrs().add(attrTO);
-                break;
+                    anyTO.getVirAttrs().add(attrTO);
+                    break;
 
-            default:
+                default:
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index 0ccbe14..ca94e16 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -38,7 +37,6 @@ 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.ClientExceptionType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.ResourceOperation;
@@ -96,11 +94,6 @@ abstract class AbstractAnyDataBinder {
 
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractAnyDataBinder.class);
 
-    private static final IntMappingType[] FOR_MANDATORY = new IntMappingType[] {
-        IntMappingType.AnyObjectPlainSchema, IntMappingType.AnyObjectDerivedSchema,
-        IntMappingType.UserPlainSchema, IntMappingType.UserDerivedSchema,
-        IntMappingType.GroupPlainSchema, IntMappingType.GroupDerivedSchema };
-
     @Autowired
     protected RealmDAO realmDAO;
 
@@ -224,10 +217,7 @@ abstract class AbstractAnyDataBinder {
 
         if (provision != null) {
             for (MappingItem item : provision.getMapping().getItems()) {
-                if (ArrayUtils.contains(FOR_MANDATORY, item.getIntMappingType())
-                        && (item.getPurpose() == MappingPurpose.PROPAGATION
-                        || item.getPurpose() == MappingPurpose.BOTH)) {
-
+                if ((item.getPurpose() == MappingPurpose.PROPAGATION || item.getPurpose() == MappingPurpose.BOTH)) {
                     List<PlainAttrValue> values = mappingManager.getIntValues(
                             provision, item, Collections.<Any<?>>singletonList(any));
                     if (values.isEmpty() && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
@@ -351,9 +341,7 @@ abstract class AbstractAnyDataBinder {
             for (MappingItem mapItem
                     : MappingManagerImpl.getPropagationMappingItems(resource.getProvision(any.getType()))) {
 
-                if (schema.getKey().equals(mapItem.getIntAttrName())
-                        && mapItem.getIntMappingType() == anyUtils.plainIntMappingType()) {
-
+                if (schema.getKey().equals(mapItem.getIntAttrName())) {
                     propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 
                     if (mapItem.isConnObjectKey() && !attr.getValuesAsStrings().isEmpty()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
index eb0c328..a9de5bd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
@@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.core.provisioning.api.data.NotificationDataBinder;
 import org.apache.syncope.common.lib.to.NotificationTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.Notification;
@@ -33,7 +34,9 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.MailTemplateDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.MailTemplate;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -55,6 +58,9 @@ public class NotificationDataBinderImpl implements NotificationDataBinder {
     @Autowired
     private EntityFactory entityFactory;
 
+    @Autowired
+    private AnyUtilsFactory anyUtilsFactory;
+
     @Override
     public NotificationTO getNotificationTO(final Notification notification) {
         NotificationTO result = new NotificationTO();
@@ -118,5 +124,8 @@ public class NotificationDataBinderImpl implements NotificationDataBinder {
                 return notificationTO.getAbouts().containsKey(anyAbout.getAnyType().getKey());
             }
         });
+
+        // 3. verify recipientAttrName
+        IntAttrNameParser.parse(notification.getRecipientAttrName(), anyUtilsFactory, AnyTypeKind.USER);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index e09972f..ddf5a14 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -31,7 +31,7 @@ import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
@@ -48,11 +48,14 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
 import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.identityconnectors.framework.common.objects.ObjectClass;
@@ -86,6 +89,9 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
     @Autowired
     private EntityFactory entityFactory;
 
+    @Autowired
+    private AnyUtilsFactory anyUtilsFactory;
+
     @Override
     public ExternalResource create(final ResourceTO resourceTO) {
         return update(entityFactory.newEntity(ExternalResource.class), resourceTO);
@@ -259,44 +265,37 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                 SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
         for (MappingItemTO itemTO : mappingTO.getItems()) {
-            if (itemTO == null || itemTO.getIntMappingType() == null) {
-                LOG.error("Null {} or missing {}",
-                        MappingItemTO.class.getSimpleName(), IntMappingType.class.getSimpleName());
-                invalidMapping.getElements().add(
-                        "Null " + MappingItemTO.class.getSimpleName()
-                        + " or missing " + IntMappingType.class.getSimpleName());
+            if (itemTO == null) {
+                LOG.error("Null {}", MappingItemTO.class.getSimpleName());
+                invalidMapping.getElements().add("Null " + MappingItemTO.class.getSimpleName());
             } else {
                 if (itemTO.getIntAttrName() == null) {
-                    if (IntMappingType.getEmbedded().contains(itemTO.getIntMappingType())) {
-                        itemTO.setIntAttrName(itemTO.getIntMappingType().toString());
-                    } else {
-                        requiredValuesMissing.getElements().add("intAttrName");
-                        scce.addException(requiredValuesMissing);
-                    }
+                    requiredValuesMissing.getElements().add("intAttrName");
+                    scce.addException(requiredValuesMissing);
                 }
 
-                boolean allowed;
-                switch (itemTO.getIntMappingType()) {
-                    case UserPlainSchema:
-                    case GroupPlainSchema:
-                    case AnyObjectPlainSchema:
-                        allowed = allowedSchemas.getPlainSchemas().contains(itemTO.getIntAttrName());
-                        break;
-
-                    case UserDerivedSchema:
-                    case GroupDerivedSchema:
-                    case AnyObjectDerivedSchema:
-                        allowed = allowedSchemas.getDerSchemas().contains(itemTO.getIntAttrName());
-                        break;
-
-                    case UserVirtualSchema:
-                    case GroupVirtualSchema:
-                    case AnyObjectVirtualSchema:
-                        allowed = allowedSchemas.getVirSchemas().contains(itemTO.getIntAttrName());
-                        break;
-
-                    default:
-                        allowed = true;
+                IntAttrName intAttrName = IntAttrNameParser.parse(
+                        itemTO.getIntAttrName(),
+                        anyUtilsFactory,
+                        mapping.getProvision().getAnyType().getKind());
+
+                boolean allowed = true;
+                if (intAttrName.getSchemaType() != null) {
+                    switch (intAttrName.getSchemaType()) {
+                        case PLAIN:
+                            allowed = allowedSchemas.getPlainSchemas().contains(itemTO.getIntAttrName());
+                            break;
+
+                        case DERIVED:
+                            allowed = allowedSchemas.getDerSchemas().contains(itemTO.getIntAttrName());
+                            break;
+
+                        case VIRTUAL:
+                            allowed = allowedSchemas.getVirSchemas().contains(itemTO.getIntAttrName());
+                            break;
+
+                        default:
+                    }
                 }
 
                 if (allowed) {
@@ -314,6 +313,13 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                     BeanUtils.copyProperties(itemTO, item, MAPPINGITEM_IGNORE_PROPERTIES);
                     item.setMapping(mapping);
                     if (item.isConnObjectKey()) {
+                        if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
+                            throw new IllegalArgumentException("Virtual attributes cannot be set as ConnObjectKey");
+                        }
+                        if ("password".equals(intAttrName.getField())) {
+                            throw new IllegalArgumentException("Password attributes cannot be set as ConnObjectKey");
+                        }
+
                         mapping.setConnObjectKeyItem(item);
                     } else {
                         mapping.add(item);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index af872c1..d0229f9 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -33,7 +33,6 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditElements.Result;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -63,10 +62,13 @@ import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
@@ -150,6 +152,9 @@ public class NotificationManagerImpl implements NotificationManager {
     @Autowired
     private EntityFactory entityFactory;
 
+    @Autowired
+    private AnyUtilsFactory anyUtilsFactory;
+
     @Transactional(readOnly = true)
     @Override
     public long getMaxRetries() {
@@ -190,8 +195,7 @@ public class NotificationManagerImpl implements NotificationManager {
         for (User recipient : recipients) {
             virAttrHander.getValues(recipient);
 
-            String email = getRecipientEmail(notification.getRecipientAttrType(),
-                    notification.getRecipientAttrName(), recipient);
+            String email = getRecipientEmail(notification.getRecipientAttrName(), recipient);
             if (email == null) {
                 LOG.warn("{} cannot be notified: {} not found", recipient, notification.getRecipientAttrName());
             } else {
@@ -339,43 +343,43 @@ public class NotificationManagerImpl implements NotificationManager {
         return notifications;
     }
 
-    private String getRecipientEmail(
-            final IntMappingType recipientAttrType, final String recipientAttrName, final User user) {
-
+    private String getRecipientEmail(final String recipientAttrName, final User user) {
         String email = null;
 
-        switch (recipientAttrType) {
-            case Username:
-                email = user.getUsername();
-                break;
+        IntAttrName intAttrName = IntAttrNameParser.parse(recipientAttrName, anyUtilsFactory, AnyTypeKind.USER);
 
-            case UserPlainSchema:
-                UPlainAttr attr = user.getPlainAttr(recipientAttrName);
-                if (attr != null) {
-                    email = attr.getValuesAsStrings().isEmpty() ? null : attr.getValuesAsStrings().get(0);
-                }
-                break;
-
-            case UserDerivedSchema:
-                DerSchema schema = derSchemaDAO.find(recipientAttrName);
-                if (schema == null) {
-                    LOG.warn("Ignoring non existing {} {}", DerSchema.class.getSimpleName(), recipientAttrName);
-                } else {
-                    email = derAttrHander.getValue(user, schema);
-                }
-                break;
-
-            case UserVirtualSchema:
-                VirSchema virSchema = virSchemaDAO.find(recipientAttrName);
-                if (virSchema == null) {
-                    LOG.warn("Ignoring non existing {} {}", VirSchema.class.getSimpleName(), recipientAttrName);
-                } else {
-                    List<String> virAttrValues = virAttrHander.getValues(user, virSchema);
-                    email = virAttrValues.isEmpty() ? null : virAttrValues.get(0);
-                }
-                break;
+        if ("username".equals(intAttrName.getField())) {
+            email = user.getUsername();
+        } else if (intAttrName.getSchemaType() != null) {
+            switch (intAttrName.getSchemaType()) {
+                case PLAIN:
+                    UPlainAttr attr = user.getPlainAttr(recipientAttrName);
+                    if (attr != null) {
+                        email = attr.getValuesAsStrings().isEmpty() ? null : attr.getValuesAsStrings().get(0);
+                    }
+                    break;
+
+                case DERIVED:
+                    DerSchema schema = derSchemaDAO.find(recipientAttrName);
+                    if (schema == null) {
+                        LOG.warn("Ignoring non existing {} {}", DerSchema.class.getSimpleName(), recipientAttrName);
+                    } else {
+                        email = derAttrHander.getValue(user, schema);
+                    }
+                    break;
+
+                case VIRTUAL:
+                    VirSchema virSchema = virSchemaDAO.find(recipientAttrName);
+                    if (virSchema == null) {
+                        LOG.warn("Ignoring non existing {} {}", VirSchema.class.getSimpleName(), recipientAttrName);
+                    } else {
+                        List<String> virAttrValues = virAttrHander.getValues(user, virSchema);
+                        email = virAttrValues.isEmpty() ? null : virAttrValues.get(0);
+                    }
+                    break;
 
-            default:
+                default:
+            }
         }
 
         return email;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/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 995f483..a2c9271 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
@@ -47,6 +47,8 @@ import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
 import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -155,10 +157,10 @@ public class PullUtils {
         return result;
     }
 
-    private AnyDAO<?> getAnyDAO(final MappingItem connObjectKeyItem) {
-        return AnyTypeKind.USER == connObjectKeyItem.getIntMappingType().getAnyTypeKind()
+    private AnyDAO<?> getAnyDAO(final AnyTypeKind anyTypeKind) {
+        return AnyTypeKind.USER == anyTypeKind
                 ? userDAO
-                : AnyTypeKind.ANY_OBJECT == connObjectKeyItem.getIntMappingType().getAnyTypeKind()
+                : AnyTypeKind.ANY_OBJECT == anyTypeKind
                         ? anyObjectDAO
                         : groupDAO;
     }
@@ -181,72 +183,70 @@ public class PullUtils {
             }
         }
 
-        switch (connObjectKeyItem.getIntMappingType()) {
-            case UserPlainSchema:
-            case GroupPlainSchema:
-            case AnyObjectPlainSchema:
-                PlainAttrValue value = anyUtils.newPlainAttrValue();
+        IntAttrName intAttrName = IntAttrNameParser.parse(
+                connObjectKeyItem.getIntAttrName(),
+                anyUtilsFactory,
+                provision.getAnyType().getKind());
+
+        if (intAttrName.getField() != null) {
+            switch (intAttrName.getField()) {
+                case "key":
+                    Any<?> any = getAnyDAO(provision.getAnyType().getKind()).find(transfUid);
+                    if (any != null) {
+                        result.add(any.getKey());
+                    }
+                    break;
 
-                PlainSchema schema = plainSchemaDAO.find(connObjectKeyItem.getIntAttrName());
-                if (schema == null) {
-                    value.setStringValue(transfUid);
-                } else {
-                    try {
-                        value.parseValue(schema, transfUid);
-                    } catch (ParsingValidationException e) {
-                        LOG.error("While parsing provided __UID__ {}", transfUid, e);
-                        value.setStringValue(transfUid);
+                case "username":
+                    User user = userDAO.findByUsername(transfUid);
+                    if (user != null) {
+                        result.add(user.getKey());
                     }
-                }
+                    break;
 
-                List<? extends Any<?>> anys =
-                        getAnyDAO(connObjectKeyItem).findByAttrValue(connObjectKeyItem.getIntAttrName(), value);
-                for (Any<?> any : anys) {
-                    result.add(any.getKey());
-                }
-                break;
-
-            case UserDerivedSchema:
-            case GroupDerivedSchema:
-            case AnyObjectDerivedSchema:
-                anys = getAnyDAO(connObjectKeyItem).findByDerAttrValue(connObjectKeyItem.getIntAttrName(), transfUid);
-                for (Any<?> any : anys) {
-                    result.add(any.getKey());
-                }
-                break;
-
-            case UserKey:
-            case GroupKey:
-            case AnyObjectKey:
-                Any<?> any = getAnyDAO(connObjectKeyItem).find(transfUid);
-                if (any != null) {
-                    result.add(any.getKey());
-                }
-                break;
+                case "name":
+                    Group group = groupDAO.findByName(transfUid);
+                    if (group != null) {
+                        result.add(group.getKey());
+                    }
+                    AnyObject anyObject = anyObjectDAO.findByName(transfUid);
+                    if (anyObject != null) {
+                        result.add(anyObject.getKey());
+                    }
+                    break;
+            }
+        } else if (intAttrName.getSchemaType() != null) {
+            switch (intAttrName.getSchemaType()) {
+                case PLAIN:
+                    PlainAttrValue value = anyUtils.newPlainAttrValue();
 
-            case Username:
-                User user = userDAO.findByUsername(transfUid);
-                if (user != null) {
-                    result.add(user.getKey());
-                }
-                break;
+                    PlainSchema schema = plainSchemaDAO.find(intAttrName.getSchemaName());
+                    if (schema == null) {
+                        value.setStringValue(transfUid);
+                    } else {
+                        try {
+                            value.parseValue(schema, transfUid);
+                        } catch (ParsingValidationException e) {
+                            LOG.error("While parsing provided __UID__ {}", transfUid, e);
+                            value.setStringValue(transfUid);
+                        }
+                    }
 
-            case GroupName:
-                Group group = groupDAO.findByName(transfUid);
-                if (group != null) {
-                    result.add(group.getKey());
-                }
-                break;
+                    List<? extends Any<?>> anys = getAnyDAO(provision.getAnyType().getKind()).
+                            findByAttrValue(intAttrName.getSchemaName(), value);
+                    for (Any<?> any : anys) {
+                        result.add(any.getKey());
+                    }
+                    break;
 
-            case AnyObjectName:
-                AnyObject anyObject = anyObjectDAO.findByName(transfUid);
-                if (anyObject != null) {
-                    result.add(anyObject.getKey());
-                }
-                break;
-                
-            default:
-                LOG.error("Invalid connObjectKey type '{}'", connObjectKeyItem.getIntMappingType());
+                case DERIVED:
+                    anys = getAnyDAO(provision.getAnyType().getKind()).
+                            findByDerAttrValue(intAttrName.getSchemaName(), transfUid);
+                    for (Any<?> any : anys) {
+                        result.add(any.getKey());
+                    }
+                    break;
+            }
         }
 
         return result;

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/ResourceDataBinderTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/ResourceDataBinderTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/ResourceDataBinderTest.java
index 26f35cc..cb1612a 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/ResourceDataBinderTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/ResourceDataBinderTest.java
@@ -28,7 +28,6 @@ import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
@@ -89,7 +88,6 @@ public class ResourceDataBinderTest extends AbstractTest {
 
         MappingItemTO item = new MappingItemTO();
         item.setIntAttrName("userId");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("campo1");
         item.setConnObjectKey(true);
         item.setMandatoryCondition("false");

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConfigurationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConfigurationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConfigurationITCase.java
index 574c147..c6bde9c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConfigurationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConfigurationITCase.java
@@ -167,7 +167,7 @@ public class ConfigurationITCase extends AbstractITCase {
 
             assertNotNull(e.getElements());
             assertEquals(1, e.getElements().size());
-            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
index beb4cf0..067022b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ConnectorITCase.java
@@ -57,7 +57,6 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ConnConfPropSchema;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
 import org.apache.syncope.common.rest.api.service.ResourceService;
 import org.apache.syncope.fit.AbstractITCase;
@@ -674,7 +673,6 @@ public class ConnectorITCase extends AbstractITCase {
             MappingItemTO mapItem = new MappingItemTO();
             mapItem.setExtAttrName("uid");
             mapItem.setIntAttrName("userId");
-            mapItem.setIntMappingType(IntMappingType.UserPlainSchema);
             mapItem.setConnObjectKey(true);
             mapping.setConnObjectKeyItem(mapItem);
             // ----------------------------------------

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
index 8597974..71a3814 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
@@ -142,7 +142,7 @@ public class DerSchemaITCase extends AbstractITCase {
             fail();
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidDerSchema, e.getType());
-            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/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 b654ac1..a09b9bb 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
@@ -76,7 +76,6 @@ import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.BulkMembersActionType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
@@ -882,14 +881,12 @@ public class GroupITCase extends AbstractITCase {
             MappingTO mapping = newLDAP.getProvision(AnyTypeKind.GROUP.name()).getMapping();
 
             MappingItemTO connObjectKey = mapping.getConnObjectKeyItem();
-            connObjectKey.setIntMappingType(IntMappingType.GroupDerivedSchema);
             connObjectKey.setIntAttrName("displayProperty");
             connObjectKey.setPurpose(MappingPurpose.PROPAGATION);
             mapping.setConnObjectKeyItem(connObjectKey);
             mapping.setConnObjectLink("'cn=' + displayProperty + ',ou=groups,o=isp'");
 
             MappingItemTO description = new MappingItemTO();
-            description.setIntMappingType(IntMappingType.GroupKey);
             description.setExtAttrName("description");
             description.setPurpose(MappingPurpose.BOTH);
             mapping.add(description);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
index 1cec39a..a89fae3 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
@@ -49,7 +49,6 @@ import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.ConnConfPropSchema;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.common.lib.types.SchemaType;
@@ -260,7 +259,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         MappingItemTO item = new MappingItemTO();
         item.setIntAttrName("username");
-        item.setIntMappingType(IntMappingType.Username);
         item.setExtAttrName("username");
         item.setMandatoryCondition("true");
         item.setPurpose(MappingPurpose.PULL);
@@ -269,7 +267,6 @@ public class MigrationITCase extends AbstractTaskITCase {
         item = new MappingItemTO();
         item.setPassword(true);
         item.setIntAttrName("password");
-        item.setIntMappingType(IntMappingType.Password);
         item.setExtAttrName("__PASSWORD__");
         item.setMandatoryCondition("true");
         item.setPurpose(MappingPurpose.PULL);
@@ -277,7 +274,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName(MIGRATION_CIPHER_ALGORITHM);
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("cipherAlgorithm");
         item.setMandatoryCondition("true");
         item.setPurpose(MappingPurpose.PULL);
@@ -285,7 +281,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("surname");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("surname");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -293,7 +288,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("email");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("email");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -301,7 +295,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("firstname");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("firstname");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -309,7 +302,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("ctype");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("type");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -317,7 +309,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("gender");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("gender");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -325,7 +316,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("loginDate");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("loginDate");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -333,7 +323,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName(MIGRATION_RESOURCES_SCHEMA);
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("__RESOURCES__");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -351,7 +340,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("groupName");
-        item.setIntMappingType(IntMappingType.GroupName);
         item.setExtAttrName("name");
         item.setMandatoryCondition("true");
         item.setPurpose(MappingPurpose.PULL);
@@ -359,7 +347,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("show");
-        item.setIntMappingType(IntMappingType.GroupPlainSchema);
         item.setExtAttrName("show");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -367,7 +354,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("title");
-        item.setIntMappingType(IntMappingType.GroupPlainSchema);
         item.setExtAttrName("title");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -375,7 +361,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName("icon");
-        item.setIntMappingType(IntMappingType.GroupPlainSchema);
         item.setExtAttrName("icon");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -383,7 +368,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName(MIGRATION_RESOURCES_SCHEMA);
-        item.setIntMappingType(IntMappingType.GroupPlainSchema);
         item.setExtAttrName("__RESOURCES__");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);
@@ -391,7 +375,6 @@ public class MigrationITCase extends AbstractTaskITCase {
 
         item = new MappingItemTO();
         item.setIntAttrName(MIGRATION_MEMBERSHIPS_SCHEMA);
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("__MEMBERSHIPS__");
         item.setMandatoryCondition("false");
         item.setPurpose(MappingPurpose.PULL);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
index 97745c3..2c5b023 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MultitenancyITCase.java
@@ -44,7 +44,6 @@ import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
@@ -157,21 +156,20 @@ public class MultitenancyITCase extends AbstractITCase {
 
             MappingItemTO item = new MappingItemTO();
             item.setIntAttrName("username");
-            item.setIntMappingType(IntMappingType.Username);
             item.setExtAttrName("cn");
             item.setPurpose(MappingPurpose.BOTH);
             mapping.setConnObjectKeyItem(item);
 
             item = new MappingItemTO();
             item.setPassword(true);
-            item.setIntMappingType(IntMappingType.Password);
+            item.setIntAttrName("password");
             item.setExtAttrName("userPassword");
             item.setPurpose(MappingPurpose.BOTH);
             item.setMandatoryCondition("true");
             mapping.add(item);
 
             item = new MappingItemTO();
-            item.setIntMappingType(IntMappingType.UserKey);
+            item.setIntAttrName("key");
             item.setPurpose(MappingPurpose.BOTH);
             item.setExtAttrName("sn");
             item.setMandatoryCondition("true");
@@ -179,7 +177,6 @@ public class MultitenancyITCase extends AbstractITCase {
 
             item = new MappingItemTO();
             item.setIntAttrName("email");
-            item.setIntMappingType(IntMappingType.UserPlainSchema);
             item.setPurpose(MappingPurpose.BOTH);
             item.setExtAttrName("mail");
             mapping.add(item);


[07/15] syncope git commit: Unique schema key across the three tables

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainSchemaValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainSchemaValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainSchemaValidator.java
index 4bbb240..2817795 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainSchemaValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainSchemaValidator.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.jpa.validation.entity;
 
 import javax.validation.ConstraintValidatorContext;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.EntityViolationType;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
@@ -29,37 +28,30 @@ public class PlainSchemaValidator extends AbstractValidator<PlainSchemaCheck, Pl
 
     @Override
     public boolean isValid(final PlainSchema schema, final ConstraintValidatorContext context) {
-        boolean isValid = schema.getKey() != null && !EntityTOUtils.ANY_FIELDS.contains(schema.getKey());
+        boolean isValid = schema.getType() != AttrSchemaType.Enum
+                || StringUtils.isNotBlank(schema.getEnumerationValues());
         if (!isValid) {
+            context.disableDefaultConstraintViolation();
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Invalid PlainSchema name")).
-                    addPropertyNode("name").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidSchemaEnum, "Enumeration values missing")).
+                    addPropertyNode("enumerationValues").addConstraintViolation();
         } else {
-            isValid = schema.getType() != AttrSchemaType.Enum
-                    || StringUtils.isNotBlank(schema.getEnumerationValues());
+            isValid = schema.getType() != AttrSchemaType.Encrypted
+                    || (schema.getSecretKey() != null && schema.getCipherAlgorithm() != null);
             if (!isValid) {
                 context.disableDefaultConstraintViolation();
                 context.buildConstraintViolationWithTemplate(
-                        getTemplate(EntityViolationType.InvalidSchemaEnum, "Enumeration values missing")).
-                        addPropertyNode("enumerationValues").addConstraintViolation();
+                        getTemplate(EntityViolationType.InvalidSchemaEncrypted,
+                                "SecretKey or CipherAlgorithm missing")).
+                        addPropertyNode("secretKey").addPropertyNode("cipherAlgorithm").addConstraintViolation();
             } else {
-                isValid = schema.getType() != AttrSchemaType.Encrypted
-                        || (schema.getSecretKey() != null && schema.getCipherAlgorithm() != null);
+                isValid = !schema.isMultivalue() || !schema.isUniqueConstraint();
                 if (!isValid) {
                     context.disableDefaultConstraintViolation();
                     context.buildConstraintViolationWithTemplate(
-                            getTemplate(EntityViolationType.InvalidSchemaEncrypted,
-                                    "SecretKey or CipherAlgorithm missing")).
-                            addPropertyNode("secretKey").addPropertyNode("cipherAlgorithm").addConstraintViolation();
-                } else {
-                    isValid = !schema.isMultivalue() || !schema.isUniqueConstraint();
-                    if (!isValid) {
-                        context.disableDefaultConstraintViolation();
-                        context.buildConstraintViolationWithTemplate(
-                                getTemplate(EntityViolationType.InvalidSchemaMultivalueUnique,
-                                        "Cannot contemporary be multivalue and have unique constraint")).
-                                addPropertyNode("multiValue").addConstraintViolation();
-                    }
+                            getTemplate(EntityViolationType.InvalidSchemaMultivalueUnique,
+                                    "Cannot contemporary be multivalue and have unique constraint")).
+                            addPropertyNode("multiValue").addConstraintViolation();
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
index 8051bda..9953859 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RelationshipTypeValidator.java
@@ -31,8 +31,8 @@ public class RelationshipTypeValidator extends AbstractValidator<RelationshipTyp
 
         if (MembershipType.getInstance().getKey().equalsIgnoreCase(object.getKey())) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Invalid RelationshipType name")).
-                    addPropertyNode("name").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidKey, "Invalid relationshipType name")).
+                    addPropertyNode("key").addConstraintViolation();
             return false;
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RoleValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RoleValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RoleValidator.java
index 29558a0..c1de34d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RoleValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/RoleValidator.java
@@ -28,10 +28,10 @@ public class RoleValidator extends AbstractValidator<RoleCheck, Role> {
     public boolean isValid(final Role role, final ConstraintValidatorContext context) {
         context.disableDefaultConstraintViolation();
 
-        if (role.getKey() == null || !NAME_PATTERN.matcher(role.getKey()).matches()) {
+        if (role.getKey() == null || !KEY_PATTERN.matcher(role.getKey()).matches()) {
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Invalid Role name")).
-                    addPropertyNode("name").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidKey, "Invalid role key")).
+                    addPropertyNode("key").addConstraintViolation();
             return false;
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchemaKeyValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchemaKeyValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchemaKeyValidator.java
index b4d00d5..8c71620 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchemaKeyValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/SchemaKeyValidator.java
@@ -18,77 +18,37 @@
  */
 package org.apache.syncope.core.persistence.jpa.validation.entity;
 
-import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 import javax.validation.ConstraintValidatorContext;
-import org.apache.commons.lang3.ClassUtils;
 import org.apache.syncope.common.lib.types.EntityViolationType;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
-import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAnyObject;
-import org.apache.syncope.core.persistence.jpa.entity.conf.JPAConf;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtils;
 
 public class SchemaKeyValidator extends AbstractValidator<SchemaKeyCheck, Object> {
 
-    private static final Set<String> UNALLOWED_SCHEMA_KEYS = new HashSet<>();
-
-    static {
-        initUnallowedSchemaKeys(JPAAnyObject.class, UNALLOWED_SCHEMA_KEYS);
-        initUnallowedSchemaKeys(JPAGroup.class, UNALLOWED_SCHEMA_KEYS);
-        initUnallowedSchemaKeys(JPAUser.class, UNALLOWED_SCHEMA_KEYS);
-        initUnallowedSchemaKeys(JPAConf.class, UNALLOWED_SCHEMA_KEYS);
-    }
-
-    private static void initUnallowedSchemaKeys(final Class<?> entityClass, final Set<String> keys) {
-        List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
-        if (!classes.contains(JPAUser.class)) {
-            classes.add(JPAUser.class);
-        }
-        for (Class<?> clazz : classes) {
-            for (Field field : clazz.getDeclaredFields()) {
-                if (!Collection.class.isAssignableFrom(field.getType())
-                        && !Map.class.isAssignableFrom(field.getType())) {
-
-                    keys.add(field.getName());
-                }
-            }
-        }
-    }
-
     @Override
     public boolean isValid(final Object object, final ConstraintValidatorContext context) {
-        String schemaName;
-        Set<String> unallowedNames = UNALLOWED_SCHEMA_KEYS;
+        String key = null;
         if (object instanceof PlainSchema) {
-            schemaName = ((PlainSchema) object).getKey();
+            key = ((PlainSchema) object).getKey();
         } else if (object instanceof DerSchema) {
-            schemaName = ((DerSchema) object).getKey();
+            key = ((DerSchema) object).getKey();
         } else if (object instanceof VirSchema) {
-            schemaName = ((VirSchema) object).getKey();
-        } else {
-            schemaName = null;
-            unallowedNames = Collections.emptySet();
+            key = ((VirSchema) object).getKey();
         }
 
-        boolean isValid = NAME_PATTERN.matcher(schemaName).matches();
+        boolean isValid = KEY_PATTERN.matcher(key).matches();
         if (!isValid) {
             context.disableDefaultConstraintViolation();
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Invalid Schema name")).
-                    addPropertyNode("name").addConstraintViolation();
-        } else if (unallowedNames.contains(schemaName)) {
+                    getTemplate(EntityViolationType.InvalidKey, "Invalid schema key")).
+                    addPropertyNode("key").addConstraintViolation();
+        } else if (JPAAnyUtils.matchesFieldName(key)) {
             context.disableDefaultConstraintViolation();
             context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidName, "Schema name not allowed: " + schemaName)).
-                    addPropertyNode("name").addConstraintViolation();
+                    getTemplate(EntityViolationType.InvalidKey, "Schema key not allowed: " + key)).
+                    addPropertyNode("key").addConstraintViolation();
 
             return false;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/domains/MasterContent.xml b/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
index b5b4c9a..675a30c 100644
--- a/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/main/resources/domains/MasterContent.xml
@@ -22,6 +22,7 @@ under the License.
 
   <SyncopeConf id="cd64d66f-6fff-4008-b966-a06b1cc1436d"/>
 
+  <SyncopeSchema id="password.cipher.algorithm"/>
   <PlainSchema id="password.cipher.algorithm" type="String"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="56db89b9-119e-4923-a16e-f42823b90c66" 
@@ -33,6 +34,7 @@ under the License.
   + not existing: NotificationJob runs according to NotificationJob.DEFAULT_CRON_EXP
   + provided as empty string: NotificationJob disabled
   + provided as non-empty string: NotificationJob runs according to the given value -->
+  <SyncopeSchema id="notificationjob.cronExpression"/>
   <PlainSchema id="notificationjob.cronExpression" type="String"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="abd5a2d2-25ee-48b7-b5ca-76813b54a6f2"
@@ -40,6 +42,7 @@ under the License.
   <CPlainAttrValue id="4828ea70-d151-4c16-b344-2d07b1956bee"
                    attribute_id="abd5a2d2-25ee-48b7-b5ca-76813b54a6f2" stringValue=""/>
   
+  <SyncopeSchema id="notification.maxRetries"/>
   <PlainSchema id="notification.maxRetries" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="0523d7e6-af13-4e1e-9edb-e35971aacee7"
@@ -47,6 +50,7 @@ under the License.
   <CPlainAttrValue id="010e2bdc-0094-4918-bac3-d0d5ea17b54a"
                    attribute_id="0523d7e6-af13-4e1e-9edb-e35971aacee7" longValue="3"/>
 
+  <SyncopeSchema id="token.length"/>
   <PlainSchema id="token.length" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="58977caa-dcf7-4ae3-8591-7e3d0a395200"
@@ -54,6 +58,7 @@ under the License.
   <CPlainAttrValue id="372e28e0-3af1-4774-b668-81aa84903b75"
                    attribute_id="58977caa-dcf7-4ae3-8591-7e3d0a395200" longValue="256"/>
 
+  <SyncopeSchema id="token.expireTime"/>
   <PlainSchema id="token.expireTime" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="01f69abd-df85-4e1b-bb88-ad570594e045"
@@ -61,6 +66,7 @@ under the License.
   <CPlainAttrValue id="963970cf-4af6-46bb-875b-a1b758ac8d05"
                    attribute_id="01f69abd-df85-4e1b-bb88-ad570594e045" longValue="60"/>
 
+  <SyncopeSchema id="selfRegistration.allowed"/>
   <PlainSchema id="selfRegistration.allowed" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="7b19cefa-d606-477c-8431-c9464f53fe8b"
@@ -68,6 +74,7 @@ under the License.
   <CPlainAttrValue id="c8b9a0f1-0168-4e2a-95b8-4819fc70e620"
                    attribute_id="7b19cefa-d606-477c-8431-c9464f53fe8b" booleanValue="1"/>
 
+  <SyncopeSchema id="passwordReset.allowed"/>
   <PlainSchema id="passwordReset.allowed" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="dc35cc97-6ed9-4bb2-bb3b-509f4cd8f3d3"
@@ -75,6 +82,7 @@ under the License.
   <CPlainAttrValue id="b1ecea41-ab7c-4dd3-9e3e-b6baf0f98046"
                    attribute_id="dc35cc97-6ed9-4bb2-bb3b-509f4cd8f3d3" booleanValue="1"/>
 
+  <SyncopeSchema id="passwordReset.securityQuestion"/>
   <PlainSchema id="passwordReset.securityQuestion" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="e5a712ad-53fd-4102-ba55-fb45caed5f7b"
@@ -82,6 +90,7 @@ under the License.
   <CPlainAttrValue id="b5e8e79d-8039-4318-9698-fe5e181ebe98"
                    attribute_id="e5a712ad-53fd-4102-ba55-fb45caed5f7b" booleanValue="1"/>
 
+  <SyncopeSchema id="authentication.statuses"/>
   <PlainSchema id="authentication.statuses" type="String" multivalue="1" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="888ae8e1-a295-4ee2-a15e-31dbf6dfc3f9"
               owner_id="cd64d66f-6fff-4008-b966-a06b1cc1436d" schema_id="authentication.statuses"/>
@@ -91,6 +100,7 @@ under the License.
                    attribute_id="888ae8e1-a295-4ee2-a15e-31dbf6dfc3f9" stringValue="active"/>
 
   <!-- Save user login date upon successful authentication -->
+  <SyncopeSchema id="log.lastlogindate"/>
   <PlainSchema id="log.lastlogindate" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="9891c0a7-27ee-4215-9eea-ca32e580b4e4"
@@ -98,6 +108,7 @@ under the License.
   <CPlainAttrValue id="162dd874-0417-4bb9-9724-db1ff2952dd1"
                    attribute_id="9891c0a7-27ee-4215-9eea-ca32e580b4e4" booleanValue="1"/>
 
+  <SyncopeSchema id="tasks.interruptMaxRetries"/>
   <PlainSchema id="tasks.interruptMaxRetries" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db"
@@ -106,6 +117,7 @@ under the License.
                    attribute_id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db" longValue="20"/>
   
   <!-- Return hashed password values when reading users -->
+  <SyncopeSchema id="return.password.value"/>
   <PlainSchema id="return.password.value" type="Boolean"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="bcfd7efc-0605-4b5e-b4bb-85c1d5f6493a"
@@ -122,6 +134,7 @@ under the License.
   <AnyType_AnyTypeClass anyType_id="GROUP" anyTypeClass_id="BaseGroup"/>
         
   <!-- Actual plain schemas -->
+  <SyncopeSchema id="email"/>
   <PlainSchema id="email" type="String" anyTypeClass_id="BaseUser"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                validatorClass="org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
@@ -165,13 +178,13 @@ we are happy to inform you that the password request was execute successfully fo
 &lt;/body&gt;
 &lt;/html&gt;"/>
 
-  <Notification id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" 
+  <Notification id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" active="1" recipientAttrName="email" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset request" template_id="requestPasswordReset" 
                 traceLevel="FAILURES"/> 
   <AnyAbout id="a328f2e6-25e9-4cc1-badf-7425d7be4b39" anyType_id="USER" notification_id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" filter="token!=$null"/>
   <Notification_events notification_id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" event="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/>
   
-  <Notification id="bef0c250-e8a7-4848-bb63-2564fc409ce2" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" 
+  <Notification id="bef0c250-e8a7-4848-bb63-2564fc409ce2" active="1" recipientAttrName="email" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset successful" template_id="confirmPasswordReset" 
                 traceLevel="FAILURES"/> 
   <Notification_events notification_id="bef0c250-e8a7-4848-bb63-2564fc409ce2" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConfTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConfTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConfTest.java
index c361614..511a359 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConfTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ConfTest.java
@@ -114,7 +114,7 @@ public class ConfTest extends AbstractTest {
 
             fail();
         } catch (InvalidEntityException e) {
-            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+            assertTrue(e.hasViolation(EntityViolationType.InvalidKey));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
index 7907381..97764b8 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
@@ -94,7 +94,7 @@ public class DerSchemaTest extends AbstractTest {
             derSchemaDAO.save(schema);
             fail();
         } catch (InvalidEntityException e) {
-            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+            assertTrue(e.hasViolation(EntityViolationType.InvalidKey));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/NotificationTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/NotificationTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/NotificationTest.java
index 94be88b..b2ef43c 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/NotificationTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/NotificationTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 
 import java.util.List;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.MailTemplateDAO;
 import org.apache.syncope.core.persistence.api.dao.NotificationDAO;
@@ -78,7 +77,6 @@ public class NotificationTest extends AbstractTest {
         notification.setRecipientsFIQL("fake recipients");
 
         notification.setRecipientAttrName("email");
-        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
 
         notification.setSender("syncope@syncope.apache.org");
         notification.setSubject("Test notification");
@@ -109,7 +107,6 @@ public class NotificationTest extends AbstractTest {
         notification.setRecipientsFIQL("fake search condition");
 
         notification.setRecipientAttrName("email");
-        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
 
         notification.getStaticRecipients().add("syncope445@syncope.apache.org");
 
@@ -136,7 +133,6 @@ public class NotificationTest extends AbstractTest {
         about.set("fake search condition");
 
         notification.setRecipientAttrName("email");
-        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
 
         notification.getStaticRecipients().add("syncope446@syncope.apache.org");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
index 8ded618..722eb5f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
@@ -101,13 +101,12 @@ public class PlainSchemaTest extends AbstractTest {
         schema.setType(AttrSchemaType.Enum);
         schema.setKey("color");
 
-        Exception ex = null;
         try {
             plainSchemaDAO.save(schema);
+            fail();
         } catch (Exception e) {
-            ex = e;
+            assertNotNull(e);
         }
-        assertNotNull(ex);
 
         schema.setEnumerationValues("red" + SyncopeConstants.ENUM_VALUES_SEPARATOR + "yellow");
         schema.setEnumerationKeys("1" + SyncopeConstants.ENUM_VALUES_SEPARATOR + "2");
@@ -146,7 +145,7 @@ public class PlainSchemaTest extends AbstractTest {
             plainSchemaDAO.save(schema);
             fail();
         } catch (InvalidEntityException e) {
-            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+            assertTrue(e.hasViolation(EntityViolationType.InvalidKey));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
index 19451e9..e08833f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
@@ -26,12 +26,9 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 import java.util.List;
-import java.util.UUID;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
@@ -120,7 +117,6 @@ public class ResourceTest extends AbstractTest {
         MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
         connObjectKey.setExtAttrName("username");
         connObjectKey.setIntAttrName("fullname");
-        connObjectKey.setIntMappingType(IntMappingType.UserKey);
         connObjectKey.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(connObjectKey);
 
@@ -157,7 +153,6 @@ public class ResourceTest extends AbstractTest {
 
         MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
         connObjectKey.setConnObjectKey(true);
-        connObjectKey.setIntMappingType(IntMappingType.UserPlainSchema);
         mapping.add(connObjectKey);
 
         // save the resource
@@ -184,7 +179,6 @@ public class ResourceTest extends AbstractTest {
 
         MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
         connObjectKey.setConnObjectKey(true);
-        connObjectKey.setIntMappingType(IntMappingType.UserVirtualSchema);
         mapping.setConnObjectKeyItem(connObjectKey);
 
         // save the resource
@@ -212,12 +206,10 @@ public class ResourceTest extends AbstractTest {
         MappingItem item = entityFactory.newEntity(MappingItem.class);
         item.setConnObjectKey(true);
         item.setIntAttrName("fullname");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         mapping.add(item);
 
         item = entityFactory.newEntity(MappingItem.class);
         item.setIntAttrName("userId");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         mapping.add(item);
 
         resourceDAO.save(resource);
@@ -241,7 +233,6 @@ public class ResourceTest extends AbstractTest {
         MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
         connObjectKey.setExtAttrName("username");
         connObjectKey.setIntAttrName("fullname");
-        connObjectKey.setIntMappingType(IntMappingType.UserKey);
         connObjectKey.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(connObjectKey);
 
@@ -277,12 +268,10 @@ public class ResourceTest extends AbstractTest {
         MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
         connObjectKey.setExtAttrName("username");
         connObjectKey.setIntAttrName("fullname");
-        connObjectKey.setIntMappingType(IntMappingType.UserKey);
         connObjectKey.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(connObjectKey);
 
         MappingItem virtualMapItem = entityFactory.newEntity(MappingItem.class);
-        virtualMapItem.setIntMappingType(IntMappingType.UserVirtualSchema);
         virtualMapItem.setIntAttrName("virtualReadOnly");
         virtualMapItem.setExtAttrName("TEST");
         virtualMapItem.setPurpose(MappingPurpose.BOTH);
@@ -324,21 +313,18 @@ public class ResourceTest extends AbstractTest {
         MappingItem item = entityFactory.newEntity(MappingItem.class);
         item.setIntAttrName("fullname");
         item.setExtAttrName("fullname");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
 
         item = entityFactory.newEntity(MappingItem.class);
         item.setIntAttrName("icon");
         item.setExtAttrName("icon");
-        item.setIntMappingType(IntMappingType.GroupPlainSchema);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.add(item);
 
         item = entityFactory.newEntity(MappingItem.class);
         item.setIntAttrName("mderiveddata");
         item.setExtAttrName("mderiveddata");
-        item.setIntMappingType(IntMappingType.AnyObjectDerivedSchema);
         item.setPurpose(MappingPurpose.PROPAGATION);
         mapping.add(item);
 
@@ -346,18 +332,7 @@ public class ResourceTest extends AbstractTest {
         ExternalResource actual = resourceDAO.save(resource);
         assertNotNull(actual);
 
-        int items = 0;
-        for (MappingItem mapItem : actual.getProvision(anyTypeDAO.findUser()).getMapping().getItems()) {
-            items++;
-
-            if ("icon".equals(mapItem.getIntAttrName())) {
-                assertTrue(IntMappingType.contains(AnyTypeKind.GROUP, mapItem.getIntMappingType().toString()));
-            }
-            if ("mderiveddata".equals(mapItem.getIntAttrName())) {
-                assertTrue(IntMappingType.contains(AnyTypeKind.ANY_OBJECT, mapItem.getIntMappingType().toString()));
-            }
-        }
-        assertEquals(3, items);
+        assertEquals(3, actual.getProvision(anyTypeDAO.findUser()).getMapping().getItems().size());
     }
 
     @Test
@@ -380,7 +355,7 @@ public class ResourceTest extends AbstractTest {
             resourceDAO.save(resource);
             fail();
         } catch (InvalidEntityException e) {
-            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+            assertTrue(e.hasViolation(EntityViolationType.InvalidKey));
         }
     }
 
@@ -405,7 +380,6 @@ public class ResourceTest extends AbstractTest {
         final MappingItem item = entityFactory.newEntity(MappingItem.class);
         item.setIntAttrName("icon");
         item.setExtAttrName("icon");
-        item.setIntMappingType(IntMappingType.GroupPlainSchema);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
index 19193dd..192ef0f 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
@@ -107,7 +107,7 @@ public class VirSchemaTest extends AbstractTest {
             virSchemaDAO.save(schema);
             fail();
         } catch (InvalidEntityException e) {
-            assertTrue(e.hasViolation(EntityViolationType.InvalidName));
+            assertTrue(e.hasViolation(EntityViolationType.InvalidKey));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PlainSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PlainSchemaTest.java
index 1c3ad04..b93acbb 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PlainSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/PlainSchemaTest.java
@@ -23,11 +23,15 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.util.HashSet;
 import java.util.Set;
 import java.util.UUID;
+import javax.persistence.EntityExistsException;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
@@ -54,12 +58,32 @@ public class PlainSchemaTest extends AbstractTest {
     private PlainSchemaDAO plainSchemaDAO;
 
     @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Autowired
     private PlainAttrDAO plainAttrDAO;
 
     @Autowired
     private ExternalResourceDAO resourceDAO;
 
     @Test
+    public void checkIdUniqueness() {
+        assertNotNull(derSchemaDAO.find("cn"));
+
+        PlainSchema schema = entityFactory.newEntity(PlainSchema.class);
+        schema.setKey("cn");
+        schema.setType(AttrSchemaType.String);
+        plainSchemaDAO.save(schema);
+
+        try {
+            plainSchemaDAO.flush();
+            fail();
+        } catch (Exception e) {
+            assertTrue(e instanceof EntityExistsException);
+        }
+    }
+
+    @Test
     public void deleteFullname() {
         // fullname is mapped as ConnObjectKey for ws-target-resource-2, need to swap it otherwise validation errors 
         // will be raised

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
index a8540bd..efe2349 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
@@ -29,7 +29,6 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
@@ -132,7 +131,6 @@ public class ResourceTest extends AbstractTest {
             MappingItem item = entityFactory.newEntity(MappingItem.class);
             item.setExtAttrName("test" + i);
             item.setIntAttrName("nonexistent" + i);
-            item.setIntMappingType(IntMappingType.UserPlainSchema);
             item.setMandatoryCondition("false");
             item.setPurpose(MappingPurpose.PULL);
             mapping.add(item);
@@ -141,7 +139,6 @@ public class ResourceTest extends AbstractTest {
         MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
         connObjectKey.setExtAttrName("username");
         connObjectKey.setIntAttrName("username");
-        connObjectKey.setIntMappingType(IntMappingType.UserKey);
         connObjectKey.setPurpose(MappingPurpose.PROPAGATION);
         mapping.setConnObjectKeyItem(connObjectKey);
         connObjectKey.setMapping(mapping);
@@ -151,7 +148,6 @@ public class ResourceTest extends AbstractTest {
         derived.setConnObjectKey(false);
         derived.setExtAttrName("fullname");
         derived.setIntAttrName("cn");
-        derived.setIntMappingType(IntMappingType.UserDerivedSchema);
         derived.setPurpose(MappingPurpose.PROPAGATION);
         mapping.add(derived);
         derived.setMapping(mapping);
@@ -299,7 +295,6 @@ public class ResourceTest extends AbstractTest {
         int origMapItems = csv.getProvision(anyTypeDAO.findUser()).getMapping().getItems().size();
 
         MappingItem newMapItem = entityFactory.newEntity(MappingItem.class);
-        newMapItem.setIntMappingType(IntMappingType.Username);
         newMapItem.setExtAttrName("TEST");
         newMapItem.setPurpose(MappingPurpose.PROPAGATION);
         csv.getProvision(anyTypeDAO.findUser()).getMapping().add(newMapItem);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
index 7a5b12e..7b00f82 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/VirSchemaTest.java
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
@@ -74,7 +73,6 @@ public class VirSchemaTest extends AbstractTest {
 
         MappingItem item = virSchema.asLinkingMappingItem();
         assertNotNull(item);
-        assertEquals(IntMappingType.UserVirtualSchema, item.getIntMappingType());
         assertEquals(virSchema.getKey(), item.getIntAttrName());
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index e956a90..2ff3310 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -22,6 +22,7 @@ under the License.
   
   <SyncopeConf id="cd64d66f-6fff-4008-b966-a06b1cc1436d"/>
 
+  <SyncopeSchema id="password.cipher.algorithm"/>
   <PlainSchema id="password.cipher.algorithm" type="String"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="56db89b9-119e-4923-a16e-f42823b90c66" 
@@ -33,6 +34,7 @@ under the License.
   + not existing: NotificationJob runs according to NotificationJob.DEFAULT_CRON_EXP
   + provided as empty string: NotificationJob disabled
   + provided as non-empty string: NotificationJob runs according to the given value -->
+  <SyncopeSchema id="notificationjob.cronExpression"/>
   <PlainSchema id="notificationjob.cronExpression" type="String"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="abd5a2d2-25ee-48b7-b5ca-76813b54a6f2"
@@ -40,6 +42,7 @@ under the License.
   <CPlainAttrValue id="4828ea70-d151-4c16-b344-2d07b1956bee"
                    attribute_id="abd5a2d2-25ee-48b7-b5ca-76813b54a6f2" stringValue="0/20 * * * * ?"/>
   
+  <SyncopeSchema id="notification.maxRetries"/>
   <PlainSchema id="notification.maxRetries" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="0523d7e6-af13-4e1e-9edb-e35971aacee7"
@@ -47,6 +50,7 @@ under the License.
   <CPlainAttrValue id="010e2bdc-0094-4918-bac3-d0d5ea17b54a"
                    attribute_id="0523d7e6-af13-4e1e-9edb-e35971aacee7" longValue="3"/>
 
+  <SyncopeSchema id="token.length"/>
   <PlainSchema id="token.length" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="58977caa-dcf7-4ae3-8591-7e3d0a395200"
@@ -54,6 +58,7 @@ under the License.
   <CPlainAttrValue id="372e28e0-3af1-4774-b668-81aa84903b75"
                    attribute_id="58977caa-dcf7-4ae3-8591-7e3d0a395200" longValue="256"/>
 
+  <SyncopeSchema id="token.expireTime"/>
   <PlainSchema id="token.expireTime" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="01f69abd-df85-4e1b-bb88-ad570594e045"
@@ -61,6 +66,7 @@ under the License.
   <CPlainAttrValue id="963970cf-4af6-46bb-875b-a1b758ac8d05"
                    attribute_id="01f69abd-df85-4e1b-bb88-ad570594e045" longValue="60"/>
 
+  <SyncopeSchema id="selfRegistration.allowed"/>
   <PlainSchema id="selfRegistration.allowed" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="7b19cefa-d606-477c-8431-c9464f53fe8b"
@@ -68,6 +74,7 @@ under the License.
   <CPlainAttrValue id="c8b9a0f1-0168-4e2a-95b8-4819fc70e620"
                    attribute_id="7b19cefa-d606-477c-8431-c9464f53fe8b" booleanValue="1"/>
 
+  <SyncopeSchema id="passwordReset.allowed"/>
   <PlainSchema id="passwordReset.allowed" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="dc35cc97-6ed9-4bb2-bb3b-509f4cd8f3d3"
@@ -75,6 +82,7 @@ under the License.
   <CPlainAttrValue id="b1ecea41-ab7c-4dd3-9e3e-b6baf0f98046"
                    attribute_id="dc35cc97-6ed9-4bb2-bb3b-509f4cd8f3d3" booleanValue="1"/>
 
+  <SyncopeSchema id="passwordReset.securityQuestion"/>
   <PlainSchema id="passwordReset.securityQuestion" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="e5a712ad-53fd-4102-ba55-fb45caed5f7b"
@@ -82,6 +90,7 @@ under the License.
   <CPlainAttrValue id="b5e8e79d-8039-4318-9698-fe5e181ebe98"
                    attribute_id="e5a712ad-53fd-4102-ba55-fb45caed5f7b" booleanValue="1"/>
 
+  <SyncopeSchema id="authentication.statuses"/>
   <PlainSchema id="authentication.statuses" type="String" multivalue="1" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="888ae8e1-a295-4ee2-a15e-31dbf6dfc3f9"
               owner_id="cd64d66f-6fff-4008-b966-a06b1cc1436d" schema_id="authentication.statuses"/>
@@ -91,6 +100,7 @@ under the License.
                    attribute_id="888ae8e1-a295-4ee2-a15e-31dbf6dfc3f9" stringValue="active"/>
 
   <!-- Save user login date upon successful authentication -->
+  <SyncopeSchema id="log.lastlogindate"/>
   <PlainSchema id="log.lastlogindate" type="Boolean"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="9891c0a7-27ee-4215-9eea-ca32e580b4e4"
@@ -98,6 +108,7 @@ under the License.
   <CPlainAttrValue id="162dd874-0417-4bb9-9724-db1ff2952dd1"
                    attribute_id="9891c0a7-27ee-4215-9eea-ca32e580b4e4" booleanValue="1"/>
 
+  <SyncopeSchema id="tasks.interruptMaxRetries"/>
   <PlainSchema id="tasks.interruptMaxRetries" type="Long"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db"
@@ -106,6 +117,7 @@ under the License.
                    attribute_id="c2b9ca96-c6ef-433d-8287-0e0cfd0ad0db" longValue="20"/>
   
   <!-- Return hashed password values when reading users -->
+  <SyncopeSchema id="return.password.value"/>
   <PlainSchema id="return.password.value" type="Boolean"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
   <CPlainAttr id="bcfd7efc-0605-4b5e-b4bb-85c1d5f6493a"
@@ -339,85 +351,121 @@ under the License.
   <UMembership id="8cfb78fc-d0e7-4f08-a0ae-d7abf3223b6f"
                user_id="823074dc-d280-436d-a7dd-07399fae48ec" group_id="ece66293-8f31-4a84-8e8d-23da36e70846"/>
 
+  <SyncopeSchema id="fullname"/>
   <PlainSchema id="fullname" type="String" anyTypeClass_id="minimal user"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="1" readonly="0"/>
+  <SyncopeSchema id="userId"/>
   <PlainSchema id="userId" type="String" anyTypeClass_id="minimal user"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="1" readonly="0"
                validatorClass="org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
+  <SyncopeSchema id="loginDate"/>
   <PlainSchema id="loginDate" type="Date" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"
                conversionPattern="yyyy-MM-dd"/>
+  <SyncopeSchema id="firstname"/>
   <PlainSchema id="firstname" type="String" anyTypeClass_id="minimal user"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="surname"/>
   <PlainSchema id="surname" type="String" anyTypeClass_id="minimal user"
                mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="ctype"/>
   <PlainSchema id="ctype" type="String" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="email"/>
   <PlainSchema id="email" type="String" anyTypeClass_id="minimal user"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                validatorClass="org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
+  <SyncopeSchema id="activationDate"/>
   <PlainSchema id="activationDate" type="Date" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                conversionPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ"/>
+  <SyncopeSchema id="uselessReadonly"/>
   <PlainSchema id="uselessReadonly" type="String" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="1"/>
+  <SyncopeSchema id="cool"/>
   <PlainSchema id="cool" type="Boolean" anyTypeClass_id="other" 
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="gender"/>
   <PlainSchema id="gender" type="Enum" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                enumerationValues="M;F"/>
+  <SyncopeSchema id="aLong"/>
   <PlainSchema id="aLong" type="Long" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="makeItDouble"/>
   <PlainSchema id="makeItDouble" type="Long" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="obscure"/>
   <PlainSchema id="obscure" type="Encrypted" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                secretKey="7abcdefghilmnopqrstuvz9#" cipherAlgorithm="SHA"/>
+  <SyncopeSchema id="photo"/>
   <PlainSchema id="photo" type="Binary" anyTypeClass_id="other"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                mimeType="image/jpeg"/>
 
+  <SyncopeSchema id="csvuserid"/>
   <DerSchema id="csvuserid" expression="firstname + ',' + surname" anyTypeClass_id="csv"/>
+  <SyncopeSchema id="cn"/>
   <DerSchema id="cn" expression="surname + ', ' + firstname" anyTypeClass_id="minimal user"/>
+  <SyncopeSchema id="noschema"/>
   <DerSchema id="noschema" expression="surname + ', ' + notfound" anyTypeClass_id="other"/>
+  <SyncopeSchema id="info"/>
   <DerSchema id="info" expression="username + ' - ' + creationDate + '[' + failedLogins + ']'" anyTypeClass_id="minimal user"/>
 
+  <SyncopeSchema id="icon"/>
   <PlainSchema id="icon" type="String" anyTypeClass_id="minimal group"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>                
+  <SyncopeSchema id="show"/>
   <PlainSchema id="show" type="Boolean" anyTypeClass_id="minimal group"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="rderived_sx"/>
   <PlainSchema id="rderived_sx" type="String" anyTypeClass_id="minimal group"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="rderived_dx"/>
   <PlainSchema id="rderived_dx" type="String" anyTypeClass_id="minimal group"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>           
+  <SyncopeSchema id="title"/>
   <PlainSchema id="title" type="String" anyTypeClass_id="minimal group"
                mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
 
+  <SyncopeSchema id="rderiveddata"/>
   <DerSchema id="rderiveddata" expression="rderived_sx + '-' + rderived_dx"
              anyTypeClass_id="minimal group"/>
+  <SyncopeSchema id="displayProperty"/>
   <DerSchema id="displayProperty" expression="icon + ': ' + show"
              anyTypeClass_id="minimal group"/>
+  <SyncopeSchema id="rderToBePropagated"/>
   <DerSchema id="rderToBePropagated" expression="rderived_sx + '-' + rderived_dx"
              anyTypeClass_id="minimal group"/>
 
+  <SyncopeSchema id="rderivedschema"/>
   <DerSchema id="rderivedschema" expression="rderived_sx + '-' + rderived_dx"  anyTypeClass_id="minimal group"/>
 
+  <SyncopeSchema id="subscriptionDate"/>
   <PlainSchema id="subscriptionDate" type="Date" anyTypeClass_id="generic membership"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
                conversionPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ"/>
+  <SyncopeSchema id="mderived_sx"/>
   <PlainSchema id="mderived_sx" type="String" anyTypeClass_id="generic membership"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="mderived_dx"/>
   <PlainSchema id="mderived_dx" type="String" anyTypeClass_id="generic membership"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>          
+  <SyncopeSchema id="postalAddress"/>
   <PlainSchema id="postalAddress" type="String" anyTypeClass_id="generic membership"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
 
+  <SyncopeSchema id="mderiveddata"/>
   <DerSchema id="mderiveddata" expression="mderived_sx + '-' + mderived_dx"/>
+  <SyncopeSchema id="mderToBePropagated"/>
   <DerSchema id="mderToBePropagated" expression="mderived_sx + '-' + mderived_dx" 
              anyTypeClass_id="generic membership"/>
         
+  <SyncopeSchema id="model"/>
   <PlainSchema id="model" type="String" anyTypeClass_id="minimal printer"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="location"/>
   <PlainSchema id="location" type="String" anyTypeClass_id="minimal printer"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
     
@@ -708,116 +756,116 @@ under the License.
   <Provision id="209ea85f-f964-49c7-a498-6c9c2baa3bd8" resource_id="ws-target-resource-1" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc" provision_id="209ea85f-f964-49c7-a498-6c9c2baa3bd8"/>
   <MappingItem id="96aad4e0-2678-4903-a52f-0a7d090a2863" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc" extAttrName="userId"
-               intMappingType="Username" mandatoryCondition="true"
+               intAttrName="username" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
   <MappingItem id="7f55b09c-b573-41dc-a9eb-ccd80bd3ea7a" extAttrName="email" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
-               intAttrName="email" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="email" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="a9749641-0556-49e2-a519-9bec35a4e06e" extAttrName="surname" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
-               intAttrName="surname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="surname" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="d118671c-2e3e-4aa3-a3dd-fde2ba4c4ded" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
-               extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
                connObjectKey="0" password="1" purpose="PROPAGATION"/>
   <MappingItem id="dca9de4f-9a5a-4280-8e9a-357e321ba7a5" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc" 
-               extAttrName="fullname" intAttrName="surname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               extAttrName="fullname" intAttrName="surname" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="471f0e2e-2bde-4442-9abf-0effb533f2ee" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
-               extAttrName="type" intAttrName="ctype" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               extAttrName="type" intAttrName="ctype" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="72324cda-a66c-4ffe-b6b6-1d9b6cee9bf2" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
-               extAttrName="name" intAttrName="firstname" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               extAttrName="name" intAttrName="firstname" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="NONE"/>
   
   <Provision id="41a53a00-0b35-4047-831a-d5238f74c7ba" resource_id="ws-target-resource-list-mappings-1" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="bf8afa4a-1522-44b9-91d0-c7b035e4fd99" provision_id="41a53a00-0b35-4047-831a-d5238f74c7ba"/>
   <MappingItem id="6f8d7b42-44f4-4697-aff5-1736c4b01ee4" mapping_id="bf8afa4a-1522-44b9-91d0-c7b035e4fd99"
-               extAttrName="email" intAttrName="email" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               extAttrName="email" intAttrName="email" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
   <MappingItem id="8515e385-3bf1-4928-adc9-489dee65829a" extAttrName="surname"
                mapping_id="bf8afa4a-1522-44b9-91d0-c7b035e4fd99"
-               intAttrName="surname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="surname" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
 
   <Provision id="09a65250-d9de-44b1-9412-11ed996d356d" resource_id="ws-target-resource-list-mappings-2" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="b12c4fad-f0f1-406d-b143-f2d68ed28e3a" provision_id="09a65250-d9de-44b1-9412-11ed996d356d"/>
   <MappingItem id="55a4cf7f-ac96-4e8b-931c-2d0eab6a6bca" mapping_id="b12c4fad-f0f1-406d-b143-f2d68ed28e3a"
-               extAttrName="userId" intAttrName="userId" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               extAttrName="userId" intAttrName="userId" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
 
   <Provision id="3d75991b-caee-4993-8e46-afb13d1bfbd4" resource_id="ws-target-resource-2" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="240a0291-f89d-4557-a547-2a3b9aad625b" provision_id="3d75991b-caee-4993-8e46-afb13d1bfbd4"/>
   <MappingItem id="d5c4d467-cd18-4148-8195-015808b4b3e6" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
-               extAttrName="fullname" intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               extAttrName="fullname" intAttrName="fullname" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="BOTH"/>
   <MappingItem id="370a8673-f3f7-4328-a9ce-acd946f687c5" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
-               extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
                connObjectKey="0" password="1" purpose="BOTH"/>
   <MappingItem id="c8d1a47a-1846-47b8-9f68-30aa21e94dcc" extAttrName="type" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
-               intAttrName="ctype" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="ctype" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="f0a06b24-7d4d-480e-8188-e53045885569" extAttrName="surname" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
-               intAttrName="surname" intMappingType="UserPlainSchema" mandatoryCondition="type == 'F'"
+               intAttrName="surname" mandatoryCondition="type == 'F'"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="adc3c628-27b3-4740-be01-2f83c210ace9" extAttrName="name" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
-               intAttrName="virtualdata" intMappingType="UserVirtualSchema" mandatoryCondition="type == 'F'"
+               intAttrName="virtualdata" mandatoryCondition="type == 'F'"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="6972a78b-2570-45d9-bc0b-31d2f2f9c860" extAttrName="fullname" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
-               intAttrName="cn" intMappingType="UserDerivedSchema" mandatoryCondition="true"
+               intAttrName="cn" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
     
   <Provision id="9ebc3237-49fa-4dce-9a4c-3070e931812f" resource_id="ws-target-resource-update" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d" provision_id="9ebc3237-49fa-4dce-9a4c-3070e931812f"/>
   <MappingItem id="cc973ed6-d031-4790-adab-fc059ac0c818" extAttrName="email" mapping_id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d"
-               intAttrName="email" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               intAttrName="email" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="7a72c812-1897-4db0-bed4-4e7e8ea51afe" extAttrName="userId" mapping_id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d"
-               intAttrName="userId" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               intAttrName="userId" mandatoryCondition="false"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
   <MappingItem id="946a3c7f-6359-4ab7-8a5f-adb08bdb4b5b" extAttrName="test3" mapping_id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d"
-               intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               intAttrName="fullname" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
     
   <Provision id="8680bc79-dfa1-4719-9886-1d582bf1124f" resource_id="ws-target-resource-nopropagation" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="63ddd4c8-efed-4a22-a4b4-1f4e6f47c8d0" provision_id="8680bc79-dfa1-4719-9886-1d582bf1124f"/>
   <MappingItem id="ffcfbb5e-7bbd-489a-a69e-2dd84f00731a" mapping_id="63ddd4c8-efed-4a22-a4b4-1f4e6f47c8d0" extAttrName="fullname" 
-               intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="fullname" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
                      
   <Provision id="0bfa7c3e-2bb3-43d7-ac0e-d57cff7a18c8" resource_id="ws-target-resource-nopropagation2" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="3f636292-6edb-4d20-ab24-fe0c5fc3dec3" provision_id="0bfa7c3e-2bb3-43d7-ac0e-d57cff7a18c8"/>
   <MappingItem id="e34928b8-ca57-4b6c-81c1-70bc87ff3fdc" mapping_id="3f636292-6edb-4d20-ab24-fe0c5fc3dec3" extAttrName="fullname" 
-               intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="fullname" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
                      
   <Provision id="5bd76fec-f8d7-4ab9-acd7-89e099d534e8" resource_id="ws-target-resource-nopropagation3" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="c2a0cec1-32c4-4493-8f01-d1176e557fc1" provision_id="5bd76fec-f8d7-4ab9-acd7-89e099d534e8"/>
   <MappingItem id="f3ba0859-b0f0-44a5-abfd-4a1a5ca29fbf" mapping_id="c2a0cec1-32c4-4493-8f01-d1176e557fc1" extAttrName="fullname"
-               intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="fullname" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
                      
   <Provision id="18de6376-7051-4216-96f0-26629076abb9" resource_id="ws-target-resource-nopropagation4" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="906452d9-3eeb-4ef7-ac90-5ffc14513fbf" provision_id="18de6376-7051-4216-96f0-26629076abb9"/>
   <MappingItem id="118" mapping_id="906452d9-3eeb-4ef7-ac90-5ffc14513fbf"
-               extAttrName="fullname" intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               extAttrName="fullname" intAttrName="fullname" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
                        
   <Provision id="779fefb5-dd25-4078-915d-3c199ee32158" resource_id="resource-testdb" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="cb624b93-874b-40a0-8021-3b8116b781ab" provision_id="779fefb5-dd25-4078-915d-3c199ee32158"/>
   <MappingItem id="1e0d30cd-2569-4a80-b9dc-af1467bd1c0b" mapping_id="cb624b93-874b-40a0-8021-3b8116b781ab"
-               extAttrName="ID" intMappingType="Username" mandatoryCondition="true"
+               extAttrName="ID" intAttrName="username" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="BOTH"/>
   <MappingItem id="7fd1a178-77a1-4c4c-aca2-3c3f1834b77b" mapping_id="cb624b93-874b-40a0-8021-3b8116b781ab"
-               extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
                connObjectKey="0" password="1" purpose="BOTH"/>
                      
   <Provision id="0359084d-68fe-4bf8-b42b-2ebe4f578ae7" resource_id="resource-testdb2" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="935a0fc2-4a0b-4d82-9931-3c5ce44a33c1" provision_id="0359084d-68fe-4bf8-b42b-2ebe4f578ae7"/>
   <MappingItem id="6d90658a-f470-4450-912d-6fe7d3bcda46" mapping_id="935a0fc2-4a0b-4d82-9931-3c5ce44a33c1" extAttrName="ID" 
-               intMappingType="Username" mandatoryCondition="true"
+               intAttrName="username" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
   <MappingItem id="2fb9eb01-50df-456e-86c1-b55f68cde2da" mapping_id="935a0fc2-4a0b-4d82-9931-3c5ce44a33c1" extAttrName="__PASSWORD__" 
-               intMappingType="Password" mandatoryCondition="true"
+               intAttrName="password" mandatoryCondition="true"
                connObjectKey="0" password="1" purpose="PROPAGATION"/>
                          
   <Provision id="2adb6537-e207-4d9b-804f-90bf18cd6f48" resource_id="resource-csv" anyType_id="USER" objectClass="__ACCOUNT__"/>
@@ -826,44 +874,44 @@ under the License.
   <Provision_AnyTypeClass provision_id="2adb6537-e207-4d9b-804f-90bf18cd6f48" anyTypeClass_id="minimal group"/>
   <Mapping id="538c27dc-d260-4c53-9fc8-bf02ee226911" provision_id="2adb6537-e207-4d9b-804f-90bf18cd6f48"/>
   <MappingItem id="517dc983-99a2-43c9-b4b4-78fd838e5ad1" extAttrName="id" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intMappingType="Username" mandatoryCondition="true"
+               intAttrName="username" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="ba6fb125-466e-4109-8e5d-133936437674" extAttrName="id" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="fullname" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="c426b070-0290-42be-9ee1-4046c7649635" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               extAttrName="__PASSWORD__" intMappingType="Password" mandatoryCondition="true"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
                connObjectKey="0" password="1" purpose="BOTH"/>
   <MappingItem id="20dbe358-5b71-4edd-8670-2bbde982e5c4" extAttrName="name" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="firstname" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               intAttrName="firstname" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="4d70850e-9fc5-4e75-83ea-432fe090e1c0" extAttrName="surname" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="surname" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               intAttrName="surname" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="4b2f4292-d8ab-4948-a341-3f8c9e23e72d" extAttrName="email" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="userId" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="userId" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PULL"/>
   <MappingItem id="20d6c914-54e7-4968-b1fc-685ae9c2c4a4" extAttrName="email" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="email" intMappingType="UserPlainSchema" mandatoryCondition="true"
+               intAttrName="email" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="PULL"/>
   <MappingItem id="09237f39-0d45-4258-a7cc-2400f7536b72" extAttrName="__NAME__" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="csvuserid" intMappingType="UserDerivedSchema" mandatoryCondition="true"
+               intAttrName="csvuserid" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
   <MappingItem id="63151b89-2eb3-4980-a682-0215d54ab4a2" extAttrName="theirgroup" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="rderToBePropagated" intMappingType="GroupDerivedSchema" mandatoryCondition="false"
+               intAttrName="rderToBePropagated" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="b6079a7b-ac40-481d-81c9-2a292bab0092" extAttrName="membership" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="mderToBePropagated" intMappingType="AnyObjectDerivedSchema" mandatoryCondition="false"
+               intAttrName="mderToBePropagated" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
                          
   <Provision id="1b53c74e-6a63-49ef-b2f1-96eeb7f1bbb8" resource_id="ws-target-resource-update-resetsynctoken" anyType_id="USER" objectClass="__ACCOUNT__"
              serializedSyncToken='{"value":null}'/>
   <Mapping id="23e20ce6-1ff9-495e-aa59-a58e5127a008" provision_id="1b53c74e-6a63-49ef-b2f1-96eeb7f1bbb8"/>
   <MappingItem id="608f01c5-eb7c-462a-b4d6-b7c3c9632a50" mapping_id="23e20ce6-1ff9-495e-aa59-a58e5127a008"
-               extAttrName="userId" intAttrName="userId" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               extAttrName="userId" intAttrName="userId" mandatoryCondition="false"
                connObjectKey="1" password="0" purpose="BOTH"/>
   <MappingItem id="79ada054-5f8b-4e77-b405-bfec58b06e7b" mapping_id="23e20ce6-1ff9-495e-aa59-a58e5127a008"
-               extAttrName="__PASSWORD__" intAttrName="fullname" intMappingType="UserPlainSchema" mandatoryCondition="false"
+               extAttrName="__PASSWORD__" intAttrName="fullname" mandatoryCondition="false"
                connObjectKey="0" password="1" purpose="BOTH"/>
 
   <Provision id="8b938d63-aa92-448c-89a8-a685fc0a67c8" resource_id="resource-ldap" anyType_id="USER" objectClass="__ACCOUNT__"/>
@@ -872,36 +920,37 @@ under the License.
   <Mapping id="ae1c77c3-2f1d-4258-ad06-710bb09041a9" provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8"
            connObjectLink="&apos;uid=&apos; + username + &apos;,ou=people,o=isp&apos;"/>
   <MappingItem id="9ff7d686-452c-4cec-a475-c1137c5d88c7" connObjectKey="1" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="cn" intAttrName="Username" intMappingType="Username"
+               extAttrName="cn" intAttrName="Username" intAttrName="username"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="73d97083-cfda-44e6-be62-3f9ac558b5eb" connObjectKey="0" password="1" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="__PASSWORD__" intAttrName="Password" intMappingType="Password"
+               extAttrName="__PASSWORD__" intAttrName="Password" intAttrName="password"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="cf0a222c-36ea-41e6-987c-7908614ccd23" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="sn" intAttrName="surname" intMappingType="UserPlainSchema"
+               extAttrName="sn" intAttrName="surname"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="b3a12364-e471-4e37-83ad-476c33a43617" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="cn" intAttrName="fullname" intMappingType="UserPlainSchema"
+               extAttrName="cn" intAttrName="fullname"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="aad2b7d7-3201-4bba-b496-f6587b4b7518" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="mail" intAttrName="email" intMappingType="UserPlainSchema"
+               extAttrName="mail" intAttrName="email"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="81b83c98-127b-469b-a497-412ba50acbeb" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="title" intAttrName="title" intMappingType="GroupPlainSchema"
+               extAttrName="title" intAttrName="title"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="318e92a1-3acb-49c5-b2fd-dba819c40ef1" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="postalAddress" intAttrName="postalAddress" intMappingType="UserPlainSchema"
+               extAttrName="postalAddress" intAttrName="postalAddress"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="78fa504f-213c-41ac-a922-7c9f98e5ce11" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="mail" intAttrName="userId" intMappingType="UserPlainSchema"
+               extAttrName="mail" intAttrName="userId"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="af6085cb-d0e8-47c9-b5f9-4b7d491a9750" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="registeredAddress" intAttrName="obscure" intMappingType="UserPlainSchema"
+               extAttrName="registeredAddress" intAttrName="obscure"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="5bb62bd2-5007-4eb8-b4f9-9df8917dc767" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="jpegPhoto" intAttrName="photo" intMappingType="UserPlainSchema"
+               extAttrName="jpegPhoto" intAttrName="photo"
                mandatoryCondition="false" purpose="BOTH"/>
         
+  <SyncopeSchema id="virtualReadOnly"/>
   <VirSchema id="virtualReadOnly" READONLY="1" anyTypeClass_id="minimal user"
              provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8" extAttrName="givenname"/>
 
@@ -909,68 +958,70 @@ under the License.
   <Mapping id="128412c8-be4f-4d7b-8bed-5ab89134f718" provision_id="20a75199-3f2e-4b9a-9510-c68dd7fc7b3d"
            connObjectLink="&apos;cn=&apos; + name + &apos;,ou=groups,o=isp&apos;"/>
   <MappingItem id="1" connObjectKey="1" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
-               extAttrName="cn" intAttrName="groupName" intMappingType="GroupName"
+               extAttrName="cn" intAttrName="name"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="2" connObjectKey="0" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
-               extAttrName="owner" intAttrName="groupOwnerSchema" intMappingType="GroupOwnerSchema"
+               extAttrName="owner" intAttrName="owner"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="3" connObjectKey="0" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
-               extAttrName="description" intAttrName="title" intMappingType="GroupPlainSchema"
+               extAttrName="description" intAttrName="title"
                mandatoryCondition="false" purpose="BOTH"/>
   
+  <SyncopeSchema id="rvirtualdata"/>
   <VirSchema id="rvirtualdata" anyTypeClass_id="minimal group" provision_id="20a75199-3f2e-4b9a-9510-c68dd7fc7b3d" extAttrName="businessCategory"/>
 
   <Provision id="46b54e2a-e43e-4cd7-8c13-1af1bd65c3d3" resource_id="resource-db-pull" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="cda910bd-fc28-4f63-890e-66edc62d428b" provision_id="46b54e2a-e43e-4cd7-8c13-1af1bd65c3d3"/>
   <MappingItem id="1a345706-a498-41bb-a948-820307a4365e" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="EMAIL" intAttrName="email" intMappingType="UserPlainSchema" 
+               extAttrName="EMAIL" intAttrName="email" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="a234bde8-b431-408c-8ec9-c986c5b7f98d" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="SURNAME" intAttrName="fullname" intMappingType="UserPlainSchema" 
+               extAttrName="SURNAME" intAttrName="fullname" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="51a856de-ae25-41cd-967a-86920c834b70" connObjectKey="1" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="ID" intAttrName="firstname" intMappingType="UserPlainSchema" 
+               extAttrName="ID" intAttrName="firstname" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="f4e5178e-ef37-4949-933a-7ec7eaea64c6" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="SURNAME" intAttrName="surname" intMappingType="UserPlainSchema" 
+               extAttrName="SURNAME" intAttrName="surname" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="3ac0ecaf-d9a1-4fc1-9ae9-84dc34576810" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="USERNAME" intAttrName="Username" intMappingType="Username" 
+               extAttrName="USERNAME" intAttrName="Username" intAttrName="username" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="e7215305-93c9-460b-b862-46f7b60de72d" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="EMAIL" intAttrName="userId" intMappingType="UserPlainSchema" 
+               extAttrName="EMAIL" intAttrName="userId" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
               
   <Provision id="6d7cb60a-c4ad-4a70-94ae-e5b88eb24930" resource_id="resource-db-virattr" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="45280585-308f-4571-9788-c7a4734b3614" provision_id="6d7cb60a-c4ad-4a70-94ae-e5b88eb24930"/>
   <MappingItem id="6cb2f9f0-5fb4-4686-a375-31e2c34a6cd8" mapping_id="45280585-308f-4571-9788-c7a4734b3614" connObjectKey="1" password="0"
-               extAttrName="ID" intMappingType="UserKey" 
+               extAttrName="ID" intAttrName="key" 
                mandatoryCondition="true" purpose="BOTH"/>
                 
+  <SyncopeSchema id="virtualdata"/>
   <VirSchema id="virtualdata" anyTypeClass_id="minimal user" provision_id="6d7cb60a-c4ad-4a70-94ae-e5b88eb24930" extAttrName="USERNAME"/>
   
   <Provision id="cfa86cbe-94b6-4712-a40a-a4861be1d425" resource_id="ws-target-resource-timeout" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="c71d690a-3dd9-48a5-b76f-32805186c4dc" provision_id="cfa86cbe-94b6-4712-a40a-a4861be1d425"/>
   <MappingItem id="321bc904-e1fc-4a54-bf7c-74c8cbcc0815" mapping_id="c71d690a-3dd9-48a5-b76f-32805186c4dc" connObjectKey="1" password="0"
-               extAttrName="fullname" intAttrName="fullname" intMappingType="UserPlainSchema"
+               extAttrName="fullname" intAttrName="fullname"
                mandatoryCondition="true" purpose="PROPAGATION"/>
   
   <Provision id="ac1659dc-3ea3-45eb-8ae6-626e3d916492" resource_id="ws-target-resource-delete" anyType_id="USER" objectClass="__ACCOUNT__"/>
   <Mapping id="72f590ae-2754-456b-aabb-eda7d8459dd3" provision_id="ac1659dc-3ea3-45eb-8ae6-626e3d916492"/>
   <MappingItem id="4c98536f-10df-4953-b2df-59d7cd057fd2" mapping_id="72f590ae-2754-456b-aabb-eda7d8459dd3" extAttrName="userId" 
-               intMappingType="Username" mandatoryCondition="true"
+               intAttrName="username" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
 
   <Provision id="f1b55b66-eb13-4a93-a49c-448e93756eb6" resource_id="resource-db-scripted" anyType_id="PRINTER" objectClass="__PRINTER__"/>
   <Mapping id="16439b5f-50c3-4604-97e9-f4004933abd8" provision_id="f1b55b66-eb13-4a93-a49c-448e93756eb6"/>
   <MappingItem id="23aa0299-ddbb-4e59-8918-0ab2a32465fa" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="ID" 
-               intMappingType="AnyObjectKey" mandatoryCondition="true"
+               intAttrName="key" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="BOTH"/>
   <MappingItem id="3dc96af0-5d0a-4ec1-be84-244716d88401" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="PRINTERNAME" 
-               intMappingType="AnyObjectName" mandatoryCondition="true"
+               intAttrName="name" mandatoryCondition="true"
                connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="f3ef9f8b-e667-4b18-969f-ba98c3d78bc0" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="LOCATION" 
-               intAttrName="location" intMappingType="AnyObjectPlainSchema"
+               intAttrName="location"
                mandatoryCondition="false" connObjectKey="0" password="0" purpose="BOTH"/>
     
   <Task DTYPE="PropagationTask" id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" operation="UPDATE"
@@ -1171,7 +1222,7 @@ $$ }&#10;"
 &lt;p&gt;
     This message was sent to the following recipients:
 &lt;ul&gt;&#10;
-$$ for (recipient: recipients) {&#10;
+$$ for (recipient: recipients) {&#10;Na
   &lt;li&gt;${recipient.plainAttrMap[&quot;email&quot;].values[0]}&lt;/li&gt;&#10;
 $$ }&#10;
 &lt;/ul&gt;&#10;
@@ -1195,7 +1246,7 @@ $$ }&#10;
 &lt;/body&gt;
 &lt;/html&gt;"/>
 
-  <Notification id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" 
+  <Notification id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" active="1" recipientAttrName="email" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset request" template_id="requestPasswordReset" 
                 traceLevel="FAILURES"/> 
   <AnyAbout id="a328f2e6-25e9-4cc1-badf-7425d7be4b39" anyType_id="USER" notification_id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" filter="token!=$null"/>
@@ -1205,7 +1256,7 @@ $$ }&#10;
         textBody="NOTIFICATION-81" htmlBody="NOTIFICATION-81" traceLevel="ALL"/>
   <NotificationTask_recipients notificationTask_id="e1e520f0-2cbd-4e11-9a89-ea58a0f957e7" address="recipient@prova.org"/>  
   
-  <Notification id="bef0c250-e8a7-4848-bb63-2564fc409ce2" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" 
+  <Notification id="bef0c250-e8a7-4848-bb63-2564fc409ce2" active="1" recipientAttrName="email" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset successful" template_id="confirmPasswordReset" 
                 traceLevel="FAILURES"/> 
   <Notification_events notification_id="bef0c250-e8a7-4848-bb63-2564fc409ce2" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>
@@ -1213,7 +1264,7 @@ $$ }&#10;
   <Notification id="9e2b911c-25de-4c77-bcea-b86ed9451050" sender="test@syncope.apache.org" subject="Test subject" template_id="test" selfAsRecipient="0" 
                 traceLevel="FAILURES"
                 recipientsFIQL="$groups==7"
-                recipientAttrType="UserPlainSchema" recipientAttrName="email" active="1"/>
+                recipientAttrName="email" active="1"/>
   <AnyAbout id="2e2ee845-2abf-43c6-b543-49243a84e2f1" anyType_id="USER" notification_id="9e2b911c-25de-4c77-bcea-b86ed9451050" filter="fullname==*o*;fullname==*i*"/>
   <Notification_events notification_id="9e2b911c-25de-4c77-bcea-b86ed9451050" event="[CUSTOM]:[]:[]:[unexisting1]:[FAILURE]"/>
   <Notification_events notification_id="9e2b911c-25de-4c77-bcea-b86ed9451050" event="[CUSTOM]:[]:[]:[unexisting2]:[SUCCESS]"/>


[04/15] syncope git commit: Fixing OpenJPA warnings about 'Supplied parameters do not match expected parameters'

Posted by il...@apache.org.
Fixing OpenJPA warnings about 'Supplied parameters do not match expected parameters'


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

Branch: refs/heads/SYNCOPE-862
Commit: 579f4b04660d03e58a2c8fc32f69174b211b63a4
Parents: acce340
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Wed Jun 1 18:52:42 2016 +0200
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Tue Jun 14 17:59:30 2016 +0200

----------------------------------------------------------------------
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    | 30 ++++++++--
 .../core/persistence/jpa/dao/JPAUserDAO.java    | 60 ++++++++++++++++----
 .../persistence/jpa/dao/JPAVirSchemaDAO.java    | 45 +++++++++++++--
 .../persistence/jpa/outer/ResourceTest.java     |  8 +--
 4 files changed, 115 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/579f4b04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 5280c3c..c527a15 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -56,6 +56,7 @@ import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADynGroupMembership;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAARelationship;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAURelationship;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
@@ -211,12 +212,29 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
     @Override
     public List<Group> findDynGroupMemberships(final AnyObject anyObject) {
-        TypedQuery<Group> query = entityManager().createQuery(
-                "SELECT e.group FROM " + JPAADynGroupMembership.class.getSimpleName()
-                + " e WHERE :anyObject MEMBER OF e.anyObjects", Group.class);
-        query.setParameter("anyObject", anyObject);
-
-        return query.getResultList();
+        Query query = entityManager().createNativeQuery(
+                "SELECT t2.id FROM " + JPAADynGroupMembership.TABLE + " t0 "
+                + "INNER JOIN ADynGroupMembership_AnyObject t1 "
+                + "ON t0.id = t1.aDynGroupMembership_id "
+                + "LEFT OUTER JOIN " + JPAGroup.TABLE + " t2 "
+                + "ON t0.GROUP_ID = t2.id "
+                + "WHERE t1.anyObject_id = ?1");
+        query.setParameter(1, anyObject.getKey());
+
+        List<Group> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            Group group = groupDAO.find(actualKey);
+            if (group == null) {
+                LOG.error("Could not find group with id {}, even though returned by the native query", actualKey);
+            } else if (!result.contains(group)) {
+                result.add(group);
+            }
+        }
+        return result;
     }
 
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)

http://git-wip-us.apache.org/repos/asf/syncope/blob/579f4b04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
index 0624190..0cd53a0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAUserDAO.java
@@ -66,6 +66,8 @@ import org.apache.syncope.core.persistence.api.entity.user.SecurityQuestion;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
+import org.apache.syncope.core.persistence.jpa.entity.JPARole;
+import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDynGroupMembership;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
@@ -418,23 +420,57 @@ public class JPAUserDAO extends AbstractAnyDAO<User> implements UserDAO {
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
     @Override
     public List<Role> findDynRoleMemberships(final User user) {
-        TypedQuery<Role> query = entityManager().createQuery(
-                "SELECT e.role FROM " + JPADynRoleMembership.class.getSimpleName()
-                + " e WHERE :user MEMBER OF e.users", Role.class);
-        query.setParameter("user", user);
-
-        return query.getResultList();
+        Query query = entityManager().createNativeQuery(
+                "SELECT t2.id FROM " + JPADynRoleMembership.TABLE + " t0 "
+                + "INNER JOIN " + JPADynRoleMembership.TABLE + "_User t1 "
+                + "ON t0.id = t1.dynRoleMembership_id "
+                + "LEFT OUTER JOIN " + JPARole.TABLE + " t2 "
+                + "ON t0.ROLE_ID = t2.id "
+                + "WHERE (t1.user_id = ?1)");
+        query.setParameter(1, user.getKey());
+
+        List<Role> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            Role role = roleDAO.find(actualKey);
+            if (role == null) {
+                LOG.error("Could not find role with id {}, even though returned by the native query", actualKey);
+            } else if (!result.contains(role)) {
+                result.add(role);
+            }
+        }
+        return result;
     }
 
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
     @Override
     public List<Group> findDynGroupMemberships(final User user) {
-        TypedQuery<Group> query = entityManager().createQuery(
-                "SELECT e.group FROM " + JPAUDynGroupMembership.class.getSimpleName()
-                + " e WHERE :user MEMBER OF e.users", Group.class);
-        query.setParameter("user", user);
-
-        return query.getResultList();
+        Query query = entityManager().createNativeQuery(
+                "SELECT t2.id FROM " + JPAUDynGroupMembership.TABLE + " t0 "
+                + "INNER JOIN " + JPAUDynGroupMembership.TABLE + "_User t1 "
+                + "ON t0.id = t1.uDynGroupMembership_id "
+                + "LEFT OUTER JOIN " + JPAGroup.TABLE + " t2 "
+                + "ON t0.GROUP_ID = t2.id "
+                + "WHERE (t1.user_id = ?1)");
+        query.setParameter(1, user.getKey());
+
+        List<Group> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            Group group = groupDAO.find(actualKey);
+            if (group == null) {
+                LOG.error("Could not find group with id {}, even though returned by the native query", actualKey);
+            } else if (!result.contains(group)) {
+                result.add(group);
+            }
+        }
+        return result;
     }
 
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)

http://git-wip-us.apache.org/repos/asf/syncope/blob/579f4b04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
index 9a42b17..61db7b3 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -18,8 +18,10 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import javax.persistence.Query;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
@@ -29,8 +31,17 @@ 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.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyType;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyTypeClass;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
+import org.apache.syncope.core.persistence.jpa.entity.JPAConnInstance;
 import org.apache.syncope.core.persistence.jpa.entity.JPAVirSchema;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPullPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAMapping;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAProvision;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
@@ -62,12 +73,34 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema> implements VirSchema
 
     @Override
     public List<VirSchema> findByProvision(final Provision provision) {
-        TypedQuery<VirSchema> query = entityManager().createQuery(
-                "SELECT e FROM " + JPAVirSchema.class.getSimpleName()
-                + " e WHERE e.provision=:provision", VirSchema.class);
-        query.setParameter("provision", provision);
-
-        return query.getResultList();
+        Query query = entityManager().createNativeQuery(
+                "SELECT t0.id FROM VirSchema t0 "
+                + "LEFT OUTER JOIN " + JPAAnyTypeClass.TABLE + " t1 ON t0.ANYTYPECLASS_ID = t1.id "
+                + "LEFT OUTER JOIN " + JPAProvision.TABLE + " t2 ON t0.PROVISION_ID = t2.id "
+                + "LEFT OUTER JOIN " + JPAAnyType.TABLE + " t3 ON t2.ANYTYPE_ID = t3.id "
+                + "LEFT OUTER JOIN " + JPAMapping.TABLE + " t4 ON t2.id = t4.PROVISION_ID "
+                + "LEFT OUTER JOIN " + JPAExternalResource.TABLE + " t5 ON t2.RESOURCE_ID = t5.id "
+                + "LEFT OUTER JOIN " + JPAAccountPolicy.TABLE + " t6 ON t5.ACCOUNTPOLICY_ID = t6.id "
+                + "LEFT OUTER JOIN " + JPAConnInstance.TABLE + " t7 ON t5.CONNECTOR_ID = t7.id "
+                + "LEFT OUTER JOIN " + JPAPasswordPolicy.TABLE + " t8 ON t5.PASSWORDPOLICY_ID = t8.id "
+                + "LEFT OUTER JOIN " + JPAPullPolicy.TABLE + " t9 ON t5.PULLPOLICY_ID = t9.id "
+                + "WHERE t0.PROVISION_ID = ?1");
+        query.setParameter(1, provision.getKey());
+
+        List<VirSchema> result = new ArrayList<>();
+        for (Object key : query.getResultList()) {
+            String actualKey = key instanceof Object[]
+                    ? (String) ((Object[]) key)[0]
+                    : ((String) key);
+
+            VirSchema virSchema = find(actualKey);
+            if (virSchema == null) {
+                LOG.error("Could not find schema with id {}, even though returned by the native query", actualKey);
+            } else if (!result.contains(virSchema)) {
+                result.add(virSchema);
+            }
+        }
+        return result;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/579f4b04/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
index d536d66..a8540bd 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
@@ -266,6 +266,9 @@ public class ResourceTest extends AbstractTest {
         assertNotNull(ldap.getProvision(anyTypeDAO.findUser()).getMapping());
         assertNotNull(ldap.getProvision(anyTypeDAO.findGroup()).getMapping());
 
+        // need to avoid any class not defined in this Maven module
+        ldap.getPropagationActionsClassNames().clear();
+
         List<? extends MappingItem> items = ldap.getProvision(anyTypeDAO.findGroup()).getMapping().getItems();
         assertNotNull(items);
         assertFalse(items.isEmpty());
@@ -275,13 +278,10 @@ public class ResourceTest extends AbstractTest {
         }
 
         Provision groupProvision = ldap.getProvision(anyTypeDAO.findGroup());
-        ldap.getProvisions().remove(groupProvision);
         for (VirSchema schema : virSchemaDAO.findByProvision(groupProvision)) {
             virSchemaDAO.delete(schema.getKey());
         }
-
-        // need to avoid any class not defined in this Maven module
-        ldap.getPropagationActionsClassNames().clear();
+        ldap.getProvisions().remove(groupProvision);
 
         resourceDAO.save(ldap);
         resourceDAO.flush();


[05/15] syncope git commit: Unique schema key across the three tables

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
index 70d55ba..012acb9 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationITCase.java
@@ -30,7 +30,6 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.common.rest.api.service.NotificationService;
 import org.apache.syncope.fit.AbstractITCase;
@@ -51,7 +50,6 @@ public class NotificationITCase extends AbstractITCase {
                 is("fullname").equalTo("*o*").and("fullname").equalTo("*i*").query());
 
         notificationTO.setRecipientAttrName("email");
-        notificationTO.setRecipientAttrType(IntMappingType.UserPlainSchema);
 
         notificationTO.setSender("syncope@syncope.apache.org");
         notificationTO.setSubject("Test notification");

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
index 5493282..665d38b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
@@ -46,7 +46,6 @@ import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
@@ -322,7 +321,6 @@ public class NotificationTaskITCase extends AbstractTaskITCase {
                 inGroups("f779c0d4-633b-4be5-8f57-32eb478a3ca5").query());
         notification.setSelfAsRecipient(false);
         notification.setRecipientAttrName("email");
-        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
         notification.getStaticRecipients().add(MAIL_ADDRESS);
         notification.setRecipientsProviderClassName(TestNotificationRecipientsProvider.class.getName());
 
@@ -395,7 +393,6 @@ public class NotificationTaskITCase extends AbstractTaskITCase {
                 inGroups("f779c0d4-633b-4be5-8f57-32eb478a3ca5").query());
         notification.setSelfAsRecipient(true);
         notification.setRecipientAttrName("email");
-        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
         if (staticRecipients != null) {
             CollectionUtils.addAll(notification.getStaticRecipients(), staticRecipients);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
index 3f9ac6d..36fe888 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
@@ -88,7 +88,7 @@ public class PlainSchemaITCase extends AbstractITCase {
             boolean entityViolationTypeCheck = false;
             for (String element : e.getElements()) {
                 if (!entityViolationTypeCheck) {
-                    entityViolationTypeCheck = element.contains(EntityViolationType.InvalidName.name());
+                    entityViolationTypeCheck = element.contains(EntityViolationType.InvalidKey.name());
                 }
             }
             assertTrue(entityViolationTypeCheck);
@@ -334,7 +334,7 @@ public class PlainSchemaITCase extends AbstractITCase {
             fail();
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
-            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/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 ed9b603..243aff7 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
@@ -44,7 +44,6 @@ 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.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
@@ -317,7 +316,6 @@ public class PushTaskITCase extends AbstractTaskITCase {
             provisionTO.setMapping(mapping);
 
             MappingItemTO item = new MappingItemTO();
-            item.setIntMappingType(IntMappingType.GroupPlainSchema);
             item.setExtAttrName("cn");
             item.setIntAttrName(schemaTO.getKey());
             item.setConnObjectKey(true);
@@ -387,7 +385,6 @@ public class PushTaskITCase extends AbstractTaskITCase {
         notification.getStaticRecipients().add("issueyncope648@syncope.apache.org");
         notification.setSelfAsRecipient(false);
         notification.setRecipientAttrName("email");
-        notification.setRecipientAttrType(IntMappingType.UserPlainSchema);
 
         notification.setSender("syncope648@syncope.apache.org");
         String subject = "Test notification";

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
index ffd2a4f..f509611 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
@@ -50,7 +50,6 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConnConfPropSchema;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.rest.api.beans.ConnObjectTOListQuery;
 import org.apache.syncope.common.rest.api.service.ResourceService;
@@ -80,21 +79,18 @@ public class ResourceITCase extends AbstractITCase {
         MappingItemTO item = new MappingItemTO();
         item.setExtAttrName("userId");
         item.setIntAttrName("userId");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.add(item);
 
         item = new MappingItemTO();
         item.setExtAttrName("username");
-        item.setIntAttrName("fullname");
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
 
         item = new MappingItemTO();
         item.setExtAttrName("fullname");
         item.setIntAttrName("cn");
-        item.setIntMappingType(IntMappingType.UserDerivedSchema);
         item.setConnObjectKey(false);
         item.setPurpose(MappingPurpose.PROPAGATION);
         mapping.add(item);
@@ -139,14 +135,12 @@ public class ResourceITCase extends AbstractITCase {
         MappingItemTO item = new MappingItemTO();
         item.setExtAttrName("uid");
         item.setIntAttrName("userId");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.add(item);
 
         item = new MappingItemTO();
         item.setExtAttrName("username");
-        item.setIntAttrName("fullname");
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setConnObjectKey(true);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
@@ -154,7 +148,6 @@ public class ResourceITCase extends AbstractITCase {
         item = new MappingItemTO();
         item.setExtAttrName("fullname");
         item.setIntAttrName("cn");
-        item.setIntMappingType(IntMappingType.UserDerivedSchema);
         item.setConnObjectKey(false);
         item.setPurpose(MappingPurpose.PROPAGATION);
         mapping.add(item);
@@ -198,7 +191,7 @@ public class ResourceITCase extends AbstractITCase {
         provisionTO.setMapping(mapping);
 
         MappingItemTO item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setExtAttrName("userId");
         item.setConnObjectKey(true);
         item.setPurpose(MappingPurpose.PROPAGATION);
@@ -212,7 +205,7 @@ public class ResourceITCase extends AbstractITCase {
         mapping = new MappingTO();
         provisionTO.setMapping(mapping);
         item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.GroupKey);
+        item.setIntAttrName("key");
         item.setExtAttrName("groupId");
         item.setConnObjectKey(true);
         item.setPurpose(MappingPurpose.PULL);
@@ -248,13 +241,12 @@ public class ResourceITCase extends AbstractITCase {
         provisionTO.setMapping(mapping);
 
         MappingItemTO item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setExtAttrName("userId");
         item.setConnObjectKey(true);
         mapping.setConnObjectKeyItem(item);
 
         item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setExtAttrName("email");
         // missing intAttrName ...
         mapping.add(item);
@@ -286,13 +278,12 @@ public class ResourceITCase extends AbstractITCase {
         provisionTO.setMapping(mapping);
 
         MappingItemTO item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setExtAttrName("userId");
         item.setConnObjectKey(true);
         mapping.setConnObjectKeyItem(item);
 
         item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setIntAttrName("usernane");
         // missing extAttrName ...
         mapping.add(item);
@@ -319,7 +310,6 @@ public class ResourceITCase extends AbstractITCase {
         MappingItemTO item = new MappingItemTO();
         item.setExtAttrName("userId");
         item.setIntAttrName("userId");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setConnObjectKey(true);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
@@ -368,7 +358,6 @@ public class ResourceITCase extends AbstractITCase {
         item.setKey("cc973ed6-d031-4790-adab-fc059ac0c818");
         item.setExtAttrName("test3");
         item.setIntAttrName("fullname");
-        item.setIntMappingType(IntMappingType.UserPlainSchema);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.add(item);
 
@@ -377,14 +366,12 @@ public class ResourceITCase extends AbstractITCase {
             item = new MappingItemTO();
             item.setExtAttrName("test" + i);
             item.setIntAttrName("fullname");
-            item.setIntMappingType(IntMappingType.UserPlainSchema);
             item.setPurpose(MappingPurpose.BOTH);
             mapping.add(item);
         }
         item = new MappingItemTO();
         item.setExtAttrName("username");
-        item.setIntAttrName("fullname");
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setConnObjectKey(true);
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
@@ -642,13 +629,13 @@ public class ResourceITCase extends AbstractITCase {
         provisionTO.setMapping(mapping);
 
         MappingItemTO item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.GroupName);
+        item.setIntAttrName("name");
         item.setExtAttrName("cn");
         item.setPurpose(MappingPurpose.BOTH);
         mapping.setConnObjectKeyItem(item);
 
         item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.GroupOwnerSchema);
+        item.setIntAttrName("owner");
         item.setExtAttrName("owner");
         item.setPurpose(MappingPurpose.BOTH);
         mapping.add(item);
@@ -666,7 +653,7 @@ public class ResourceITCase extends AbstractITCase {
             fail();
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidExternalResource, e.getType());
-            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
         }
     }
 
@@ -687,14 +674,13 @@ public class ResourceITCase extends AbstractITCase {
         provisionTO.setMapping(mapping);
 
         MappingItemTO item = new MappingItemTO();
-        item.setIntMappingType(IntMappingType.UserKey);
+        item.setIntAttrName("key");
         item.setExtAttrName("userId");
         item.setConnObjectKey(true);
         item.setPurpose(MappingPurpose.PROPAGATION);
         mapping.setConnObjectKeyItem(item);
 
         MappingItemTO item2 = new MappingItemTO();
-        item2.setIntMappingType(IntMappingType.UserPlainSchema);
         item2.setConnObjectKey(false);
         item2.setIntAttrName("gender");
         item2.setExtAttrName("gender");

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
index 413d80d..37fc276 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirAttrITCase.java
@@ -50,7 +50,6 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
@@ -506,7 +505,6 @@ public class VirAttrITCase extends AbstractITCase {
 
             MappingItemTO item = new MappingItemTO();
             item.setIntAttrName("fullname");
-            item.setIntMappingType(IntMappingType.UserPlainSchema);
             item.setExtAttrName("ID");
             item.setPurpose(MappingPurpose.PROPAGATION);
             item.setConnObjectKey(true);
@@ -515,14 +513,12 @@ public class VirAttrITCase extends AbstractITCase {
             item = new MappingItemTO();
             item.setExtAttrName("USERNAME");
             item.setIntAttrName("username");
-            item.setIntMappingType(IntMappingType.Username);
             item.setPurpose(MappingPurpose.PROPAGATION);
             mapping.getItems().add(item);
 
             item = new MappingItemTO();
             item.setExtAttrName("EMAIL");
             item.setIntAttrName("rvirtualdata");
-            item.setIntMappingType(IntMappingType.GroupVirtualSchema);
             item.setPurpose(MappingPurpose.PROPAGATION);
             mapping.getItems().add(item);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a4afd4a2/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
index fbe264e..b7ab0ce 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
@@ -148,7 +148,7 @@ public class VirSchemaITCase extends AbstractITCase {
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidVirSchema, e.getType());
 
-            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
         }
     }
 }


[14/15] syncope git commit: [SYNCOPE-862] Preliminary work

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
index 60be1fe..5280c3c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnyObjectDAO.java
@@ -27,6 +27,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.persistence.NoResultException;
 import javax.persistence.Query;
 import javax.persistence.TypedQuery;
 import org.apache.commons.collections4.CollectionUtils;
@@ -40,6 +41,7 @@ import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
@@ -124,6 +126,38 @@ public class JPAAnyObjectDAO extends AbstractAnyDAO<AnyObject> implements AnyObj
     }
 
     @Override
+    public AnyObject findByName(final String name) {
+        TypedQuery<AnyObject> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAAnyObject.class.getSimpleName() + " e WHERE e.name = :name", AnyObject.class);
+        query.setParameter("name", name);
+
+        AnyObject result = null;
+        try {
+            result = query.getSingleResult();
+        } catch (NoResultException e) {
+            LOG.debug("No any object found with name {}", name, e);
+        }
+
+        return result;
+    }
+
+    @Override
+    public AnyObject authFindByName(final String name) {
+        if (name == null) {
+            throw new NotFoundException("Null name");
+        }
+
+        AnyObject anyObject = findByName(name);
+        if (anyObject == null) {
+            throw new NotFoundException("Any Object " + name);
+        }
+
+        securityChecks(anyObject);
+
+        return anyObject;
+    }
+
+    @Override
     public List<ARelationship> findARelationships(final AnyObject anyObject) {
         TypedQuery<ARelationship> query = entityManager().createQuery(
                 "SELECT e FROM " + JPAARelationship.class.getSimpleName()

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
index 07e18e2..d1df518 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAConfDAO.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.dao;
 
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
-import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
@@ -40,9 +39,6 @@ public class JPAConfDAO extends AbstractDAO<Conf> implements ConfDAO {
     @Autowired
     private PlainSchemaDAO schemaDAO;
 
-    @Autowired
-    private PlainAttrDAO attrDAO;
-
     @Override
     public Conf get() {
         Conf instance = entityManager().find(JPAConf.class, KEY);
@@ -96,8 +92,8 @@ public class JPAConfDAO extends AbstractDAO<Conf> implements ConfDAO {
         if (old != null && (!attr.getSchema().isUniqueConstraint()
                 || (!attr.getUniqueValue().getStringValue().equals(old.getUniqueValue().getStringValue())))) {
 
-            instance.getPlainAttrs().remove(old);
-            attrDAO.delete(old.getKey(), CPlainAttr.class);
+            old.setOwner(null);
+            instance.remove(old);
         }
 
         instance.add(attr);
@@ -111,8 +107,8 @@ public class JPAConfDAO extends AbstractDAO<Conf> implements ConfDAO {
         Conf instance = get();
         CPlainAttr attr = instance.getPlainAttr(key);
         if (attr != null) {
-            instance.getPlainAttrs().remove(attr);
-            attrDAO.delete(attr.getKey(), CPlainAttr.class);
+            attr.setOwner(null);
+            instance.remove(attr);
 
             instance = entityManager().merge(instance);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
index 38d4add..af5220f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAGroupDAO.java
@@ -44,6 +44,7 @@ import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
 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.Any;
@@ -52,9 +53,11 @@ import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembership;
 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.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
 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.jpa.entity.JPAAnyUtilsFactory;
 import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAMembership;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPATypeExtension;
@@ -72,6 +75,9 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     @Autowired
     private UserDAO userDAO;
 
+    @Autowired
+    private PlainAttrDAO plainAttrDAO;
+
     @Override
     protected AnyUtils init() {
         return new JPAAnyUtilsFactory().getInstance(AnyTypeKind.GROUP);
@@ -242,16 +248,30 @@ public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
     @Override
     public void delete(final Group group) {
         for (AMembership membership : findAMemberships(group)) {
-            membership.getLeftEnd().getMemberships().remove(membership);
-            anyObjectDAO.save(membership.getLeftEnd());
+            AnyObject leftEnd = membership.getLeftEnd();
+            leftEnd.getMemberships().remove(membership);
+            membership.setRightEnd(null);
+            for (APlainAttr attr : leftEnd.getPlainAttrs(membership)) {
+                leftEnd.remove(attr);
+                attr.setOwner(null);
+                attr.setMembership(null);
+                plainAttrDAO.delete(attr);
+            }
 
-            entityManager().remove(membership);
+            anyObjectDAO.save(leftEnd);
         }
         for (UMembership membership : findUMemberships(group)) {
-            membership.getLeftEnd().getMemberships().remove(membership);
-            userDAO.save(membership.getLeftEnd());
+            User leftEnd = membership.getLeftEnd();
+            leftEnd.getMemberships().remove(membership);
+            membership.setRightEnd(null);
+            for (UPlainAttr attr : leftEnd.getPlainAttrs(membership)) {
+                leftEnd.remove(attr);
+                attr.setOwner(null);
+                attr.setMembership(null);
+                plainAttrDAO.delete(attr);
+            }
 
-            entityManager().remove(membership);
+            userDAO.save(leftEnd);
         }
 
         entityManager().remove(group);

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
index 496e689..cf3ede1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAny.java
@@ -25,14 +25,11 @@ import javax.persistence.FetchType;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.IterableUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.core.provisioning.api.utils.EntityUtils;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
 import org.apache.syncope.core.persistence.jpa.validation.entity.AnyCheck;
 
 @AnyCheck
@@ -81,33 +78,8 @@ public abstract class AbstractAny<P extends PlainAttr<?>> extends AbstractAnnota
     }
 
     @Override
-    public P getPlainAttr(final String plainSchemaName) {
-        return IterableUtils.find(getPlainAttrs(), new Predicate<P>() {
-
-            @Override
-            public boolean evaluate(final P plainAttr) {
-                return plainAttr != null && plainAttr.getSchema() != null
-                        && plainSchemaName.equals(plainAttr.getSchema().getKey());
-            }
-        });
-    }
-
-    protected abstract List<JPAExternalResource> internalGetResources();
-
-    @Override
-    public boolean add(final ExternalResource resource) {
-        checkType(resource, JPAExternalResource.class);
-        return internalGetResources().add((JPAExternalResource) resource);
-    }
-
-    @Override
     public List<String> getResourceNames() {
         return CollectionUtils.collect(
                 getResources(), EntityUtils.<ExternalResource>keyTransformer(), new ArrayList<String>());
     }
-
-    @Override
-    public List<? extends ExternalResource> getResources() {
-        return internalGetResources();
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractGroupableRelatable.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractGroupableRelatable.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractGroupableRelatable.java
new file mode 100644
index 0000000..a2a41fa
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractGroupableRelatable.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
+import org.apache.syncope.core.persistence.api.entity.Membership;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
+import org.apache.syncope.core.persistence.api.entity.Relationship;
+import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+
+public abstract class AbstractGroupableRelatable<
+        L extends Any<P>, 
+        M extends Membership<L>, 
+        P extends GroupablePlainAttr<L, M>,
+        R extends Any<?>,
+        REL extends Relationship<L, R>>
+        extends AbstractAny<P> implements GroupableRelatable<L, M, P, R, REL> {
+
+    private static final long serialVersionUID = -2269285197388729673L;
+
+    protected abstract List<? extends P> internalGetPlainAttrs();
+
+    @Override
+    public boolean remove(final P attr) {
+        return internalGetPlainAttrs().remove(attr);
+    }
+
+    @Override
+    public P getPlainAttr(final String plainSchemaName) {
+        return IterableUtils.find(internalGetPlainAttrs(), new Predicate<P>() {
+
+            @Override
+            public boolean evaluate(final P plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && plainAttr.getMembership() == null
+                        && plainSchemaName.equals(plainAttr.getSchema().getKey());
+            }
+        });
+    }
+
+    @Override
+    public P getPlainAttr(final String plainSchemaName, final Membership<?> membership) {
+        return IterableUtils.find(internalGetPlainAttrs(), new Predicate<P>() {
+
+            @Override
+            public boolean evaluate(final P plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && plainAttr.getMembership() != null && plainAttr.getMembership().equals(membership)
+                        && plainSchemaName.equals(plainAttr.getSchema().getKey());
+            }
+        });
+    }
+
+    @Override
+    public List<? extends P> getPlainAttrs() {
+        return CollectionUtils.select(internalGetPlainAttrs(), new Predicate<P>() {
+
+            @Override
+            public boolean evaluate(final P plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && plainAttr.getMembership() == null;
+            }
+        }, new ArrayList<P>());
+    }
+
+    @Override
+    public Collection<? extends P> getPlainAttrs(final String plainSchemaName) {
+        return CollectionUtils.select(internalGetPlainAttrs(), new Predicate<P>() {
+
+            @Override
+            public boolean evaluate(final P plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && plainSchemaName.equals(plainAttr.getSchema().getKey());
+            }
+        });
+    }
+
+    @Override
+    public Collection<? extends P> getPlainAttrs(final Membership<?> membership) {
+        return CollectionUtils.select(internalGetPlainAttrs(), new Predicate<P>() {
+
+            @Override
+            public boolean evaluate(final P plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && membership.equals(plainAttr.getMembership());
+            }
+        });
+    }
+
+    @Override
+    public M getMembership(final String groupKey) {
+        return IterableUtils.find(getMemberships(), new Predicate<M>() {
+
+            @Override
+            public boolean evaluate(final M membership) {
+                return groupKey != null && groupKey.equals(membership.getRightEnd().getKey());
+            }
+        });
+    }
+
+    @Override
+    public REL getRelationship(final RelationshipType relationshipType, final String otherEndKey) {
+        return IterableUtils.find(getRelationships(), new Predicate<REL>() {
+
+            @Override
+            public boolean evaluate(final REL relationship) {
+                return otherEndKey != null && otherEndKey.equals(relationship.getRightEnd().getKey())
+                        && ((relationshipType == null && relationship.getType() == null)
+                        || (relationshipType != null && relationshipType.equals(relationship.getType())));
+            }
+        });
+    }
+
+    @Override
+    public Collection<? extends REL> getRelationships(final RelationshipType relationshipType) {
+        return CollectionUtils.select(getRelationships(), new Predicate<REL>() {
+
+            @Override
+            public boolean evaluate(final REL relationship) {
+                return relationshipType != null && relationshipType.equals(relationship.getType());
+            }
+        });
+    }
+
+    @Override
+    public Collection<? extends REL> getRelationships(final String otherEndKey) {
+        return CollectionUtils.select(getRelationships(), new Predicate<REL>() {
+
+            @Override
+            public boolean evaluate(final REL relationship) {
+                return otherEndKey != null && otherEndKey.equals(relationship.getRightEnd().getKey());
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
index a4d6eea..5c1b203 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
@@ -26,6 +26,7 @@ import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -342,17 +343,17 @@ public class JPAAnyUtils implements AnyUtils {
 
     @Transactional(readOnly = true)
     @Override
-    public <S extends Schema> Set<S> getAllowedSchemas(final Any<?> any, final Class<S> reference) {
-        Set<S> schemas = new HashSet<>();
+    public <S extends Schema> AllowedSchemas<S> getAllowedSchemas(final Any<?> any, final Class<S> reference) {
+        AllowedSchemas<S> result = null;
 
         if (any instanceof User) {
-            schemas.addAll(userDAO.findAllowedSchemas((User) any, reference));
+            result = userDAO.findAllowedSchemas((User) any, reference);
         } else if (any instanceof Group) {
-            schemas.addAll(groupDAO.findAllowedSchemas((Group) any, reference));
+            result = groupDAO.findAllowedSchemas((Group) any, reference);
         } else if (any instanceof AnyObject) {
-            schemas.addAll(anyObjectDAO.findAllowedSchemas((AnyObject) any, reference));
+            result = anyObjectDAO.findAllowedSchemas((AnyObject) any, reference);
         }
 
-        return schemas;
+        return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
index f9a8151..044faae 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
@@ -27,9 +27,11 @@ import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
 import javax.validation.Valid;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
@@ -37,7 +39,8 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
 
 @Entity
-@Table(name = JPAAPlainAttr.TABLE)
+@Table(name = JPAAPlainAttr.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "owner_id", "membership_id", "schema_id" }))
 public class JPAAPlainAttr extends AbstractPlainAttr<AnyObject> implements APlainAttr {
 
     private static final long serialVersionUID = 8066058729580952116L;
@@ -47,6 +50,12 @@ public class JPAAPlainAttr extends AbstractPlainAttr<AnyObject> implements APlai
     @ManyToOne(fetch = FetchType.EAGER)
     private JPAAnyObject owner;
 
+    /**
+     * The membership of this attribute; might be {@code NULL} if this attribute is not related to a membership.
+     */
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAAMembership membership;
+
     @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
     @Valid
     private List<JPAAPlainAttrValue> values = new ArrayList<>();
@@ -67,6 +76,17 @@ public class JPAAPlainAttr extends AbstractPlainAttr<AnyObject> implements APlai
     }
 
     @Override
+    public AMembership getMembership() {
+        return membership;
+    }
+
+    @Override
+    public void setMembership(final AMembership membership) {
+        checkType(membership, JPAAMembership.class);
+        this.membership = (JPAAMembership) membership;
+    }
+
+    @Override
     protected boolean addForMultiValue(final PlainAttrValue attrValue) {
         checkType(attrValue, JPAAPlainAttrValue.class);
         return values.add((JPAAPlainAttrValue) attrValue);

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index 44f55df..d790082 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import javax.persistence.Cacheable;
 import javax.persistence.CascadeType;
+import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
@@ -33,17 +33,14 @@ import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.IterableUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
-import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 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.jpa.entity.AbstractAny;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractGroupableRelatable;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyType;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyTypeClass;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
@@ -51,12 +48,18 @@ import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResour
 @Entity
 @Table(name = JPAAnyObject.TABLE)
 @Cacheable
-public class JPAAnyObject extends AbstractAny<APlainAttr> implements AnyObject {
+public class JPAAnyObject
+        extends AbstractGroupableRelatable<AnyObject, AMembership, APlainAttr, AnyObject, ARelationship>
+        implements AnyObject {
 
     private static final long serialVersionUID = 9063766472970643492L;
 
     public static final String TABLE = "AnyObject";
 
+    @Column(unique = true)
+    @NotNull
+    private String name;
+
     @NotNull
     @ManyToOne(fetch = FetchType.EAGER, optional = false)
     private JPAAnyType type;
@@ -79,15 +82,25 @@ public class JPAAnyObject extends AbstractAny<APlainAttr> implements AnyObject {
             @JoinColumn(name = "anyTypeClass_id"))
     private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "leftEnd")
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "leftEnd")
     @Valid
     private List<JPAARelationship> relationships = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "leftEnd")
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "leftEnd")
     @Valid
     private List<JPAAMembership> memberships = new ArrayList<>();
 
     @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
     public AnyType getType() {
         return type;
     }
@@ -99,22 +112,28 @@ public class JPAAnyObject extends AbstractAny<APlainAttr> implements AnyObject {
     }
 
     @Override
+    public boolean add(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        return resources.add((JPAExternalResource) resource);
+    }
+
+    @Override
+    public List<? extends ExternalResource> getResources() {
+        return resources;
+    }
+
+    @Override
     public boolean add(final APlainAttr attr) {
         checkType(attr, JPAAPlainAttr.class);
         return plainAttrs.add((JPAAPlainAttr) attr);
     }
 
     @Override
-    public List<? extends APlainAttr> getPlainAttrs() {
+    protected List<? extends APlainAttr> internalGetPlainAttrs() {
         return plainAttrs;
     }
 
     @Override
-    protected List<JPAExternalResource> internalGetResources() {
-        return resources;
-    }
-
-    @Override
     public boolean add(final AnyTypeClass auxClass) {
         checkType(auxClass, JPAAnyTypeClass.class);
         return this.auxClasses.add((JPAAnyTypeClass) auxClass);
@@ -132,41 +151,6 @@ public class JPAAnyObject extends AbstractAny<APlainAttr> implements AnyObject {
     }
 
     @Override
-    public ARelationship getRelationship(final RelationshipType relationshipType, final String anyObjectKey) {
-        return IterableUtils.find(getRelationships(), new Predicate<ARelationship>() {
-
-            @Override
-            public boolean evaluate(final ARelationship relationship) {
-                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey())
-                        && ((relationshipType == null && relationship.getType() == null)
-                        || (relationshipType != null && relationshipType.equals(relationship.getType())));
-            }
-        });
-    }
-
-    @Override
-    public Collection<? extends ARelationship> getRelationships(final RelationshipType relationshipType) {
-        return CollectionUtils.select(getRelationships(), new Predicate<ARelationship>() {
-
-            @Override
-            public boolean evaluate(final ARelationship relationship) {
-                return relationshipType != null && relationshipType.equals(relationship.getType());
-            }
-        });
-    }
-
-    @Override
-    public Collection<? extends ARelationship> getRelationships(final String anyObjectKey) {
-        return CollectionUtils.select(getRelationships(), new Predicate<ARelationship>() {
-
-            @Override
-            public boolean evaluate(final ARelationship relationship) {
-                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey());
-            }
-        });
-    }
-
-    @Override
     public List<? extends ARelationship> getRelationships() {
         return relationships;
     }
@@ -178,17 +162,6 @@ public class JPAAnyObject extends AbstractAny<APlainAttr> implements AnyObject {
     }
 
     @Override
-    public AMembership getMembership(final String groupKey) {
-        return IterableUtils.find(getMemberships(), new Predicate<AMembership>() {
-
-            @Override
-            public boolean evaluate(final AMembership membership) {
-                return groupKey != null && groupKey.equals(membership.getRightEnd().getKey());
-            }
-        });
-    }
-
-    @Override
     public List<? extends AMembership> getMemberships() {
         return memberships;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
index 1ceaaa7..88ce38f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
@@ -47,7 +47,7 @@ public class JPAConf extends AbstractProvidedKeyEntity implements Conf {
 
     public static final String TABLE = "SyncopeConf";
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "owner")
     @Valid
     private List<JPACPlainAttr> plainAttrs = new ArrayList<>();
 
@@ -58,6 +58,12 @@ public class JPAConf extends AbstractProvidedKeyEntity implements Conf {
     }
 
     @Override
+    public boolean remove(final CPlainAttr attr) {
+        checkType(attr, JPACPlainAttr.class);
+        return plainAttrs.remove((JPACPlainAttr) attr);
+    }
+
+    @Override
     public CPlainAttr getPlainAttr(final String plainSchemaName) {
         return IterableUtils.find(plainAttrs, new Predicate<CPlainAttr>() {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttr.java
index 644fa27..53cf335 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGPlainAttr.java
@@ -27,6 +27,7 @@ import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
 import javax.validation.Valid;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
@@ -37,7 +38,8 @@ import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
 
 @Entity
-@Table(name = JPAGPlainAttr.TABLE)
+@Table(name = JPAGPlainAttr.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "owner_id", "schema_id" }))
 public class JPAGPlainAttr extends AbstractPlainAttr<Group> implements GPlainAttr {
 
     private static final long serialVersionUID = 2848159565890995780L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
index 8afb1ae..bcfa9b0 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGroup.java
@@ -44,6 +44,7 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembers
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.group.TypeExtension;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.UDynGroupMembership;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractAny;
@@ -74,7 +75,7 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
     @ManyToOne
     private JPAGroup groupOwner;
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "owner")
     @Valid
     private List<JPAGPlainAttr> plainAttrs = new ArrayList<>();
 
@@ -104,6 +105,16 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
     private List<JPATypeExtension> typeExtensions = new ArrayList<>();
 
     @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    @Override
     public AnyType getType() {
         return ApplicationContextProvider.getBeanFactory().getBean(AnyTypeDAO.class).findGroup();
     }
@@ -114,18 +125,14 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
     }
 
     @Override
-    protected List<JPAExternalResource> internalGetResources() {
-        return resources;
-    }
-
-    @Override
-    public String getName() {
-        return name;
+    public boolean add(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        return resources.add((JPAExternalResource) resource);
     }
 
     @Override
-    public void setName(final String name) {
-        this.name = name;
+    public List<? extends ExternalResource> getResources() {
+        return resources;
     }
 
     @Override
@@ -157,6 +164,24 @@ public class JPAGroup extends AbstractAny<GPlainAttr> implements Group {
     }
 
     @Override
+    public boolean remove(final GPlainAttr attr) {
+        checkType(attr, JPAGPlainAttr.class);
+        return plainAttrs.remove((JPAGPlainAttr) attr);
+    }
+
+    @Override
+    public GPlainAttr getPlainAttr(final String plainSchemaName) {
+        return IterableUtils.find(getPlainAttrs(), new Predicate<GPlainAttr>() {
+
+            @Override
+            public boolean evaluate(final GPlainAttr plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && plainSchemaName.equals(plainAttr.getSchema().getKey());
+            }
+        });
+    }
+
+    @Override
     public List<? extends GPlainAttr> getPlainAttrs() {
         return plainAttrs;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 438994f..1d00f89 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -183,6 +183,10 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
                 name = "groupOwnerSchema";
                 break;
 
+            case AnyObjectName:
+                name = "anyObjectName";
+                break;
+                
             default:
                 name = intAttrName;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
index 84c9c84..bdabf2c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
@@ -27,9 +27,11 @@ import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
 import javax.validation.Valid;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
@@ -37,7 +39,8 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
 
 @Entity
-@Table(name = JPAUPlainAttr.TABLE)
+@Table(name = JPAUPlainAttr.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "owner_id", "membership_id", "schema_id" }))
 public class JPAUPlainAttr extends AbstractPlainAttr<User> implements UPlainAttr {
 
     private static final long serialVersionUID = 6333601983691157406L;
@@ -51,6 +54,12 @@ public class JPAUPlainAttr extends AbstractPlainAttr<User> implements UPlainAttr
     private JPAUser owner;
 
     /**
+     * The membership of this attribute; might be {@code NULL} if this attribute is not related to a membership.
+     */
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAUMembership membership;
+
+    /**
      * Values of this attribute (if schema is not UNIQUE).
      */
     @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
@@ -76,6 +85,17 @@ public class JPAUPlainAttr extends AbstractPlainAttr<User> implements UPlainAttr
     }
 
     @Override
+    public UMembership getMembership() {
+        return membership;
+    }
+
+    @Override
+    public void setMembership(final UMembership membership) {
+        checkType(membership, JPAUMembership.class);
+        this.membership = (JPAUMembership) membership;
+    }
+
+    @Override
     protected boolean addForMultiValue(final PlainAttrValue attrValue) {
         checkType(attrValue, JPAUPlainAttrValue.class);
         return values.add((JPAUPlainAttrValue) attrValue);

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index a0ecf00..f207cfe 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import java.util.ArrayList;
 import java.util.Calendar;
-import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import javax.persistence.Basic;
@@ -47,9 +46,6 @@ import javax.validation.Valid;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.IterableUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.entity.user.SecurityQuestion;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
@@ -62,18 +58,21 @@ import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
-import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractAny;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractGroupableRelatable;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyTypeClass;
 import org.apache.syncope.core.persistence.jpa.entity.JPARole;
 
 @Entity
 @Table(name = JPAUser.TABLE)
 @Cacheable
-public class JPAUser extends AbstractAny<UPlainAttr> implements User {
+public class JPAUser
+        extends AbstractGroupableRelatable<User, UMembership, UPlainAttr, AnyObject, URelationship>
+        implements User {
 
     private static final long serialVersionUID = -3905046855521446823L;
 
@@ -172,11 +171,11 @@ public class JPAUser extends AbstractAny<UPlainAttr> implements User {
             @JoinColumn(name = "anyTypeClass_id"))
     private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "leftEnd")
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "leftEnd")
     @Valid
     private List<JPAURelationship> relationships = new ArrayList<>();
 
-    @OneToMany(cascade = CascadeType.ALL, mappedBy = "leftEnd")
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "leftEnd")
     @Valid
     private List<JPAUMembership> memberships = new ArrayList<>();
 
@@ -197,7 +196,13 @@ public class JPAUser extends AbstractAny<UPlainAttr> implements User {
     }
 
     @Override
-    protected List<JPAExternalResource> internalGetResources() {
+    public boolean add(final ExternalResource resource) {
+        checkType(resource, JPAExternalResource.class);
+        return resources.add((JPAExternalResource) resource);
+    }
+
+    @Override
+    public List<? extends ExternalResource> getResources() {
         return resources;
     }
 
@@ -270,7 +275,7 @@ public class JPAUser extends AbstractAny<UPlainAttr> implements User {
     }
 
     @Override
-    public List<? extends UPlainAttr> getPlainAttrs() {
+    protected List<? extends UPlainAttr> internalGetPlainAttrs() {
         return plainAttrs;
     }
 
@@ -471,41 +476,6 @@ public class JPAUser extends AbstractAny<UPlainAttr> implements User {
     }
 
     @Override
-    public URelationship getRelationship(final RelationshipType relationshipType, final String anyObjectKey) {
-        return IterableUtils.find(getRelationships(), new Predicate<URelationship>() {
-
-            @Override
-            public boolean evaluate(final URelationship relationship) {
-                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey())
-                        && ((relationshipType == null && relationship.getType() == null)
-                        || (relationshipType != null && relationshipType.equals(relationship.getType())));
-            }
-        });
-    }
-
-    @Override
-    public Collection<? extends URelationship> getRelationships(final RelationshipType relationshipType) {
-        return CollectionUtils.select(getRelationships(), new Predicate<URelationship>() {
-
-            @Override
-            public boolean evaluate(final URelationship relationship) {
-                return relationshipType != null && relationshipType.equals(relationship.getType());
-            }
-        });
-    }
-
-    @Override
-    public Collection<? extends URelationship> getRelationships(final String anyObjectKey) {
-        return CollectionUtils.select(getRelationships(), new Predicate<URelationship>() {
-
-            @Override
-            public boolean evaluate(final URelationship relationship) {
-                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey());
-            }
-        });
-    }
-
-    @Override
     public List<? extends URelationship> getRelationships() {
         return relationships;
     }
@@ -517,17 +487,6 @@ public class JPAUser extends AbstractAny<UPlainAttr> implements User {
     }
 
     @Override
-    public UMembership getMembership(final String groupKey) {
-        return IterableUtils.find(getMemberships(), new Predicate<UMembership>() {
-
-            @Override
-            public boolean evaluate(final UMembership membership) {
-                return groupKey != null && groupKey.equals(membership.getRightEnd().getKey());
-            }
-        });
-    }
-
-    @Override
     public List<? extends UMembership> getMemberships() {
         return memberships;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AnyValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AnyValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AnyValidator.java
index fb28c4e..37e227f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AnyValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/AnyValidator.java
@@ -18,42 +18,63 @@
  */
 package org.apache.syncope.core.persistence.jpa.validation.entity;
 
-import java.util.Collection;
 import javax.validation.ConstraintValidatorContext;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Transformer;
 import org.apache.syncope.common.lib.types.EntityViolationType;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.conf.Conf;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
 
 @SuppressWarnings("rawtypes")
 public class AnyValidator extends AbstractValidator<AnyCheck, Any> {
 
+    private boolean raiseNotAllowedViolation(
+            final ConstraintValidatorContext context,
+            final String schema,
+            final Group group) {
+
+        if (group == null) {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidPlainAttr,
+                            schema + " not allowed for this instance")).
+                    addPropertyNode("plainAttrs").addConstraintViolation();
+        } else {
+            context.buildConstraintViolationWithTemplate(
+                    getTemplate(EntityViolationType.InvalidPlainAttr,
+                            schema + " not allowed for membership of group " + group.getName())).
+                    addPropertyNode("plainAttrs").addConstraintViolation();
+        }
+        return false;
+    }
+
     @Override
     public boolean isValid(final Any any, final ConstraintValidatorContext context) {
         context.disableDefaultConstraintViolation();
 
         if (!(any instanceof Conf)) {
-            Collection<String> allowedPlainSchemas = CollectionUtils.collect(new JPAAnyUtilsFactory().
-                    getInstance(any.getType().getKind()).getAllowedSchemas(any, PlainSchema.class),
-                    new Transformer<PlainSchema, String>() {
+            AllowedSchemas<PlainSchema> allowedPlainSchemas = new JPAAnyUtilsFactory().
+                    getInstance(any.getType().getKind()).getAllowedSchemas(any, PlainSchema.class);
 
-                @Override
-                public String transform(final PlainSchema schema) {
-                    return schema.getKey();
+            for (PlainAttr<?> attr : ((Any<?>) any).getPlainAttrs()) {
+                if (attr != null && !allowedPlainSchemas.forSelfContains(attr.getSchema().getKey())) {
+                    return raiseNotAllowedViolation(context, attr.getSchema().getKey(), null);
                 }
-            });
+            }
+            if (any instanceof GroupableRelatable) {
+                for (Membership<?> membership : ((GroupableRelatable<?, ?, ?, ?, ?>) any).getMemberships()) {
+                    for (PlainAttr<?> attr : ((GroupableRelatable<?, ?, ?, ?, ?>) any).getPlainAttrs(membership)) {
+                        if (attr != null && !allowedPlainSchemas.forMembershipsContains(
+                                membership.getRightEnd(), attr.getSchema().getKey())) {
 
-            for (PlainAttr<?> attr : ((Any<?>) any).getPlainAttrs()) {
-                if (attr != null && !allowedPlainSchemas.contains(attr.getSchema().getKey())) {
-                    context.buildConstraintViolationWithTemplate(
-                            getTemplate(EntityViolationType.InvalidPlainSchema,
-                                    attr.getSchema().getKey() + " not allowed for this instance")).
-                            addPropertyNode("plainAttrs").addConstraintViolation();
-                    return false;
+                            return raiseNotAllowedViolation(
+                                    context, attr.getSchema().getKey(), membership.getRightEnd());
+                        }
+                    }
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java
index 387e368..e1bdf68 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/EntityValidationListener.java
@@ -29,6 +29,7 @@ import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.AnnotatedEntity;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.ProvidedKeyEntity;
 import org.apache.syncope.core.persistence.api.entity.Schema;
@@ -41,9 +42,6 @@ import org.slf4j.LoggerFactory;
  */
 public class EntityValidationListener {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(EntityValidationListener.class);
 
     @PrePersist
@@ -62,6 +60,7 @@ public class EntityValidationListener {
                         && !Schema.class.equals(interf)
                         && !Task.class.equals(interf)
                         && !Policy.class.equals(interf)
+                        && !GroupableRelatable.class.equals(interf)
                         && !Any.class.equals(interf)
                         && Entity.class.isAssignableFrom(interf)) {
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValueValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValueValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValueValidator.java
index da00ebd..64ec693 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValueValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PlainAttrValueValidator.java
@@ -74,7 +74,7 @@ public class PlainAttrValueValidator extends AbstractValidator<PlainAttrValueChe
                             + "]" + " is " + uniqueValueSchema + ", while owning attribute schema is " + attrSchema);
 
                     context.disableDefaultConstraintViolation();
-                    context.buildConstraintViolationWithTemplate(getTemplate(EntityViolationType.InvalidPlainSchema,
+                    context.buildConstraintViolationWithTemplate(getTemplate(EntityViolationType.InvalidPlainAttr,
                             "Unique value schema is " + uniqueValueSchema
                             + ", while owning attribute schema is " + attrSchema)).addPropertyNode("schema").
                             addConstraintViolation();

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
index f12e913..cc324c6 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnyObjectTest.java
@@ -62,6 +62,7 @@ public class AnyObjectTest extends AbstractTest {
     @Test
     public void save() {
         AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
+        anyObject.setName("a name");
         anyObject.setType(anyTypeDAO.find("PRINTER"));
         anyObject.setRealm(realmDAO.findByFullPath(SyncopeConstants.ROOT_REALM));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
index 712aa51..2b7f441 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainAttrTest.java
@@ -170,7 +170,7 @@ public class PlainAttrTest extends AbstractTest {
         // for attribute
         assertTrue(iee.hasViolation(EntityViolationType.InvalidValueList));
         // for uauv
-        assertTrue(iee.hasViolation(EntityViolationType.InvalidPlainSchema));
+        assertTrue(iee.hasViolation(EntityViolationType.InvalidPlainAttr));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ConfTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ConfTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ConfTest.java
new file mode 100644
index 0000000..f9bcff1
--- /dev/null
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ConfTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.outer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.apache.syncope.core.persistence.api.dao.ConfDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.jpa.AbstractTest;
+import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainAttrValue;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional("Master")
+public class ConfTest extends AbstractTest {
+
+    @Autowired
+    private ConfDAO confDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    private void add(final CPlainAttr newAttr, final String value) {
+        JPACPlainAttrValue attrValue;
+        if (newAttr.getSchema().isUniqueConstraint()) {
+            attrValue = new JPACPlainAttrValue();
+            ((PlainAttrUniqueValue) attrValue).setSchema(newAttr.getSchema());
+        } else {
+            attrValue = new JPACPlainAttrValue();
+        }
+        newAttr.add(value, attrValue);
+    }
+
+    @Test
+    public void update() {
+        CPlainAttr expireTime = confDAO.find("token.expireTime");
+        assertNotNull(expireTime);
+        long value = expireTime.getValues().get(0).getLongValue();
+        value++;
+
+        CPlainAttr attr = entityFactory.newEntity(CPlainAttr.class);
+        attr.setSchema(plainSchemaDAO.find("token.expireTime"));
+        add(attr, String.valueOf(value));
+
+        confDAO.save(expireTime);
+        confDAO.flush();
+
+        CPlainAttr actual = confDAO.find("token.expireTime");
+        assertEquals(expireTime, actual);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
index ae450aa..8037a2b 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/GroupTest.java
@@ -271,6 +271,7 @@ public class GroupTest extends AbstractTest {
     public void adynMembership() {
         // 0. create any object matching the condition below
         AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
+        anyObject.setName("name");
         anyObject.setType(anyTypeDAO.find("PRINTER"));
         anyObject.setRealm(realmDAO.findByFullPath("/even/two"));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
index 1a5a62d..cdb3067 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/UserTest.java
@@ -23,9 +23,14 @@ import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.util.List;
 import java.util.UUID;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidEntityException;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
@@ -145,7 +150,91 @@ public class UserTest extends AbstractTest {
                 user.getRelationships().get(0).getRightEnd().getKey());
     }
 
-    @Test // search by derived attribute
+    @Test
+    public void membershipWithAttrs() {
+        User user = userDAO.findByUsername("vivaldi");
+        assertNotNull(user);
+        assertTrue(user.getMemberships().isEmpty());
+
+        // add 'obscure' to user (no membership): works because 'obscure' is from 'other', default class for USER
+        UPlainAttr attr = entityFactory.newEntity(UPlainAttr.class);
+        attr.setOwner(user);
+        attr.setSchema(plainSchemaDAO.find("obscure"));
+        attr.add("testvalue", anyUtilsFactory.getInstance(AnyTypeKind.USER));
+        user.add(attr);
+
+        // add 'obscure' to user (via 'artDirector' membership): does not work because 'obscure' is from 'other'
+        // but 'artDirector' defines no type extension
+        UMembership membership = entityFactory.newEntity(UMembership.class);
+        membership.setLeftEnd(user);
+        membership.setRightEnd(groupDAO.findByName("artDirector"));
+        user.add(membership);
+
+        attr = entityFactory.newEntity(UPlainAttr.class);
+        attr.setOwner(user);
+        attr.setMembership(membership);
+        attr.setSchema(plainSchemaDAO.find("obscure"));
+        attr.add("testvalue2", anyUtilsFactory.getInstance(AnyTypeKind.USER));
+        user.add(attr);
+
+        try {
+            userDAO.save(user);
+            fail();
+        } catch (InvalidEntityException e) {
+            assertNotNull(e);
+        }
+
+        // replace 'artDirector' with 'additional', which defines type extension with class 'other' and 'csv':
+        // now it works
+        membership = user.getMembership(groupDAO.findByName("artDirector").getKey());
+        user.remove(user.getPlainAttr("obscure", membership));
+        user.getMemberships().remove(membership);
+        membership.setLeftEnd(null);
+
+        membership = entityFactory.newEntity(UMembership.class);
+        membership.setLeftEnd(user);
+        membership.setRightEnd(groupDAO.findByName("additional"));
+        user.add(membership);
+
+        attr = entityFactory.newEntity(UPlainAttr.class);
+        attr.setOwner(user);
+        attr.setMembership(membership);
+        attr.setSchema(plainSchemaDAO.find("obscure"));
+        attr.add("testvalue2", anyUtilsFactory.getInstance(AnyTypeKind.USER));
+        user.add(attr);
+
+        userDAO.save(user);
+        userDAO.flush();
+
+        user = userDAO.findByUsername("vivaldi");
+        assertEquals(1, user.getMemberships().size());
+
+        final UMembership newM = user.getMembership(groupDAO.findByName("additional").getKey());
+        assertEquals(1, user.getPlainAttrs(newM).size());
+
+        assertNull(user.getPlainAttr("obscure").getMembership());
+        assertEquals(2, user.getPlainAttrs("obscure").size());
+        assertTrue(user.getPlainAttrs("obscure").contains(user.getPlainAttr("obscure")));
+        assertTrue(IterableUtils.matchesAny(user.getPlainAttrs("obscure"), new Predicate<UPlainAttr>() {
+
+            @Override
+            public boolean evaluate(final UPlainAttr object) {
+                return object.getMembership() == null;
+            }
+        }));
+        assertTrue(IterableUtils.matchesAny(user.getPlainAttrs("obscure"), new Predicate<UPlainAttr>() {
+
+            @Override
+            public boolean evaluate(final UPlainAttr object) {
+                return newM.equals(object.getMembership());
+            }
+        }));
+    }
+
+    /**
+     * Search by derived attribute.
+     */
+    @Test
     public void issueSYNCOPE800() {
         // create derived attribute (literal as prefix)
         DerSchema prefix = entityFactory.newEntity(DerSchema.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 37fc8a1..e956a90 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -175,15 +175,15 @@ under the License.
          accountPolicy_id="20ab5a8c-4b0c-432c-b957-f7fb9784d9f7"
          passwordPolicy_id="ce93fcda-dc3a-4369-a7b0-a6108c261c85"/>
   
-  <AnyObject id="fc6dbc3a-6c07-4965-8781-921e7401a4a5"
+  <AnyObject id="fc6dbc3a-6c07-4965-8781-921e7401a4a5" name="HP LJ 1300n"
              realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" type_id="PRINTER"
              creator="admin" lastModifier="admin" 
              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
-  <AnyObject id="8559d14d-58c2-46eb-a2d4-a7d35161e8f8"
+  <AnyObject id="8559d14d-58c2-46eb-a2d4-a7d35161e8f8" name="Canon MF 8030cn"
              realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" type_id="PRINTER"
              creator="admin" lastModifier="admin" 
              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
-  <AnyObject id="9e1d130c-d6a3-48b1-98b3-182477ed0688"
+  <AnyObject id="9e1d130c-d6a3-48b1-98b3-182477ed0688" name="Epson Stylus Color"
              realm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c" type_id="PRINTER"
              creator="admin" lastModifier="admin" 
              creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
@@ -966,6 +966,9 @@ under the License.
   <MappingItem id="23aa0299-ddbb-4e59-8918-0ab2a32465fa" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="ID" 
                intMappingType="AnyObjectKey" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="BOTH"/>
+  <MappingItem id="3dc96af0-5d0a-4ec1-be84-244716d88401" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="PRINTERNAME" 
+               intMappingType="AnyObjectName" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="BOTH"/>
   <MappingItem id="f3ef9f8b-e667-4b18-969f-ba98c3d78bc0" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="LOCATION" 
                intAttrName="location" intMappingType="AnyObjectPlainSchema"
                mandatoryCondition="false" connObjectKey="0" password="0" purpose="BOTH"/>
@@ -985,7 +988,7 @@ under the License.
         pullMode="INCREMENTAL" unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1"/>
   <AnyTemplatePullTask id="3a6173a9-8c34-4e37-b3b1-0c2ea385fac0"
                        pullTask_id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" anyType_id="USER"
-                       template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","readonly":false,"values":[""]}],"virAttrs":[],"resources":["resource-testdb"],"relationships":[],"memberships":[{"leftType":null,"leftKey":0,"rightType":"GROUP","rightKey":"f779c0d4-633b-4be5-8f57-32eb478a3ca5","groupName":null}],"dynGroups":[],"roles":[],"dynRoles":[],"plainAttrs":[{"schema":"ctype","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}]}'/>
+                       template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","readonly":false,"values":[""]}],"virAttrs":[],"resources":["resource-testdb"],"relationships":[],"memberships":[{"rightType":"GROUP","rightKey":"f779c0d4-633b-4be5-8f57-32eb478a3ca5","groupName":null}],"dynGroups":[],"roles":[],"dynRoles":[],"plainAttrs":[{"schema":"ctype","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}]}'/>
   <AnyTemplatePullTask id="b3772d66-ec06-4133-bf38-b3273845ac5b"
                        pullTask_id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" anyType_id="GROUP"
                        template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"plainAttrs":[]}'/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
index bc70fb8..c4f44bd 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/DerAttrHandler.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.provisioning.api;
 import java.util.Map;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 
 public interface DerAttrHandler {
 
@@ -37,7 +38,27 @@ public interface DerAttrHandler {
      * Calculates derived attributes values associated to the given any.
      *
      * @param any any object
-     * @return derived attribute values, either for local cache or external resources
+     * @return derived attribute values
      */
     Map<DerSchema, String> getValues(Any<?> any);
+
+    /**
+     * Calculates derived attribute value associated to the given any, for the given membership and
+     * derived schema.
+     *
+     * @param any any object
+     * @param membership membership
+     * @param schema derived schema
+     * @return derived attribute value
+     */
+    String getValue(Any<?> any, Membership<?> membership, DerSchema schema);
+
+    /**
+     * Calculates derived attributes values associated to the given any, for the given membership.
+     *
+     * @param any any object
+     * @param membership membership
+     * @return derived attribute values
+     */
+    Map<DerSchema, String> getValues(final Any<?> any, final Membership<?> membership);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
index 0b8d60f..72bb198 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
@@ -21,13 +21,14 @@ package org.apache.syncope.core.provisioning.api;
 import java.util.List;
 import java.util.Map;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 
 public interface VirAttrHandler {
 
     /**
      * Query external resource (or cache, if configured) associated to the given any for values associated to the given
-     * virtual schema.
+     * virtual schema, not related to any membership.
      *
      * @param any any object
      * @param schema virtual schema
@@ -37,13 +38,36 @@ public interface VirAttrHandler {
     List<String> getValues(Any<?> any, VirSchema schema);
 
     /**
+     * Query external resource (or cache, if configured) associated to the given any for values associated to the given
+     * virtual schema, for the given membership.
+     *
+     * @param any any object
+     * @param membership membership
+     * @param schema virtual schema
+     * @return virtual attribute values, either for local cache or external resource, if resource is owned by the given
+     * any and associated to the given virtual schema; empty list otherwise.
+     */
+    List<String> getValues(Any<?> any, Membership<?> membership, VirSchema schema);
+
+    /**
      * Query external resources (or cache, if configured) associated to the given any for values associated to all
      * {@link VirSchema} instances in the {@link org.apache.syncope.core.persistence.api.entity.AnyTypeClass}
-     * associated to the given any.
+     * associated to the given any, with no membership.
      *
      * @param any any object
      * @return virtual attribute values, either for local cache or external resources
      */
     Map<VirSchema, List<String>> getValues(Any<?> any);
 
+    /**
+     * Query external resources (or cache, if configured) associated to the given any for values associated to all
+     * {@link VirSchema} instances in the {@link org.apache.syncope.core.persistence.api.entity.AnyTypeClass}
+     * associated to the given any, for the given membership.
+     *
+     * @param any any object
+     * @param membership membership
+     * @return virtual attribute values, either for local cache or external resources
+     */
+    Map<VirSchema, List<String>> getValues(Any<?> any, Membership<?> membership);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DerAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DerAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DerAttrHandlerImpl.java
index f827f46..0261752 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DerAttrHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DerAttrHandlerImpl.java
@@ -28,6 +28,7 @@ import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,6 +36,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+@Transactional(readOnly = true)
 @Component
 public class DerAttrHandlerImpl implements DerAttrHandler {
 
@@ -57,10 +59,23 @@ public class DerAttrHandlerImpl implements DerAttrHandler {
         return result;
     }
 
-    @Transactional(readOnly = true)
     @Override
     public String getValue(final Any<?> any, final DerSchema schema) {
-        if (!anyUtilsFactory.getInstance(any).getAllowedSchemas(any, DerSchema.class).contains(schema)) {
+        if (!anyUtilsFactory.getInstance(any).
+                getAllowedSchemas(any, DerSchema.class).forSelfContains(schema)) {
+
+            LOG.debug("{} not allowed for {}", schema, any);
+            return null;
+        }
+
+        return getValues(any, Collections.singleton(schema)).get(schema);
+    }
+
+    @Override
+    public String getValue(final Any<?> any, final Membership<?> membership, final DerSchema schema) {
+        if (!anyUtilsFactory.getInstance(any).
+                getAllowedSchemas(any, DerSchema.class).getForMembership(membership.getRightEnd()).contains(schema)) {
+
             LOG.debug("{} not allowed for {}", schema, any);
             return null;
         }
@@ -68,10 +83,19 @@ public class DerAttrHandlerImpl implements DerAttrHandler {
         return getValues(any, Collections.singleton(schema)).get(schema);
     }
 
-    @Transactional(readOnly = true)
     @Override
     public Map<DerSchema, String> getValues(final Any<?> any) {
-        return getValues(any, anyUtilsFactory.getInstance(any).getAllowedSchemas(any, DerSchema.class));
+        return getValues(
+                any,
+                anyUtilsFactory.getInstance(any).getAllowedSchemas(any, DerSchema.class).getForSelf());
+    }
+
+    @Override
+    public Map<DerSchema, String> getValues(final Any<?> any, final Membership<?> membership) {
+        return getValues(
+                any,
+                anyUtilsFactory.getInstance(any).getAllowedSchemas(any, DerSchema.class).
+                getForMembership(membership.getRightEnd()));
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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 c742c1a..b84799a 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
@@ -32,6 +32,7 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.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;
@@ -68,6 +69,7 @@ import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.api.entity.Schema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
@@ -698,6 +700,16 @@ public class MappingManagerImpl implements MappingManager {
                 }
                 break;
 
+            case AnyObjectName:
+                for (Any<?> any : anys) {
+                    if (any instanceof AnyObject) {
+                        APlainAttrValue attrValue = entityFactory.newEntity(APlainAttrValue.class);
+                        attrValue.setStringValue(((AnyObject) any).getName());
+                        values.add(attrValue);
+                    }
+                }
+                break;
+
             default:
         }
 
@@ -800,6 +812,14 @@ public class MappingManagerImpl implements MappingManager {
                 }
                 break;
 
+            case AnyObjectName:
+                if (anyTO instanceof AnyObjectTO) {
+                    ((AnyObjectTO) anyTO).setName(values.isEmpty() || values.get(0) == null
+                            ? null
+                            : values.get(0).toString());
+                }
+                break;
+
             case UserPlainSchema:
             case GroupPlainSchema:
             case AnyObjectPlainSchema:


[03/15] syncope git commit: [SYNCOPE-860] provides role and group members inspecting feature

Posted by il...@apache.org.
[SYNCOPE-860] provides role and group members inspecting feature


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

Branch: refs/heads/SYNCOPE-862
Commit: f5f6270ef2f437a036f36e5cd6a9e31d0515e7ab
Parents: befa49c
Author: fmartelli <fa...@gmail.com>
Authored: Tue Jun 14 16:55:27 2016 +0200
Committer: fmartelli <fa...@gmail.com>
Committed: Tue Jun 14 16:55:27 2016 +0200

----------------------------------------------------------------------
 .../console/panels/AnyDirectoryPanel.java       |   6 +-
 .../console/panels/AnyObjectDirectoryPanel.java | 109 +++++++-----
 .../syncope/client/console/panels/AnyPanel.java |  23 ++-
 .../client/console/panels/DirectoryPanel.java   |  11 +-
 .../console/panels/GroupDirectoryPanel.java     | 130 +++++++++++++-
 .../client/console/panels/ListViewPanel.java    |   8 +-
 .../console/panels/MembersTogglePanel.java      | 118 +++++++++++++
 .../client/console/panels/ParametersPanel.java  |   6 +-
 .../console/panels/RoleDirectoryPanel.java      |  65 ++++++-
 .../console/panels/SecurityQuestionsPanel.java  |   6 +-
 .../console/panels/UserDirectoryPanel.java      | 139 ++++++++-------
 .../AnyObjectSelectionDirectoryPanel.java       |   8 +-
 .../search/AnySelectionDirectoryPanel.java      |   7 +-
 .../search/GroupSelectionDirectoryPanel.java    |   8 +-
 .../search/UserSelectionDirectoryPanel.java     |   8 +-
 .../wicket/markup/html/form/ActionLink.java     |   5 +
 .../markup/html/form/ActionLinksPanel.java      | 171 +++++++++++++------
 .../client/console/widgets/JobWidget.java       |  12 +-
 .../ReconciliationDetailsModalPanel.java        |   4 +-
 .../console/widgets/ReconciliationWidget.java   |  10 +-
 .../client/console/wizards/WizardMgtPanel.java  |  19 ++-
 .../console/wizards/any/Relationships.java      |   2 +-
 .../panels/GroupDirectoryPanel.properties       |   1 +
 .../panels/GroupDirectoryPanel_it.properties    |   1 +
 .../panels/GroupDirectoryPanel_pt_BR.properties |   1 +
 .../panels/GroupDirectoryPanel_ru.properties    |   1 +
 .../console/panels/MembersTogglePanel.html      |  32 ++++
 .../panels/RoleDirectoryPanel.properties        |   1 +
 .../panels/RoleDirectoryPanel_it.properties     |   1 +
 .../panels/RoleDirectoryPanel_pt_BR.properties  |   1 +
 .../panels/RoleDirectoryPanel_ru.properties     |   5 +-
 .../markup/html/form/ActionLinksPanel.html      |   5 +
 .../panels/CamelRoutesDirectoryPanel.java       |   4 +-
 .../syncope/fit/console/GroupsITCase.java       |  28 +++
 .../apache/syncope/fit/console/RolesITCase.java |  17 ++
 35 files changed, 754 insertions(+), 219 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
index f2e8aec..256df52 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyDirectoryPanel.java
@@ -83,7 +83,11 @@ public abstract class AnyDirectoryPanel<A extends AnyTO, E extends AbstractAnyRe
     protected final BaseModal<Serializable> utilityModal = new BaseModal<>("outer");
 
     protected AnyDirectoryPanel(final String id, final Builder<A, E> builder) {
-        super(id, builder);
+        this(id, builder, true);
+    }
+
+    protected AnyDirectoryPanel(final String id, final Builder<A, E> builder, final boolean wizardInModal) {
+        super(id, builder, wizardInModal);
         this.realm = builder.realm;
         this.type = builder.type;
         this.fiql = builder.fiql;

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
index ecdb0ff..5473ee0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDirectoryPanel.java
@@ -60,8 +60,8 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
 
     private static final long serialVersionUID = -1100228004207271270L;
 
-    protected AnyObjectDirectoryPanel(final String id, final Builder builder) {
-        super(id, builder);
+    protected AnyObjectDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
+        super(id, builder, wizardInModal);
     }
 
     @Override
@@ -106,8 +106,6 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
                     Arrays.asList(AnyObjectDisplayAttributesModalPanel.DEFAULT_SELECTION));
         }
 
-        setWindowClosedReloadCallback(displayAttributeModal);
-
         columns.add(new ActionColumn<AnyObjectTO, String>(new ResourceModel("actions")) {
 
             private static final long serialVersionUID = -3503023501954863131L;
@@ -118,24 +116,6 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
 
                 panel.add(new ActionLink<AnyObjectTO>() {
 
-                    private static final long serialVersionUID = -7978723352517770645L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
-                        final IModel<AnyWrapper<AnyObjectTO>> formModel = new CompoundPropertyModel<>(new AnyWrapper<>(
-                                model.getObject()));
-                        altDefaultModal.setFormModel(formModel);
-
-                        target.add(altDefaultModal.setContent(new StatusModal<>(
-                                altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
-
-                        altDefaultModal.header(new Model<>(
-                                getString("any.edit", new Model<>(new AnyWrapper<>(model.getObject())))));
-
-                        altDefaultModal.show(true);
-                    }
-                }, ActionType.MANAGE_RESOURCES, AnyEntitlement.READ.getFor(type)).add(new ActionLink<AnyObjectTO>() {
-
                     private static final long serialVersionUID = -7978723352517770644L;
 
                     @Override
@@ -156,31 +136,12 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
                         send(AnyObjectDirectoryPanel.this, Broadcast.EXACT,
                                 new AjaxWizard.NewItemActionEvent<>(new AnyWrapper<>(clone), target));
                     }
-                }, ActionType.CLONE, AnyEntitlement.CREATE.getFor(type)).add(new ActionLink<AnyObjectTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
-                        target.add(utilityModal.setContent(new AnyPropagationTasks(
-                                utilityModal, AnyTypeKind.ANY_OBJECT, model.getObject().getKey(), pageRef)));
-
-                        utilityModal.header(new StringResourceModel("any.propagation.tasks", model));
-                        utilityModal.show(true);
-                    }
-                }, ActionType.PROPAGATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<AnyObjectTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
 
                     @Override
-                    public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
-                        target.add(utilityModal.setContent(
-                                new NotificationTasks(AnyTypeKind.ANY_OBJECT, model.getObject().getKey(), pageRef)));
-                        utilityModal.header(new StringResourceModel("any.notification.tasks", model));
-                        utilityModal.show(true);
-                        target.add(utilityModal);
+                    protected boolean statusCondition(final AnyObjectTO modelObject) {
+                        return addAjaxLink.isVisibleInHierarchy();
                     }
-                }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<AnyObjectTO>() {
+                }, ActionType.CLONE, AnyEntitlement.CREATE.getFor(type)).add(new ActionLink<AnyObjectTO>() {
 
                     private static final long serialVersionUID = -7978723352517770646L;
 
@@ -192,13 +153,62 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
                             target.add(container);
                         } catch (SyncopeClientException e) {
                             LOG.error("While deleting object {}", model.getObject().getKey(), e);
-                           SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                     ? e.getClass().getName() : e.getMessage());
                         }
                         SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
                     }
                 }, ActionType.DELETE, AnyEntitlement.DELETE.getFor(type));
 
+                if (wizardInModal) {
+                    panel.add(new ActionLink<AnyObjectTO>() {
+
+                        private static final long serialVersionUID = -7978723352517770645L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
+                            final IModel<AnyWrapper<AnyObjectTO>> formModel = new CompoundPropertyModel<>(
+                                    new AnyWrapper<>(
+                                            model.getObject()));
+                            altDefaultModal.setFormModel(formModel);
+
+                            target.add(altDefaultModal.setContent(new StatusModal<>(
+                                    altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
+
+                            altDefaultModal.header(new Model<>(
+                                    getString("any.edit", new Model<>(new AnyWrapper<>(model.getObject())))));
+
+                            altDefaultModal.show(true);
+                        }
+                    }, ActionType.MANAGE_RESOURCES, AnyEntitlement.READ.getFor(type)).add(
+                            new ActionLink<AnyObjectTO>() {
+
+                        private static final long serialVersionUID = -7978723352517770644L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
+                            target.add(utilityModal.setContent(new AnyPropagationTasks(
+                                    utilityModal, AnyTypeKind.ANY_OBJECT, model.getObject().getKey(), pageRef)));
+
+                            utilityModal.header(new StringResourceModel("any.propagation.tasks", model));
+                            utilityModal.show(true);
+                        }
+                    }, ActionType.PROPAGATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<AnyObjectTO>() {
+
+                                private static final long serialVersionUID = -7978723352517770644L;
+
+                                @Override
+                                public void onClick(final AjaxRequestTarget target, final AnyObjectTO ignore) {
+                                    target.add(utilityModal.setContent(
+                                            new NotificationTasks(AnyTypeKind.ANY_OBJECT, model.getObject().getKey(),
+                                                    pageRef)));
+                                    utilityModal.header(new StringResourceModel("any.notification.tasks", model));
+                                    utilityModal.show(true);
+                                    target.add(utilityModal);
+                                }
+                            }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST);
+                }
+
                 return panel.build(componentId, model.getObject());
             }
 
@@ -218,6 +228,11 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
                         displayAttributeModal.header(new ResourceModel("any.attr.display"));
                         displayAttributeModal.show(true);
                     }
+
+                    @Override
+                    protected boolean statusCondition(final Serializable modelObject) {
+                        return wizardInModal;
+                    }
                 }, ActionType.CHANGE_VIEW, AnyEntitlement.READ.getFor(type)).add(
                         new ActionLink<Serializable>() {
 
@@ -250,8 +265,8 @@ public class AnyObjectDirectoryPanel extends AnyDirectoryPanel<AnyObjectTO, AnyO
         }
 
         @Override
-        protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> newInstance(final String id) {
-            return new AnyObjectDirectoryPanel(id, this);
+        protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> newInstance(final String id, final boolean wizardInModal) {
+            return new AnyObjectDirectoryPanel(id, this, wizardInModal);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
index 9a3d8c6..04d57ff 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyPanel.java
@@ -61,7 +61,7 @@ import org.apache.wicket.model.util.ListModel;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class AnyPanel extends Panel {
+public class AnyPanel extends Panel implements ModalPanel {
 
     private static final long serialVersionUID = -1100228004207271270L;
 
@@ -88,6 +88,17 @@ public class AnyPanel extends Panel {
             final RealmTO realmTO,
             final Triple<UserFormLayoutInfo, GroupFormLayoutInfo, Map<String, AnyObjectFormLayoutInfo>> formLayoutInfo,
             final PageReference pageRef) {
+        this(id, anyTypeTO, realmTO, formLayoutInfo, true, pageRef);
+    }
+
+    @SuppressWarnings({ "unchecked", "unchecked" })
+    public AnyPanel(
+            final String id,
+            final AnyTypeTO anyTypeTO,
+            final RealmTO realmTO,
+            final Triple<UserFormLayoutInfo, GroupFormLayoutInfo, Map<String, AnyObjectFormLayoutInfo>> formLayoutInfo,
+            final boolean enableSearch,
+            final PageReference pageRef) {
 
         super(id);
         this.anyTypeTO = anyTypeTO;
@@ -136,7 +147,7 @@ public class AnyPanel extends Panel {
             }
         };
         accordion.setOutputMarkupId(true);
-        add(accordion);
+        add(accordion.setEnabled(enableSearch).setVisible(enableSearch));
 
         directoryPanel = getDirectoryPanel("searchResult");
         add(directoryPanel);
@@ -197,7 +208,7 @@ public class AnyPanel extends Panel {
         return panel;
     }
 
-    private Panel getDirectoryPanel(final String id) {
+    protected Panel getDirectoryPanel(final String id) {
         final Panel panel;
         final String fiql;
         switch (anyTypeTO.getKind()) {
@@ -209,7 +220,7 @@ public class AnyPanel extends Panel {
                         anyTypeClassRestClient.list(anyTypeTO.getClasses()),
                         anyTypeTO.getKey(),
                         pageRef).setRealm(realmTO.getFullPath()).setFiltered(true).
-                        setFiql(fiql).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
+                        setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
                         userTO,
                         anyTypeTO.getClasses(),
                         formLayoutInfo.getLeft(),
@@ -225,7 +236,7 @@ public class AnyPanel extends Panel {
                         anyTypeClassRestClient.list(anyTypeTO.getClasses()),
                         anyTypeTO.getKey(),
                         pageRef).setRealm(realmTO.getFullPath()).setFiltered(true).
-                        setFiql(fiql).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
+                        setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
                         groupTO,
                         anyTypeTO.getClasses(),
                         formLayoutInfo.getMiddle(),
@@ -243,7 +254,7 @@ public class AnyPanel extends Panel {
                         anyTypeClassRestClient.list(anyTypeTO.getClasses()),
                         anyTypeTO.getKey(),
                         pageRef).setRealm(realmTO.getFullPath()).setFiltered(true).
-                        setFiql(fiql).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
+                        setFiql(fiql).setWizardInModal(true).addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
                         anyObjectTO,
                         anyTypeTO.getClasses(),
                         formLayoutInfo.getRight().get(anyTypeTO.getKey()),

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
index 1ce1f19..330590e 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/DirectoryPanel.java
@@ -117,7 +117,7 @@ public abstract class DirectoryPanel<
             private static final long serialVersionUID = -8424727765826509309L;
 
             @Override
-            protected WizardMgtPanel<W> newInstance(final String id) {
+            protected WizardMgtPanel<W> newInstance(final String id, final boolean wizardInModal) {
                 throw new UnsupportedOperationException("Not supported yet.");
             }
         }.setFiltered(false), wizardInModal);
@@ -160,9 +160,12 @@ public abstract class DirectoryPanel<
 
             @Override
             public void onClose(final AjaxRequestTarget target) {
-                DirectoryPanel.EventDataWrapper event = new DirectoryPanel.EventDataWrapper();
-                event.setTarget(target);
-                send(DirectoryPanel.this, Broadcast.EXACT, event);
+                final EventDataWrapper data = new EventDataWrapper();
+                data.setTarget(target);
+                data.setRows(rows);
+
+                send(DirectoryPanel.this, Broadcast.EXACT, data);
+
                 modal.show(false);
             }
         });

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
index 60d70b9..3da0f44 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/GroupDirectoryPanel.java
@@ -25,9 +25,13 @@ import java.util.Arrays;
 import java.util.List;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.layout.FormLayoutInfoUtils;
 import org.apache.syncope.client.console.notifications.NotificationTasks;
+import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.GroupRestClient;
 import org.apache.syncope.client.console.status.StatusModal;
 import org.apache.syncope.client.console.tasks.AnyPropagationTasks;
@@ -41,17 +45,25 @@ import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.client.console.wizards.any.AnyWrapper;
 import org.apache.syncope.client.console.wizards.any.GroupWrapper;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyEntitlement;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.BulkMembersActionType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.CompoundPropertyModel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
@@ -65,13 +77,103 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
 
     private final BaseModal<Serializable> typeExtensionsModal = new BaseModal<>("outer");
 
-    protected GroupDirectoryPanel(final String id, final Builder builder) {
-        super(id, builder);
+    protected final BaseModal<Serializable> membersModal = new BaseModal<>("outer");
+
+    protected final MembersTogglePanel templates;
+
+    protected GroupDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
+        super(id, builder, wizardInModal);
 
         typeExtensionsModal.size(Modal.Size.Large);
         addOuterObject(typeExtensionsModal);
         setWindowClosedReloadCallback(typeExtensionsModal);
         typeExtensionsModal.addSubmitButton();
+
+        addOuterObject(membersModal);
+        membersModal.size(Modal.Size.Large);
+
+        templates = new MembersTogglePanel(page.getPageReference()) {
+
+            private static final long serialVersionUID = -8765794727538618705L;
+
+            @Override
+            protected Serializable onApplyInternal(
+                    final GroupTO groupTO, final String type, final AjaxRequestTarget target) {
+
+                final AnyTypeRestClient typeRestClient = new AnyTypeRestClient();
+                final AnyTypeClassRestClient classRestClient = new AnyTypeClassRestClient();
+
+                final AnyTypeTO anyTypeTO = typeRestClient.read(type);
+
+                ModalPanel panel = new AnyPanel(BaseModal.CONTENT_ID, anyTypeTO, null, null, false, pageRef) {
+
+                    private static final long serialVersionUID = 1L;
+
+                    @Override
+                    protected Panel getDirectoryPanel(final String id) {
+
+                        final Panel panel;
+
+                        if (AnyTypeKind.USER.name().equals(type)) {
+                            String query = SyncopeClient.getUserSearchConditionBuilder().and(
+                                    SyncopeClient.getUserSearchConditionBuilder().inGroups(groupTO.getKey()),
+                                    SyncopeClient.getUserSearchConditionBuilder().is("key").notNullValue()).query();
+
+                            panel = new UserDirectoryPanel.Builder(
+                                    classRestClient.list(anyTypeTO.getClasses()), anyTypeTO.getKey(), pageRef).
+                                    setRealm("/").
+                                    setFiltered(true).
+                                    setFiql(query).
+                                    disableCheckBoxes().
+                                    addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
+                                            new UserTO(),
+                                            anyTypeTO.getClasses(),
+                                            FormLayoutInfoUtils.fetch(typeRestClient.list()).getLeft(),
+                                            pageRef), false).
+                                    setWizardInModal(false).build(id);
+
+                            MetaDataRoleAuthorizationStrategy.authorize(
+                                    panel, WebPage.RENDER, StandardEntitlement.USER_LIST);
+                        } else {
+                            String query = SyncopeClient.getAnyObjectSearchConditionBuilder(type).and(
+                                    SyncopeClient.getUserSearchConditionBuilder().inGroups(groupTO.getKey()),
+                                    SyncopeClient.getUserSearchConditionBuilder().is("key").notNullValue()).query();
+
+                            panel = new AnyObjectDirectoryPanel.Builder(
+                                    classRestClient.list(anyTypeTO.getClasses()), anyTypeTO.getKey(), pageRef).
+                                    setRealm("/").
+                                    setFiltered(true).
+                                    setFiql(query).
+                                    disableCheckBoxes().
+                                    addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
+                                            new AnyObjectTO(),
+                                            anyTypeTO.getClasses(),
+                                            FormLayoutInfoUtils.fetch(typeRestClient.list()).getRight().get(type),
+                                            pageRef), false).
+                                    setWizardInModal(false).build(id);
+
+                            MetaDataRoleAuthorizationStrategy.authorize(
+                                    panel, WebPage.RENDER, AnyEntitlement.LIST.getFor(anyTypeTO.getKey()));
+                        }
+
+                        return panel;
+                    }
+                };
+
+                membersModal.header(new StringResourceModel(
+                        "group.members",
+                        GroupDirectoryPanel.this,
+                        Model.of(Pair.of(groupTO, type))));
+
+                membersModal.setContent(panel);
+                membersModal.show(true);
+                target.add(membersModal);
+
+                return null;
+            }
+        };
+
+        addOuterObject(templates);
     }
 
     @Override
@@ -125,6 +227,20 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final GroupTO ignore) {
+                        templates.setTargetObject(model.getObject());
+                        templates.toggle(target, true);
+                    }
+
+                    @Override
+                    public boolean isIndicatorEnabled() {
+                        return false;
+                    }
+                }, ActionType.MEMBERS, StandardEntitlement.GROUP_READ).add(new ActionLink<GroupTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770645L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final GroupTO ignore) {
                         IModel<AnyWrapper<GroupTO>> formModel = new CompoundPropertyModel<>(
                                 new AnyWrapper<>(model.getObject()));
                         altDefaultModal.setFormModel(formModel);
@@ -203,7 +319,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
                             target.add(container);
                         } catch (SyncopeClientException e) {
                             LOG.error("While deleting object {}", model.getObject().getKey(), e);
-                           SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                     ? e.getClass().getName() : e.getMessage());
                         }
                         SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
@@ -220,7 +336,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
                             target.add(container);
                         } catch (SyncopeClientException e) {
                             LOG.error("While provisioning members of group {}", model.getObject().getKey(), e);
-                           SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                     ? e.getClass().getName() : e.getMessage());
                         }
                         SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
@@ -239,7 +355,7 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
                             target.add(container);
                         } catch (SyncopeClientException e) {
                             LOG.error("While provisioning members of group {}", model.getObject().getKey(), e);
-                           SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                            SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                     ? e.getClass().getName() : e.getMessage());
                         }
                         SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
@@ -293,8 +409,8 @@ public class GroupDirectoryPanel extends AnyDirectoryPanel<GroupTO, GroupRestCli
         }
 
         @Override
-        protected WizardMgtPanel<AnyWrapper<GroupTO>> newInstance(final String id) {
-            return new GroupDirectoryPanel(id, this);
+        protected WizardMgtPanel<AnyWrapper<GroupTO>> newInstance(final String id, final boolean wizardInModal) {
+            return new GroupDirectoryPanel(id, this, wizardInModal);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
index ca63496..b649c4f 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ListViewPanel.java
@@ -100,8 +100,9 @@ public abstract class ListViewPanel<T extends Serializable> extends WizardMgtPan
             final ActionLinksPanel.Builder<T> actions,
             final CheckAvailability check,
             final boolean reuseItem,
+            final boolean wizardInModal,
             final IModel<? extends Collection<T>> model) {
-        super(id);
+        super(id, wizardInModal);
         setOutputMarkupId(true);
 
         this.check = Model.of(check);
@@ -354,8 +355,9 @@ public abstract class ListViewPanel<T extends Serializable> extends WizardMgtPan
         }
 
         @Override
-        protected WizardMgtPanel<T> newInstance(final String id) {
-            return new ListViewPanel<T>(id, items, reference, includes, actions, check, reuseItem, model) {
+        protected WizardMgtPanel<T> newInstance(final String id, final boolean wizardInModal) {
+            return new ListViewPanel<T>(
+                    id, items, reference, includes, actions, check, reuseItem, wizardInModal, model) {
 
                 private static final long serialVersionUID = 1L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java
new file mode 100644
index 0000000..1b8695c
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/MembersTogglePanel.java
@@ -0,0 +1,118 @@
+/*
+ * 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.client.console.panels;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
+import org.apache.syncope.client.console.wicket.markup.html.form.FieldPanel;
+import org.apache.syncope.common.lib.EntityTOUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.model.LoadableDetachableModel;
+import org.apache.wicket.model.Model;
+
+public abstract class MembersTogglePanel extends TogglePanel<Serializable> {
+
+    private static final long serialVersionUID = -3195479265440591519L;
+
+    private GroupTO groupTO;
+
+    protected final Form<?> form;
+
+    protected final Model<String> typeModel = new Model<>();
+
+    private final LoadableDetachableModel<List<String>> anyTypes = new LoadableDetachableModel<List<String>>() {
+
+        private static final long serialVersionUID = 5275935387613157437L;
+
+        @Override
+        protected List<String> load() {
+            final List<String> res = new ArrayList<>();
+            CollectionUtils.collect(
+                    CollectionUtils.select(new AnyTypeRestClient().list(), new Predicate<AnyTypeTO>() {
+
+                        @Override
+                        public boolean evaluate(final AnyTypeTO object) {
+                            return object.getKind() != AnyTypeKind.GROUP;
+                        }
+                    }), EntityTOUtils.<AnyTypeTO>keyTransformer(), res);
+            return res;
+        }
+    };
+
+    public MembersTogglePanel(final PageReference pageRef) {
+        super("outer", "groupMembers");
+        this.pageRef = pageRef;
+
+        form = new Form<>("membersForm");
+        addInnerObject(form);
+
+        final FieldPanel<String> type = new AjaxDropDownChoicePanel<>("type", "type", typeModel, false).
+                setChoices(anyTypes).
+                setStyleSheet("form-control").
+                setRequired(true);
+
+        type.hideLabel();
+        form.add(type);
+
+        form.add(new AjaxSubmitLink("changeit", form) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                try {
+                    onApplyInternal(groupTO, typeModel.getObject(), target);
+                    toggle(target, false);
+                } catch (SyncopeClientException e) {
+                    SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                            ? e.getClass().getName()
+                            : e.getMessage());
+                    LOG.error("While inspecting group memebers of type {}", typeModel.getObject(), e);
+                }
+                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+            }
+
+            @Override
+            protected void onError(final AjaxRequestTarget target, final Form<?> form) {
+                SyncopeConsoleSession.get().getNotificationPanel().refresh(target);
+            }
+        });
+    }
+
+    protected abstract Serializable onApplyInternal(
+            final GroupTO groupTO, final String type, final AjaxRequestTarget target);
+
+    public void setTargetObject(final GroupTO groupTO) {
+        this.groupTO = groupTO;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
index 00e274a..e1fbfe1 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ParametersPanel.java
@@ -77,8 +77,8 @@ public class ParametersPanel extends DirectoryPanel<
             private static final long serialVersionUID = 8769126634538601689L;
 
             @Override
-            protected WizardMgtPanel<AttrTO> newInstance(final String id) {
-                return new ParametersPanel(id, this);
+            protected WizardMgtPanel<AttrTO> newInstance(final String id, final boolean wizardInModal) {
+                throw new UnsupportedOperationException();
             }
         });
 
@@ -173,7 +173,7 @@ public class ParametersPanel extends DirectoryPanel<
                                     target.add(container);
                                 } catch (Exception e) {
                                     LOG.error("While deleting {}", model.getObject(), e);
-                                   SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                                    SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                             ? e.getClass().getName() : e.getMessage());
                                 }
                                 SyncopeConsoleSession.get().getNotificationPanel().refresh(target);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
index fb7fa26..1bcd7bb 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/RoleDirectoryPanel.java
@@ -29,6 +29,9 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.commons.RoleDataProvider;
+import org.apache.syncope.client.console.layout.FormLayoutInfoUtils;
+import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
+import org.apache.syncope.client.console.rest.AnyTypeRestClient;
 import org.apache.syncope.client.console.rest.RoleRestClient;
 import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
@@ -38,8 +41,12 @@ import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPane
 import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.WizardMgtPanel;
 import org.apache.syncope.client.console.wizards.role.RoleWrapper;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.RoleTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -47,8 +54,11 @@ import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDa
 import org.apache.wicket.event.Broadcast;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
+import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
 
 public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, RoleDataProvider, RoleRestClient> {
 
@@ -56,6 +66,8 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
 
     protected final BaseModal<Serializable> utilityModal = new BaseModal<>("outer");
 
+    protected final BaseModal<Serializable> membersModal = new BaseModal<>("outer");
+
     protected RoleDirectoryPanel(final String id, final Builder builder) {
         super(id, builder);
         setShowResultPage(true);
@@ -68,6 +80,9 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
         utilityModal.size(Modal.Size.Large);
         utilityModal.addSubmitButton();
 
+        addOuterObject(membersModal);
+        membersModal.size(Modal.Size.Large);
+
         MetaDataRoleAuthorizationStrategy.authorize(addAjaxLink, ENABLE, StandardEntitlement.ROLE_CREATE);
     }
 
@@ -106,6 +121,54 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final RoleTO ignore) {
+                        final String query = SyncopeClient.getUserSearchConditionBuilder().and(
+                                SyncopeClient.getUserSearchConditionBuilder().inRoles(model.getObject().getKey()),
+                                SyncopeClient.getUserSearchConditionBuilder().is("key").notNullValue()).query();
+
+                        final AnyTypeRestClient typeRestClient = new AnyTypeRestClient();
+                        final AnyTypeClassRestClient classRestClient = new AnyTypeClassRestClient();
+
+                        final AnyTypeTO anyTypeTO = typeRestClient.read(AnyTypeKind.USER.name());
+
+                        ModalPanel panel = new AnyPanel(BaseModal.CONTENT_ID, anyTypeTO, null, null, false, pageRef) {
+
+                            private static final long serialVersionUID = 1L;
+
+                            @Override
+                            protected Panel getDirectoryPanel(final String id) {
+                                final Panel panel = new UserDirectoryPanel.Builder(
+                                        classRestClient.list(anyTypeTO.getClasses()), anyTypeTO.getKey(), pageRef).
+                                        setRealm("/").
+                                        setFiltered(true).
+                                        setFiql(query).
+                                        disableCheckBoxes().
+                                        addNewItemPanelBuilder(FormLayoutInfoUtils.instantiate(
+                                                new UserTO(),
+                                                anyTypeTO.getClasses(),
+                                                FormLayoutInfoUtils.fetch(typeRestClient.list()).getLeft(),
+                                                pageRef), false).
+                                        setWizardInModal(false).build(id);
+
+                                MetaDataRoleAuthorizationStrategy.authorize(
+                                        panel,
+                                        WebPage.RENDER,
+                                        StandardEntitlement.USER_LIST);
+
+                                return panel;
+                            }
+                        };
+
+                        membersModal.header(new StringResourceModel("role.members", RoleDirectoryPanel.this, model));
+                        membersModal.setContent(panel);
+                        membersModal.show(true);
+                        target.add(membersModal);
+                    }
+                }, ActionLink.ActionType.MEMBERS, StandardEntitlement.USER_LIST).add(new ActionLink<RoleTO>() {
+
+                    private static final long serialVersionUID = -7978723352517770644L;
+
+                    @Override
+                    public void onClick(final AjaxRequestTarget target, final RoleTO ignore) {
                         send(RoleDirectoryPanel.this, Broadcast.EXACT,
                                 new AjaxWizard.EditItemActionEvent<>(
                                         new RoleWrapper(new RoleRestClient().read(model.getObject().getKey())),
@@ -197,7 +260,7 @@ public class RoleDirectoryPanel extends DirectoryPanel<RoleTO, RoleWrapper, Role
         }
 
         @Override
-        protected WizardMgtPanel<RoleWrapper> newInstance(final String id) {
+        protected WizardMgtPanel<RoleWrapper> newInstance(final String id, final boolean wizardInModal) {
             return new RoleDirectoryPanel(id, this);
         }
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
index 2d65fbd..03af4fe 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SecurityQuestionsPanel.java
@@ -63,8 +63,8 @@ public class SecurityQuestionsPanel extends DirectoryPanel<
             private static final long serialVersionUID = 8769126634538601689L;
 
             @Override
-            protected WizardMgtPanel<SecurityQuestionTO> newInstance(final String id) {
-                return new SecurityQuestionsPanel(id, this);
+            protected WizardMgtPanel<SecurityQuestionTO> newInstance(final String id, final boolean wizardInModal) {
+                throw new UnsupportedOperationException();
             }
         }.disableCheckBoxes());
 
@@ -153,7 +153,7 @@ public class SecurityQuestionsPanel extends DirectoryPanel<
                                     target.add(container);
                                 } catch (Exception e) {
                                     LOG.error("While deleting {}", model.getObject(), e);
-                                   SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
+                                    SyncopeConsoleSession.get().error(StringUtils.isBlank(e.getMessage())
                                             ? e.getClass().getName() : e.getMessage());
                                 }
                                 SyncopeConsoleSession.get().getNotificationPanel().refresh(target);

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
index 920ad11..fed9254 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/UserDirectoryPanel.java
@@ -62,7 +62,11 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
     private static final long serialVersionUID = -1100228004207271270L;
 
     protected UserDirectoryPanel(final String id, final Builder builder) {
-        super(id, builder);
+        this(id, builder, true);
+    }
+
+    protected UserDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
+        super(id, builder, wizardInModal);
     }
 
     @Override
@@ -146,42 +150,6 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
 
                     @Override
                     public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
-                        IModel<AnyWrapper<UserTO>> formModel = new CompoundPropertyModel<>(
-                                new AnyWrapper<>(model.getObject()));
-                        altDefaultModal.setFormModel(formModel);
-
-                        target.add(altDefaultModal.setContent(new StatusModal<>(
-                                altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
-
-                        altDefaultModal.header(new Model<>(
-                                getString("any.edit", new Model<>(new AnyWrapper<>(model.getObject())))));
-
-                        altDefaultModal.show(true);
-                    }
-                }, ActionType.MANAGE_RESOURCES, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
-                        IModel<AnyWrapper<UserTO>> formModel = new CompoundPropertyModel<>(
-                                new AnyWrapper<>(model.getObject()));
-                        altDefaultModal.setFormModel(formModel);
-
-                        target.add(altDefaultModal.setContent(new StatusModal<>(
-                                altDefaultModal, pageRef, formModel.getObject().getInnerObject(), true)));
-
-                        altDefaultModal.header(new Model<>(
-                                getString("any.edit", new Model<>(new AnyWrapper<>(model.getObject())))));
-
-                        altDefaultModal.show(true);
-                    }
-                }, ActionType.ENABLE, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
-
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
                         send(UserDirectoryPanel.this, Broadcast.EXACT,
                                 new AjaxWizard.EditItemActionEvent<>(
                                         new UserWrapper(new UserRestClient().read(model.getObject().getKey())),
@@ -199,31 +167,13 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
                         send(UserDirectoryPanel.this, Broadcast.EXACT,
                                 new AjaxWizard.NewItemActionEvent<>(new UserWrapper(clone), target));
                     }
-                }, ActionType.CLONE, StandardEntitlement.USER_CREATE).add(new ActionLink<UserTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
 
                     @Override
-                    public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
-                        target.add(utilityModal.setContent(new AnyPropagationTasks(
-                                utilityModal, AnyTypeKind.USER, model.getObject().getKey(), pageRef)));
-
-                        utilityModal.header(new StringResourceModel("any.propagation.tasks", model));
-                        utilityModal.show(true);
+                    protected boolean statusCondition(final UserTO modelObject) {
+                        return addAjaxLink.isVisibleInHierarchy();
                     }
-                }, ActionType.PROPAGATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<UserTO>() {
-
-                    private static final long serialVersionUID = -7978723352517770644L;
 
-                    @Override
-                    public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
-                        target.add(utilityModal.setContent(
-                                new NotificationTasks(AnyTypeKind.USER, model.getObject().getKey(), pageRef)));
-                        utilityModal.header(new StringResourceModel("any.notification.tasks", model));
-                        utilityModal.show(true);
-                        target.add(utilityModal);
-                    }
-                }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<UserTO>() {
+                }, ActionType.CLONE, StandardEntitlement.USER_CREATE).add(new ActionLink<UserTO>() {
 
                     private static final long serialVersionUID = -7978723352517770644L;
 
@@ -242,6 +192,70 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
                     }
                 }, ActionType.DELETE, StandardEntitlement.USER_DELETE);
 
+                if (wizardInModal) {
+                    panel.add(new ActionLink<UserTO>() {
+
+                        private static final long serialVersionUID = -7978723352517770644L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
+                            IModel<AnyWrapper<UserTO>> formModel = new CompoundPropertyModel<>(
+                                    new AnyWrapper<>(model.getObject()));
+                            altDefaultModal.setFormModel(formModel);
+
+                            target.add(altDefaultModal.setContent(new StatusModal<>(
+                                    altDefaultModal, pageRef, formModel.getObject().getInnerObject(), false)));
+
+                            altDefaultModal.header(new Model<>(
+                                    getString("any.edit", new Model<>(new AnyWrapper<>(model.getObject())))));
+
+                            altDefaultModal.show(true);
+                        }
+                    }, ActionType.MANAGE_RESOURCES, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
+
+                        private static final long serialVersionUID = -7978723352517770644L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
+                            IModel<AnyWrapper<UserTO>> formModel = new CompoundPropertyModel<>(
+                                    new AnyWrapper<>(model.getObject()));
+                            altDefaultModal.setFormModel(formModel);
+
+                            target.add(altDefaultModal.setContent(new StatusModal<>(
+                                    altDefaultModal, pageRef, formModel.getObject().getInnerObject(), true)));
+
+                            altDefaultModal.header(new Model<>(
+                                    getString("any.edit", new Model<>(new AnyWrapper<>(model.getObject())))));
+
+                            altDefaultModal.show(true);
+                        }
+                    }, ActionType.ENABLE, StandardEntitlement.USER_READ).add(new ActionLink<UserTO>() {
+
+                        private static final long serialVersionUID = -7978723352517770644L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
+                            target.add(utilityModal.setContent(new AnyPropagationTasks(
+                                    utilityModal, AnyTypeKind.USER, model.getObject().getKey(), pageRef)));
+
+                            utilityModal.header(new StringResourceModel("any.propagation.tasks", model));
+                            utilityModal.show(true);
+                        }
+                    }, ActionType.PROPAGATION_TASKS, StandardEntitlement.TASK_LIST).add(new ActionLink<UserTO>() {
+
+                        private static final long serialVersionUID = -7978723352517770644L;
+
+                        @Override
+                        public void onClick(final AjaxRequestTarget target, final UserTO ignore) {
+                            target.add(utilityModal.setContent(
+                                    new NotificationTasks(AnyTypeKind.USER, model.getObject().getKey(), pageRef)));
+                            utilityModal.header(new StringResourceModel("any.notification.tasks", model));
+                            utilityModal.show(true);
+                            target.add(utilityModal);
+                        }
+                    }, ActionType.NOTIFICATION_TASKS, StandardEntitlement.TASK_LIST);
+                }
+
                 return panel.build(componentId, model.getObject());
             }
 
@@ -262,6 +276,11 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
                         displayAttributeModal.addSubmitButton();
                         displayAttributeModal.show(true);
                     }
+
+                    @Override
+                    protected boolean statusCondition(final Serializable modelObject) {
+                        return wizardInModal;
+                    }
                 }, ActionType.CHANGE_VIEW, StandardEntitlement.USER_READ).add(
                         new ActionLink<Serializable>() {
 
@@ -290,8 +309,8 @@ public class UserDirectoryPanel extends AnyDirectoryPanel<UserTO, UserRestClient
         }
 
         @Override
-        protected WizardMgtPanel<AnyWrapper<UserTO>> newInstance(final String id) {
-            return new UserDirectoryPanel(id, this);
+        protected WizardMgtPanel<AnyWrapper<UserTO>> newInstance(final String id, final boolean wizardInModal) {
+            return new UserDirectoryPanel(id, this, wizardInModal);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
index e9eb5bf..d89b3ea 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnyObjectSelectionDirectoryPanel.java
@@ -33,8 +33,8 @@ public final class AnyObjectSelectionDirectoryPanel
 
     private static final long serialVersionUID = -1100228004207271272L;
 
-    private AnyObjectSelectionDirectoryPanel(final String id, final Builder builder) {
-        super(id, builder, AnyObjectTO.class);
+    private AnyObjectSelectionDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
+        super(id, builder, AnyObjectTO.class, wizardInModal);
     }
 
     @Override
@@ -73,8 +73,8 @@ public final class AnyObjectSelectionDirectoryPanel
         }
 
         @Override
-        protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> newInstance(final String id) {
-            return new AnyObjectSelectionDirectoryPanel(id, this);
+        protected WizardMgtPanel<AnyWrapper<AnyObjectTO>> newInstance(final String id, final boolean wizardInModal) {
+            return new AnyObjectSelectionDirectoryPanel(id, this, wizardInModal);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnySelectionDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnySelectionDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnySelectionDirectoryPanel.java
index 3a0815c..5919dee 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnySelectionDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/AnySelectionDirectoryPanel.java
@@ -61,9 +61,12 @@ public abstract class AnySelectionDirectoryPanel<A extends AnyTO, E extends Abst
     private final Class<A> reference;
 
     protected AnySelectionDirectoryPanel(
-            final String id, final AnyDirectoryPanel.Builder<A, E> builder, final Class<A> reference) {
+            final String id,
+            final AnyDirectoryPanel.Builder<A, E> builder,
+            final Class<A> reference,
+            final boolean wizardInModal) {
 
-        super(id, builder);
+        super(id, builder, wizardInModal);
         this.reference = reference;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
index 0076af9..65c7bd6 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/GroupSelectionDirectoryPanel.java
@@ -32,8 +32,8 @@ public final class GroupSelectionDirectoryPanel extends AnySelectionDirectoryPan
 
     private static final long serialVersionUID = -1100228004207271271L;
 
-    private GroupSelectionDirectoryPanel(final String id, final Builder builder) {
-        super(id, builder, GroupTO.class);
+    private GroupSelectionDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
+        super(id, builder, GroupTO.class, wizardInModal);
     }
 
     @Override
@@ -72,8 +72,8 @@ public final class GroupSelectionDirectoryPanel extends AnySelectionDirectoryPan
         }
 
         @Override
-        protected WizardMgtPanel<AnyWrapper<GroupTO>> newInstance(final String id) {
-            return new GroupSelectionDirectoryPanel(id, this);
+        protected WizardMgtPanel<AnyWrapper<GroupTO>> newInstance(final String id, final boolean wizardInModal) {
+            return new GroupSelectionDirectoryPanel(id, this, wizardInModal);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
index 7545ec7..c3c8825 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/search/UserSelectionDirectoryPanel.java
@@ -32,8 +32,8 @@ public final class UserSelectionDirectoryPanel extends AnySelectionDirectoryPane
 
     private static final long serialVersionUID = -1100228004207271272L;
 
-    private UserSelectionDirectoryPanel(final String id, final Builder builder) {
-        super(id, builder, UserTO.class);
+    private UserSelectionDirectoryPanel(final String id, final Builder builder, final boolean wizardInModal) {
+        super(id, builder, UserTO.class, wizardInModal);
     }
 
     @Override
@@ -72,8 +72,8 @@ public final class UserSelectionDirectoryPanel extends AnySelectionDirectoryPane
         }
 
         @Override
-        protected WizardMgtPanel<AnyWrapper<UserTO>> newInstance(final String id) {
-            return new UserSelectionDirectoryPanel(id, this);
+        protected WizardMgtPanel<AnyWrapper<UserTO>> newInstance(final String id, final boolean wizardInModal) {
+            return new UserSelectionDirectoryPanel(id, this, wizardInModal);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f5f6270e/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
index 4faf86e..f772eec 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/markup/html/form/ActionLink.java
@@ -58,6 +58,7 @@ public abstract class ActionLink<T extends Serializable> implements Serializable
         ENABLE("update"),
         NOT_FOND("read"),
         VIEW("view"),
+        MEMBERS("members"),
         SEARCH("search"),
         DELETE("delete"),
         EXECUTE("execute"),
@@ -132,4 +133,8 @@ public abstract class ActionLink<T extends Serializable> implements Serializable
     public final boolean isEnabled(final T modelObject) {
         return this.enabled && statusCondition(modelObject);
     }
+
+    public boolean isIndicatorEnabled() {
+        return true;
+    }
 }


[12/15] syncope git commit: [SYNCOPE-862] Features complete

Posted by il...@apache.org.
[SYNCOPE-862] Features complete


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

Branch: refs/heads/SYNCOPE-862
Commit: 8e162494e707c3279f4bc43f951a7c87d869daef
Parents: a4afd4a
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Tue Jun 14 17:57:42 2016 +0200
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Tue Jun 14 17:59:30 2016 +0200

----------------------------------------------------------------------
 .../client/console/commons/Constants.java       |  34 +-
 .../NotificationWizardBuilder.java              | 103 +--
 .../client/console/panels/BeanPanel.java        |  60 +-
 .../console/panels/ConnObjectListViewPanel.java |   2 +-
 .../client/console/rest/SchemaRestClient.java   |   1 +
 .../client/console/wizards/any/Groups.java      |  11 +-
 .../console/wizards/any/Relationships.java      |  10 +-
 .../wizards/resources/ResourceMappingPanel.java | 317 ++++------
 .../SyncopeConsoleApplication.properties        |   1 +
 .../SyncopeConsoleApplication_it.properties     |   1 +
 .../SyncopeConsoleApplication_pt_BR.properties  |   1 +
 .../SyncopeConsoleApplication_ru.properties     |   1 +
 .../NotificationWizardBuilder$Details.html      |   3 -
 ...NotificationWizardBuilder$Details.properties |   3 +-
 ...ificationWizardBuilder$Details_it.properties |   3 +-
 ...cationWizardBuilder$Details_pt_BR.properties |   3 +-
 ...ificationWizardBuilder$Details_ru.properties |  14 +-
 .../NotificationWizardBuilder$Events.properties |   2 -
 ...tificationWizardBuilder$Events_it.properties |   2 -
 ...icationWizardBuilder$Events_pt_BR.properties |   2 -
 ...tificationWizardBuilder$Events_ru.properties |  52 +-
 .../console/pages/Notifications.properties      |   2 -
 .../console/pages/Notifications_it.properties   |   2 -
 .../pages/Notifications_pt_BR.properties        |   2 -
 .../console/pages/Notifications_ru.properties   |  50 +-
 .../wizards/resources/ResourceMappingPanel.html |  19 +-
 .../resources/ResourceProvisionPanel.properties |   5 +-
 .../ResourceProvisionPanel_it.properties        |   5 +-
 .../ResourceProvisionPanel_pt_BR.properties     |   5 +-
 .../ResourceProvisionPanel_ru.properties        |   6 +-
 .../syncope/common/lib/to/AnyObjectTO.java      |   2 +-
 .../common/lib/to/GroupableRelatableTO.java     |  36 ++
 .../syncope/common/lib/to/GroupableTO.java      |  31 -
 .../syncope/common/lib/to/RelatableTO.java      |  30 -
 .../apache/syncope/common/lib/to/UserTO.java    |   2 +-
 .../syncope/core/logic/ResourceLogic.java       |   6 +-
 .../logic/report/ReconciliationReportlet.java   |   6 +-
 .../core/persistence/api/dao/SchemaDAO.java     |   2 +-
 .../persistence/jpa/entity/JPAAnyUtils.java     |  11 +-
 .../jpa/entity/resource/JPAMappingItem.java     |   4 +-
 .../entity/ExternalResourceValidator.java       | 102 +--
 .../persistence/jpa/inner/ResourceTest.java     |  65 +-
 .../persistence/jpa/outer/ResourceTest.java     |   1 +
 .../test/resources/domains/MasterContent.xml    |  13 +-
 .../src/test/resources/domains/TwoContent.xml   |   4 +-
 .../core/provisioning/api/IntAttrName.java      | 103 +++
 .../provisioning/api/IntAttrNameParser.java     | 140 -----
 .../core/provisioning/api/MappingManager.java   |   7 +-
 .../api/data/MappingItemTransformer.java        |   4 +-
 .../provisioning/java/ConnectorFacadeProxy.java |   5 +-
 .../provisioning/java/IntAttrNameParser.java    | 120 ++++
 .../provisioning/java/MappingManagerImpl.java   | 623 +++++++------------
 .../provisioning/java/VirAttrHandlerImpl.java   |   5 +-
 .../java/data/AbstractAnyDataBinder.java        |  37 +-
 .../data/DefaultMappingItemTransformer.java     |   2 +-
 .../java/data/JEXLMappingItemTransformer.java   |  46 +-
 .../java/data/NotificationDataBinderImpl.java   |   7 +-
 .../java/data/ResourceDataBinderImpl.java       |  60 +-
 .../java/data/UserDataBinderImpl.java           |   5 +-
 .../notification/NotificationManagerImpl.java   |  30 +-
 .../AbstractPropagationTaskExecutor.java        |   6 +-
 .../propagation/PropagationManagerImpl.java     |   4 +-
 .../pushpull/AbstractPushResultHandler.java     |   4 +-
 .../pushpull/PlainAttrsPullCorrelationRule.java |   6 +-
 .../java/pushpull/PullJobDelegate.java          |  10 +-
 .../provisioning/java/pushpull/PullUtils.java   |  22 +-
 .../java/utils/ConnObjectUtils.java             |   3 +-
 .../provisioning/java/utils/MappingUtils.java   | 239 +++++++
 .../src/main/resources/provisioningContext.xml  |   1 +
 .../java/IntAttrNameParserTest.java             | 161 +++++
 .../core/provisioning/java/MappingTest.java     |   5 +-
 .../reference/PrefixMappingItemTransformer.java |   4 +-
 .../fit/console/NotificationsITCase.java        |  12 +-
 .../syncope/fit/console/TopologyITCase.java     |  13 +-
 .../apache/syncope/fit/core/GroupITCase.java    |  31 +-
 .../syncope/fit/core/MembershipITCase.java      | 112 ++++
 .../syncope/fit/core/MigrationITCase.java       |   4 +-
 .../apache/syncope/fit/core/ResourceITCase.java |  36 +-
 78 files changed, 1491 insertions(+), 1413 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
index 19b1ce1..7157c09 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/commons/Constants.java
@@ -23,7 +23,6 @@ import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig
 import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
 import org.apache.wicket.Component;
 import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 
 public final class Constants {
@@ -164,27 +163,9 @@ public final class Constants {
      */
     public static final String GUARDED_BYTE_ARRAY = "org.identityconnectors.common.security.GuardedByteArray";
 
-    public static Component getPopover(
-            final String id,
-            final IModel<String> msg,
-            final Component caller,
-            final TooltipConfig.Placement placement) {
-        return new Label(id, Model.of()).add(new PopoverBehavior(
-                Model.<String>of(),
-                msg,
-                new PopoverConfig().withHtml(true).withPlacement(placement)) {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected String createRelAttribute() {
-                return id;
-            }
-        });
-    }
-
     public static Component getJEXLPopover(final Component caller, final TooltipConfig.Placement placement) {
-        return getPopover("jexlInfo",
+        return new Label("jexlInfo", Model.of()).add(new PopoverBehavior(
+                Model.<String>of(),
                 Model.of(caller.getString("jexl_info")
                         + "<ul>"
                         + "<li>" + caller.getString("jexl_ex1") + "</li>"
@@ -192,8 +173,15 @@ public final class Constants {
                         + "</ul>"
                         + "<a href='https://commons.apache.org/proper/commons-jexl/reference/index.html' "
                         + "target='_blank'>" + caller.getString("jexl_syntax_url") + "</a>"),
-                caller,
-                placement);
+                new PopoverConfig().withHtml(true).withPlacement(placement)) {
+
+            private static final long serialVersionUID = -7867802555691605021L;
+
+            @Override
+            protected String createRelAttribute() {
+                return "jexlInfo";
+            }
+        });
     }
 
     private Constants() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index 4bc8478..cf97161 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -23,7 +23,6 @@ import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.EnumSet;
 import java.util.List;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.Transformer;
@@ -52,7 +51,6 @@ import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.wicket.PageReference;
@@ -119,50 +117,34 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
         private static final long serialVersionUID = -7709805590497687958L;
 
         public Details(final NotificationWrapper modelObject) {
-            final NotificationTO notificationTO = modelObject.getInnerObject();
-            final boolean createFlag = notificationTO.getKey() == null;
+            NotificationTO notificationTO = modelObject.getInnerObject();
+            boolean createFlag = notificationTO.getKey() == null;
 
-            final AjaxTextFieldPanel sender = new AjaxTextFieldPanel("sender", getString("sender"),
+            AjaxTextFieldPanel sender = new AjaxTextFieldPanel("sender", getString("sender"),
                     new PropertyModel<String>(notificationTO, "sender"));
             sender.addRequiredLabel();
             sender.addValidator(EmailAddressValidator.getInstance());
             add(sender);
 
-            final AjaxTextFieldPanel subject = new AjaxTextFieldPanel("subject", getString("subject"),
+            AjaxTextFieldPanel subject = new AjaxTextFieldPanel("subject", getString("subject"),
                     new PropertyModel<String>(notificationTO, "subject"));
             subject.addRequiredLabel();
             add(subject);
 
-            final AjaxDropDownChoicePanel<IntMappingType> recipientAttrType =
-                    new AjaxDropDownChoicePanel<>(
-                            "recipientAttrType",
-                            new ResourceModel("recipientAttrType", "recipientAttrType").getObject(),
-                            new PropertyModel<IntMappingType>(notificationTO, "recipientAttrType"));
-            recipientAttrType.setChoices(
-                    new ArrayList<>(IntMappingType.getAttributeTypes(AnyTypeKind.USER,
-                            EnumSet.of(IntMappingType.UserKey, IntMappingType.Password))));
-            recipientAttrType.addRequiredLabel();
-            add(recipientAttrType);
-
-            final AjaxDropDownChoicePanel<String> recipientAttrName = new AjaxDropDownChoicePanel<>(
+            AjaxTextFieldPanel recipientAttrName = new AjaxTextFieldPanel(
                     "recipientAttrName", new ResourceModel("recipientAttrName", "recipientAttrName").getObject(),
                     new PropertyModel<String>(notificationTO, "recipientAttrName"));
-            recipientAttrName.setChoices(getSchemaNames(recipientAttrType.getModelObject()));
+            recipientAttrName.setChoices(getSchemaNames());
             recipientAttrName.addRequiredLabel();
+            recipientAttrName.setTitle(getString("intAttrNameInfo.help")
+                    + "<div style=\"font-size: 10px;\">"
+                    + "<code>groups[groupName].attribute</code>\n"
+                    + "<code>anyObjects[anyObjectName].attribute</code>\n"
+                    + "<code>memberships[groupName].attribute</code>\n"
+                    + "</div>", true);
             add(recipientAttrName);
 
-            recipientAttrType.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                private static final long serialVersionUID = -1107858522700306810L;
-
-                @Override
-                protected void onUpdate(final AjaxRequestTarget target) {
-                    recipientAttrName.setChoices(getSchemaNames(recipientAttrType.getModelObject()));
-                    target.add(recipientAttrName);
-                }
-            });
-
-            final AjaxDropDownChoicePanel<String> template = new AjaxDropDownChoicePanel<>(
+            AjaxDropDownChoicePanel<String> template = new AjaxDropDownChoicePanel<>(
                     "template", getString("template"),
                     new PropertyModel<String>(notificationTO, "template"));
             template.setChoices(CollectionUtils.collect(
@@ -177,7 +159,7 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
             template.addRequiredLabel();
             add(template);
 
-            final AjaxDropDownChoicePanel<TraceLevel> traceLevel = new AjaxDropDownChoicePanel<>(
+            AjaxDropDownChoicePanel<TraceLevel> traceLevel = new AjaxDropDownChoicePanel<>(
                     "traceLevel", getString("traceLevel"),
                     new PropertyModel<TraceLevel>(notificationTO, "traceLevel"));
             traceLevel.setChoices(Arrays.asList(TraceLevel.values()));
@@ -228,7 +210,7 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
             super(id, model);
             setOutputMarkupId(true);
 
-            final List<String> anyTypeTOs = CollectionUtils.collect(
+            List<String> anyTypeTOs = CollectionUtils.collect(
                     new AnyTypeRestClient().list(),
                     EntityTOUtils.<AnyTypeTO>keyTransformer(), new ArrayList<String>());
 
@@ -289,22 +271,24 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
 
         private AbstractSearchPanel.Builder<?> getClauseBuilder(
                 final String type, final ListModel<SearchClause> clauseModel) {
+
             AbstractSearchPanel.Builder<?> clause;
 
             switch (type) {
                 case "USER":
                     clause = new UserSearchPanel.Builder(clauseModel);
                     break;
+
                 case "GROUP":
                     clause = new GroupSearchPanel.Builder(clauseModel);
                     break;
+
                 default:
                     clause = new AnyObjectSearchPanel.Builder(type, clauseModel);
-                    break;
             }
+
             return clause;
         }
-
     }
 
     public class Abouts extends WizardStep {
@@ -389,40 +373,21 @@ public class NotificationWizardBuilder extends AjaxWizardBuilder<NotificationWra
 
     }
 
-    private List<String> getSchemaNames(final IntMappingType type) {
-        final List<String> result;
-
-        if (type == null) {
-            result = Collections.<String>emptyList();
-        } else {
-            switch (type) {
-                case UserPlainSchema:
-                    result = CollectionUtils.collect(
-                            schemaRestClient.<PlainSchemaTO>getSchemas(SchemaType.PLAIN, AnyTypeKind.USER.name()),
-                            EntityTOUtils.<PlainSchemaTO>keyTransformer(), new ArrayList<String>());
-                    break;
-
-                case UserDerivedSchema:
-                    result = CollectionUtils.collect(
-                            schemaRestClient.<DerSchemaTO>getSchemas(SchemaType.DERIVED, AnyTypeKind.USER.name()),
-                            EntityTOUtils.<DerSchemaTO>keyTransformer(), new ArrayList<String>());
-                    break;
-
-                case UserVirtualSchema:
-                    result = CollectionUtils.collect(
-                            schemaRestClient.<VirSchemaTO>getSchemas(SchemaType.VIRTUAL, AnyTypeKind.USER.name()),
-                            EntityTOUtils.<VirSchemaTO>keyTransformer(), new ArrayList<String>());
-                    break;
-
-                case Username:
-                    result = Collections.singletonList("Username");
-                    break;
-
-                default:
-                    result = Collections.<String>emptyList();
-            }
-        }
-
+    private List<String> getSchemaNames() {
+        List<String> result = new ArrayList<>();
+        result.add("username");
+
+        CollectionUtils.collect(
+                schemaRestClient.<PlainSchemaTO>getSchemas(SchemaType.PLAIN, AnyTypeKind.USER.name()),
+                EntityTOUtils.<PlainSchemaTO>keyTransformer(), result);
+        CollectionUtils.collect(
+                schemaRestClient.<DerSchemaTO>getSchemas(SchemaType.DERIVED, AnyTypeKind.USER.name()),
+                EntityTOUtils.<DerSchemaTO>keyTransformer(), result);
+        CollectionUtils.collect(
+                schemaRestClient.<VirSchemaTO>getSchemas(SchemaType.VIRTUAL, AnyTypeKind.USER.name()),
+                EntityTOUtils.<VirSchemaTO>keyTransformer(), result);
+
+        Collections.sort(result);
         return result;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
index fe09351..6da40f0 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/BeanPanel.java
@@ -50,8 +50,6 @@ import org.apache.syncope.common.lib.report.Schema;
 import org.apache.syncope.common.lib.report.SearchCondition;
 import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.list.ListItem;
@@ -102,7 +100,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
 
             @Override
             protected List<String> load() {
-                List<String> result = new ArrayList<String>();
+                List<String> result = new ArrayList<>();
 
                 if (BeanPanel.this.getDefaultModelObject() != null) {
                     for (Field field : BeanPanel.this.getDefaultModelObject().getClass().getDeclaredFields()) {
@@ -160,18 +158,18 @@ public class BeanPanel<T extends Serializable> extends Panel {
                     switch (scondAnnot.type()) {
                         case "USER":
                             panel = new UserSearchPanel.Builder(
-                                    new ListModel<SearchClause>(clauses)).required(false).build("value");
+                                    new ListModel<>(clauses)).required(false).build("value");
                             builder = SyncopeClient.getUserSearchConditionBuilder();
                             break;
                         case "GROUP":
                             panel = new GroupSearchPanel.Builder(
-                                    new ListModel<SearchClause>(clauses)).required(false).build("value");
+                                    new ListModel<>(clauses)).required(false).build("value");
                             builder = SyncopeClient.getGroupSearchConditionBuilder();
                             break;
                         default:
                             panel = new AnyObjectSearchPanel.Builder(
                                     scondAnnot.type(),
-                                    new ListModel<SearchClause>(clauses)).required(false).build("value");
+                                    new ListModel<>(clauses)).required(false).build("value");
                             builder = SyncopeClient.getAnyObjectSearchConditionBuilder(null);
                     }
 
@@ -190,51 +188,21 @@ public class BeanPanel<T extends Serializable> extends Panel {
 
                         final List<AbstractSchemaTO> choices = new ArrayList<>();
 
-                        for (IntMappingType type : schemaAnnot.type()) {
+                        for (SchemaType type : schemaAnnot.type()) {
                             switch (type) {
-                                case UserPlainSchema:
+                                case PLAIN:
                                     choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.PLAIN, AnyTypeKind.USER));
+                                            schemaRestClient.getSchemas(SchemaType.PLAIN, schemaAnnot.anyTypeKind()));
                                     break;
 
-                                case UserDerivedSchema:
+                                case DERIVED:
                                     choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.DERIVED, AnyTypeKind.USER));
+                                            schemaRestClient.getSchemas(SchemaType.DERIVED, schemaAnnot.anyTypeKind()));
                                     break;
 
-                                case UserVirtualSchema:
+                                case VIRTUAL:
                                     choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.VIRTUAL, AnyTypeKind.USER));
-                                    break;
-
-                                case GroupPlainSchema:
-                                    choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.PLAIN, AnyTypeKind.GROUP));
-                                    break;
-
-                                case GroupDerivedSchema:
-                                    choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.DERIVED, AnyTypeKind.GROUP));
-                                    break;
-
-                                case GroupVirtualSchema:
-                                    choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.VIRTUAL, AnyTypeKind.GROUP));
-                                    break;
-
-                                case AnyObjectPlainSchema:
-                                    choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.PLAIN, AnyTypeKind.ANY_OBJECT));
-                                    break;
-
-                                case AnyObjectDerivedSchema:
-                                    choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.DERIVED, AnyTypeKind.ANY_OBJECT));
-                                    break;
-
-                                case AnyObjectVirtualSchema:
-                                    choices.addAll(
-                                            schemaRestClient.getSchemas(SchemaType.VIRTUAL, AnyTypeKind.ANY_OBJECT));
+                                            schemaRestClient.getSchemas(SchemaType.VIRTUAL, schemaAnnot.anyTypeKind()));
                                     break;
 
                                 default:
@@ -244,7 +212,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
                         panel = new AjaxPalettePanel.Builder<String>().setName(fieldName).build(
                                 "value",
                                 new PropertyModel<List<String>>(bean.getObject(), fieldName),
-                                new ListModel<String>(
+                                new ListModel<>(
                                         CollectionUtils.collect(
                                                 choices, new Transformer<AbstractSchemaTO, String>() {
 
@@ -263,7 +231,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
                             ((List) wrapper.getPropertyValue(fieldName)).add(null);
                         }
 
-                        panel = new MultiFieldPanel.Builder<String>(
+                        panel = new MultiFieldPanel.Builder<>(
                                 new PropertyModel<List<String>>(bean.getObject(), fieldName)).build(
                                 "value",
                                 fieldName,
@@ -287,7 +255,7 @@ public class BeanPanel<T extends Serializable> extends Panel {
         if (ClassUtils.isAssignable(Boolean.class, type)) {
             result = new AjaxCheckBoxPanel(id, fieldName, model);
         } else if (ClassUtils.isAssignable(Number.class, type)) {
-            result = new AjaxSpinnerFieldPanel.Builder<Number>().build(
+            result = new AjaxSpinnerFieldPanel.Builder<>().build(
                     id, fieldName, (Class<Number>) ClassUtils.resolvePrimitiveIfNecessary(type), model);
         } else if (Date.class.equals(type)) {
             result = new DateTimeFieldPanel(id, fieldName, model, SyncopeConstants.DEFAULT_DATE_PATTERN);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
index 53e2c69..45ddb35 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ConnObjectListViewPanel.java
@@ -68,7 +68,7 @@ public abstract class ConnObjectListViewPanel extends Panel {
 
             @Override
             protected Component getValueComponent(final String key, final ConnObjectTO bean) {
-                final AttrTO attrTO = IterableUtils.find(bean.getPlainAttrs(), new Predicate<AttrTO>() {
+                final AttrTO attrTO = IterableUtils.find(bean.getAttrs(), new Predicate<AttrTO>() {
 
                     @Override
                     public boolean evaluate(final AttrTO object) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
index a6ad2eb..d38091b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
@@ -54,6 +54,7 @@ public class SchemaRestClient extends BaseRestClient {
                     classes.addAll(type.getClasses());
                 }
                 break;
+
             default:
                 for (AnyTypeTO anyTypeTO : getService(AnyTypeService.class).list()) {
                     if (anyTypeTO.getKind() != AnyTypeKind.USER && anyTypeTO.getKind() != AnyTypeKind.GROUP) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 401f8e0..8935ef3 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
@@ -32,7 +32,6 @@ import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.GroupableTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
@@ -41,6 +40,7 @@ import org.apache.wicket.markup.html.form.IChoiceRenderer;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.util.ListModel;
 import org.apache.wicket.util.lang.Args;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 
 public class Groups extends WizardStep {
 
@@ -83,8 +83,8 @@ public class Groups extends WizardStep {
                     }
                 });
 
-        add(builder.setAllowOrder(true).withFilter().build(
-                "groups", new ListModel<>(GroupableTO.class.cast(anyTO).getMemberships()),
+        add(builder.setAllowOrder(true).withFilter().build("groups",
+                new ListModel<>(GroupableRelatableTO.class.cast(anyTO).getMemberships()),
                 new AjaxPalettePanel.Builder.Query<MembershipTO>() {
 
             private static final long serialVersionUID = -7223078772249308813L;
@@ -116,9 +116,8 @@ public class Groups extends WizardStep {
         for (GroupTO group : allGroups) {
             allGroupsByKey.put(group.getKey(), group);
         }
-        add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).build(
-                "dyngroups",
-                new ListModel<>(CollectionUtils.collect(GroupableTO.class.cast(anyTO).getDynGroups(),
+        add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).build("dyngroups",
+                new ListModel<>(CollectionUtils.collect(GroupableRelatableTO.class.cast(anyTO).getDynGroups(),
                         new Transformer<String, String>() {
 
                     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
index e41cdea..20f054c 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/Relationships.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.client.console.wizards.any;
 
-import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -55,7 +54,7 @@ import org.apache.syncope.common.lib.EntityTOUtils;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
-import org.apache.syncope.common.lib.to.RelatableTO;
+import org.apache.syncope.common.lib.to.GroupableRelatableTO;
 import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.RelationshipTypeTO;
 import org.apache.syncope.common.lib.types.AnyEntitlement;
@@ -135,8 +134,7 @@ public class Relationships extends WizardStep {
                                             public void onClick(
                                                     final AjaxRequestTarget target, final RelationshipTO modelObject) {
                                                 removeRelationships(relationships, modelObject);
-                                                send(Relationships.this, Broadcast.DEPTH, 
-                                                        new ListViewReload<Serializable>(target));
+                                                send(Relationships.this, Broadcast.DEPTH, new ListViewReload<>(target));
                                             }
                                         }, ActionType.DELETE, AnyEntitlement.UPDATE.getFor(anyTO.getType())).
                                         build(panelId);
@@ -175,8 +173,8 @@ public class Relationships extends WizardStep {
     }
 
     private List<RelationshipTO> getCurrentRelationships() {
-        return anyTO instanceof RelatableTO
-                ? RelatableTO.class.cast(anyTO).getRelationships()
+        return anyTO instanceof GroupableRelatableTO
+                ? GroupableRelatableTO.class.cast(anyTO).getRelationships()
                 : Collections.<RelationshipTO>emptyList();
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
index 06ea7c8..de90660 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
@@ -18,17 +18,24 @@
  */
 package org.apache.syncope.client.console.wizards.resources;
 
+import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverBehavior;
+import de.agilecoders.wicket.core.markup.html.bootstrap.components.PopoverConfig;
 import de.agilecoders.wicket.core.markup.html.bootstrap.components.TooltipConfig;
 import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
+import org.apache.commons.lang3.ClassUtils;
 import org.apache.syncope.client.console.commons.ConnIdSpecialAttributeName;
 import org.apache.syncope.client.console.commons.Constants;
 import org.apache.syncope.client.console.rest.AnyTypeClassRestClient;
@@ -38,22 +45,23 @@ import org.apache.syncope.client.console.wicket.ajax.form.IndicatorAjaxFormCompo
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxCheckBoxPanel;
-import org.apache.syncope.client.console.wicket.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.client.console.wicket.markup.html.form.MappingPurposePanel;
 import org.apache.syncope.client.console.widgets.JEXLTransformerWidget;
 import org.apache.syncope.client.console.widgets.MappingItemTransformerWidget;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.ConnIdObjectClassTO;
 import org.apache.syncope.common.lib.to.ConnInstanceTO;
+import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.MappingItemTO;
 import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.ProvisionTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -76,10 +84,32 @@ public class ResourceMappingPanel extends Panel {
 
     private static final long serialVersionUID = -7982691107029848579L;
 
-    /**
-     * Mapping field style sheet.
-     */
-    private static final String DEF_FIELD_STYLE = "";
+    private static final Set<String> USER_FIELD_NAMES = new HashSet<>();
+
+    private static final Set<String> GROUP_FIELD_NAMES = new HashSet<>();
+
+    private static final Set<String> ANY_OBJECT_FIELD_NAMES = new HashSet<>();
+
+    static {
+        initFieldNames(UserTO.class, USER_FIELD_NAMES);
+        initFieldNames(GroupTO.class, GROUP_FIELD_NAMES);
+        initFieldNames(AnyObjectTO.class, ANY_OBJECT_FIELD_NAMES);
+    }
+
+    private static void initFieldNames(final Class<?> entityClass, final Set<String> keys) {
+        List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
+        classes.add(entityClass);
+        for (Class<?> clazz : classes) {
+            for (Field field : clazz.getDeclaredFields()) {
+                if (!Modifier.isStatic(field.getModifiers())
+                        && !Collection.class.isAssignableFrom(field.getType())
+                        && !Map.class.isAssignableFrom(field.getType())) {
+
+                    keys.add(field.getName());
+                }
+            }
+        }
+    }
 
     /**
      * Any type rest client.
@@ -157,6 +187,24 @@ public class ResourceMappingPanel extends Panel {
         this.mappingContainer.setVisible(provisionTO != null);
         add(this.mappingContainer);
 
+        mappingContainer.add(new Label("intAttrNameInfo", Model.of()).add(new PopoverBehavior(
+                Model.<String>of(),
+                Model.of(getString("intAttrNameInfo.help")
+                        + "<div style=\"font-size: 10px;\">"
+                        + "<code>groups[groupName].attribute</code>\n"
+                        + "<code>anyObjects[anyObjectName].attribute</code>\n"
+                        + "<code>memberships[groupName].attribute</code>\n"
+                        + "</div>"),
+                new PopoverConfig().withHtml(true).withPlacement(TooltipConfig.Placement.bottom)) {
+
+            private static final long serialVersionUID = -7867802555691605021L;
+
+            @Override
+            protected String createRelAttribute() {
+                return "intAttrNameInfo";
+            }
+        }));
+
         mappingContainer.add(Constants.getJEXLPopover(this, TooltipConfig.Placement.bottom));
 
         passwordLabel = new Label("passwordLabel", new ResourceModel("password"));
@@ -216,77 +264,32 @@ public class ResourceMappingPanel extends Panel {
                     mapItem.setPurpose(MappingPurpose.BOTH);
                 }
 
-                AnyTypeKind entity = null;
-                if (provisionTO.getAnyType().equals(AnyTypeKind.GROUP.name())) {
-                    // support for clone
-                    entity = AnyTypeKind.GROUP;
-                } else if (mapItem.getIntMappingType() != null) {
-                    entity = mapItem.getIntMappingType().getAnyTypeKind();
-                }
-
-                // it will happen just in case of clone to create a new mapping for group object
-                if (mapItem.getIntMappingType() != null && mapItem.getIntMappingType().getAnyTypeKind() != entity) {
-                    mapItem.setIntMappingType(null);
-                    mapItem.setIntAttrName(null);
-                }
-
-                //--------------------------------
-                // Entity
-                // -------------------------------
-                final AjaxDropDownChoicePanel<AnyTypeKind> entitiesPanel = new AjaxDropDownChoicePanel<>(
-                        "entities",
-                        new ResourceModel("entities", "entities").getObject(),
-                        new Model<>(entity));
-
-                entitiesPanel.hideLabel();
-                entitiesPanel.setChoices(provisionTO.getAnyType().equals(AnyTypeKind.GROUP.name())
-                        ? Collections.<AnyTypeKind>singletonList(AnyTypeKind.GROUP)
-                        : Arrays.asList(AnyTypeKind.values()));
-
-                entitiesPanel.setStyleSheet(false, DEF_FIELD_STYLE);
-                item.add(entitiesPanel);
-                // -------------------------------
-
-                //--------------------------------
-                // Internal attribute type
-                // -------------------------------
-                final List<IntMappingType> attrTypes = new ArrayList<>(getAttributeTypes(entity));
-                final AjaxDropDownChoicePanel<IntMappingType> intMappingTypes = new AjaxDropDownChoicePanel<>(
-                        "intMappingTypes",
-                        new ResourceModel("intMappingTypes", "intMappingTypes").getObject(),
-                        new PropertyModel<IntMappingType>(mapItem, "intMappingType"),
-                        false);
-                intMappingTypes.setNullValid(true).setRequired(true).hideLabel();
-                intMappingTypes.setChoices(attrTypes);
-                item.add(intMappingTypes);
-                // -------------------------------
-
                 //--------------------------------
                 // Internal attribute
                 // -------------------------------
-                final AjaxTextFieldPanel intAttrNames = new AjaxTextFieldPanel(
-                        "intAttrNames",
-                        getString("intAttrNames"),
+                AjaxTextFieldPanel intAttrName = new AjaxTextFieldPanel(
+                        "intAttrName",
+                        getString("intAttrName"),
                         new PropertyModel<String>(mapItem, "intAttrName"),
                         false);
-                intAttrNames.setChoices(Collections.<String>emptyList());
-                intAttrNames.setRequired(true).hideLabel();
-                item.add(intAttrNames);
+                intAttrName.setChoices(Collections.<String>emptyList());
+                intAttrName.setRequired(true).hideLabel();
+                item.add(intAttrName);
                 // -------------------------------
 
                 //--------------------------------
                 // External attribute
                 // -------------------------------
-                final AjaxTextFieldPanel extAttrNames = new AjaxTextFieldPanel(
+                final AjaxTextFieldPanel extAttrName = new AjaxTextFieldPanel(
                         "extAttrName",
-                        new ResourceModel("extAttrNames", "extAttrNames").getObject(),
+                        getString("extAttrName"),
                         new PropertyModel<String>(mapItem, "extAttrName"));
-                extAttrNames.setChoices(getExtAttrNames(resourceTO.getConnector(), resourceTO.getConfOverride()));
+                extAttrName.setChoices(getExtAttrNames(resourceTO.getConnector(), resourceTO.getConfOverride()));
 
                 boolean required = !mapItem.isPassword();
-                extAttrNames.setRequired(required).hideLabel();
-                extAttrNames.setEnabled(required);
-                item.add(extAttrNames);
+                extAttrName.setRequired(required).hideLabel();
+                extAttrName.setEnabled(required);
+                item.add(extAttrName);
                 // -------------------------------
 
                 //--------------------------------
@@ -339,7 +342,7 @@ public class ResourceMappingPanel extends Panel {
                 //--------------------------------
                 // Purpose
                 // -------------------------------
-                final WebMarkupContainer purpose = new WebMarkupContainer("purpose");
+                WebMarkupContainer purpose = new WebMarkupContainer("purpose");
                 purpose.setOutputMarkupId(Boolean.TRUE);
 
                 final MappingPurposePanel panel = new MappingPurposePanel(
@@ -376,38 +379,7 @@ public class ResourceMappingPanel extends Panel {
                 item.add(actions.build("toRemove"));
                 // -------------------------------
 
-                entitiesPanel.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                    private static final long serialVersionUID = -1107858522700306810L;
-
-                    @Override
-                    protected void onUpdate(final AjaxRequestTarget target) {
-                        attrTypes.clear();
-                        attrTypes.addAll(getAttributeTypes(entitiesPanel.getModelObject()));
-                        intMappingTypes.setChoices(attrTypes);
-
-                        intAttrNames.setChoices(Collections.<String>emptyList());
-
-                        target.add(intMappingTypes);
-                        target.add(intAttrNames);
-                    }
-                });
-
-                intMappingTypes.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
-
-                    private static final long serialVersionUID = -1107858522700306810L;
-
-                    @Override
-                    protected void onUpdate(final AjaxRequestTarget target) {
-                        setAttrNames(intMappingTypes.getModelObject(), intAttrNames);
-                        target.add(intAttrNames);
-
-                        setConnObjectKey(intMappingTypes.getModelObject(), connObjectKey, password);
-                        target.add(connObjectKey);
-                    }
-                });
-
-                intAttrNames.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
+                intAttrName.getField().add(new IndicatorAjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 
                     private static final long serialVersionUID = -1107858522700306810L;
 
@@ -439,28 +411,28 @@ public class ResourceMappingPanel extends Panel {
 
                     @Override
                     protected void onUpdate(final AjaxRequestTarget target) {
-                        extAttrNames.setEnabled(!mapItem.isConnObjectKey() && !password.getModelObject());
-                        extAttrNames.setModelObject(password.getModelObject()
-                                ? ConnIdSpecialAttributeName.PASSWORD : extAttrNames.getModelObject());
-                        extAttrNames.setRequired(!password.getModelObject());
-                        target.add(extAttrNames);
+                        extAttrName.setEnabled(!mapItem.isConnObjectKey() && !password.getModelObject());
+                        extAttrName.setModelObject(password.getModelObject()
+                                ? ConnIdSpecialAttributeName.PASSWORD : extAttrName.getModelObject());
+                        extAttrName.setRequired(!password.getModelObject());
+                        target.add(extAttrName);
 
-                        setConnObjectKey(intMappingTypes.getModelObject(), connObjectKey, password);
+                        setConnObjectKey(connObjectKey, password);
                         target.add(connObjectKey);
                     }
                 });
 
-                setAttrNames(mapItem.getIntMappingType(), intAttrNames);
-                setConnObjectKey(mapItem.getIntMappingType(), connObjectKey, password);
+                setAttrNames(intAttrName);
+                setConnObjectKey(connObjectKey, password);
 
                 if (!AnyTypeKind.USER.name().equals(provisionTO.getAnyType())) {
                     password.setVisible(false);
 
                     // Changes required by clone ....
-                    extAttrNames.setEnabled(!mapItem.isConnObjectKey());
+                    extAttrName.setEnabled(!mapItem.isConnObjectKey());
                     if (mapItem.isPassword()) {
                         // re-enable if and only if cloned objec mapping item was a password
-                        intAttrNames.setEnabled(true);
+                        intAttrName.setEnabled(true);
                     }
                     mapItem.setPassword(false);
                 }
@@ -517,118 +489,55 @@ public class ResourceMappingPanel extends Panel {
      * @param type attribute type.
      * @param toBeUpdated drop down choice to be updated.
      */
-    private void setAttrNames(final IntMappingType type, final AjaxTextFieldPanel toBeUpdated) {
+    private void setAttrNames(final AjaxTextFieldPanel toBeUpdated) {
         toBeUpdated.setRequired(true);
         toBeUpdated.setEnabled(true);
 
-        if (type == null || type.getAnyTypeKind() == null) {
-            toBeUpdated.setChoices(Collections.<String>emptyList());
-        } else {
-            AnyTypeTO anyTypeTO = anyTypeRestClient.read(provisionTO.getAnyType());
+        AnyTypeTO anyTypeTO = anyTypeRestClient.read(provisionTO.getAnyType());
 
-            List<AnyTypeClassTO> anyTypeClassTOs = new ArrayList<>();
-            anyTypeClassTOs.addAll(anyTypeClassRestClient.list(anyTypeTO.getClasses()));
-            for (String auxClass : provisionTO.getAuxClasses()) {
-                anyTypeClassTOs.add(anyTypeClassRestClient.read(auxClass));
-            }
+        List<AnyTypeClassTO> anyTypeClassTOs = new ArrayList<>();
+        anyTypeClassTOs.addAll(anyTypeClassRestClient.list(anyTypeTO.getClasses()));
+        for (String auxClass : provisionTO.getAuxClasses()) {
+            anyTypeClassTOs.add(anyTypeClassRestClient.read(auxClass));
+        }
 
-            List<String> choices;
-            switch (type) {
-                case UserPlainSchema:
-                case GroupPlainSchema:
-                case AnyObjectPlainSchema:
-                    final Set<String> plains = new HashSet<>();
-                    for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) {
-                        plains.addAll(anyTypeClassTO.getPlainSchemas());
-                    }
-                    choices = new ArrayList<>(plains);
-                    break;
-
-                case UserDerivedSchema:
-                case GroupDerivedSchema:
-                case AnyObjectDerivedSchema:
-                    final Set<String> deriveds = new HashSet<>();
-                    for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) {
-                        deriveds.addAll(anyTypeClassTO.getDerSchemas());
-                    }
-                    choices = new ArrayList<>(deriveds);
-                    break;
-
-                case UserVirtualSchema:
-                case GroupVirtualSchema:
-                case AnyObjectVirtualSchema:
-                    final Set<String> virtuals = new HashSet<>();
-                    for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) {
-                        virtuals.addAll(anyTypeClassTO.getVirSchemas());
-                    }
-                    choices = new ArrayList<>(virtuals);
-                    break;
-
-                case UserKey:
-                case Password:
-                case Username:
-                case GroupKey:
-                case GroupName:
-                case AnyObjectKey:
-                case AnyObjectName:
-                default:
-                    toBeUpdated.setRequired(false);
-                    toBeUpdated.setEnabled(false);
-                    choices = Collections.<String>emptyList();
-            }
-            Collections.sort(choices);
-            toBeUpdated.setChoices(choices);
+        List<String> choices = new ArrayList<>();
+
+        switch (provisionTO.getAnyType()) {
+            case "USER":
+                choices.addAll(USER_FIELD_NAMES);
+                break;
+
+            case "GROUP":
+                choices.addAll(GROUP_FIELD_NAMES);
+                break;
+
+            default:
+                choices.addAll(ANY_OBJECT_FIELD_NAMES);
+        }
+
+        for (AnyTypeClassTO anyTypeClassTO : anyTypeClassTOs) {
+            choices.addAll(anyTypeClassTO.getPlainSchemas());
+            choices.addAll(anyTypeClassTO.getDerSchemas());
+            choices.addAll(anyTypeClassTO.getVirSchemas());
         }
+
+        Collections.sort(choices);
+        toBeUpdated.setChoices(choices);
     }
 
     /**
      * Enable/Disable connObjectKey checkbox.
      *
-     * @param type attribute type.
      * @param connObjectKey connObjectKey checkbox.
      * @param password password checkbox.
      */
-    private void setConnObjectKey(
-            final IntMappingType type, final AjaxCheckBoxPanel connObjectKey, final AjaxCheckBoxPanel password) {
-
-        if (type != null && type.getAnyTypeKind() != null) {
-            switch (type) {
-                case UserVirtualSchema:
-                case GroupVirtualSchema:
-                case AnyObjectVirtualSchema:
-                // Virtual connObjectKey is not permitted
-                case Password:
-                    // connObjectKey cannot be derived from password.
-                    connObjectKey.setReadOnly(true);
-                    connObjectKey.setModelObject(false);
-                    break;
-
-                default:
-                    if (password.getModelObject()) {
-                        connObjectKey.setReadOnly(true);
-                        connObjectKey.setModelObject(false);
-                    } else {
-                        connObjectKey.setReadOnly(false);
-                    }
-            }
-        }
-    }
-
-    /**
-     * Get all attribute types from a selected attribute type.
-     *
-     * @param kind entity.
-     * @return all attribute types.
-     */
-    private List<IntMappingType> getAttributeTypes(final AnyTypeKind kind) {
-        final List<IntMappingType> res = new ArrayList<>();
-
-        if (kind != null) {
-            res.addAll(IntMappingType.getAttributeTypes(kind));
+    private void setConnObjectKey(final AjaxCheckBoxPanel connObjectKey, final AjaxCheckBoxPanel password) {
+        if (password.getModelObject()) {
+            connObjectKey.setReadOnly(true);
+            connObjectKey.setModelObject(false);
+        } else {
+            connObjectKey.setReadOnly(false);
         }
-
-        Collections.sort(res);
-
-        return res;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
index 0214cf6..c8f42ad 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication.properties
@@ -73,3 +73,4 @@ OrderByLink.CSS.none=sorting
 entitlements=Entitlements
 audit=Audit
 connectors.confirm.reload=This request is potentially dangerous for running operations, continue?
+intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships  (if applicable); for example:

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
index abc0782..a17d3d8 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_it.properties
@@ -72,3 +72,4 @@ OrderByLink.CSS.none=sorting
 entitlements=Entitlement
 audit=Audit
 connectors.confirm.reload=Questa richiesta \u00e8 potenzialmente dannosa per le operazioni in corso, proseguire?
+intAttrNameInfo.help=Oltre agli attributi auto-completati, \u00e8 possibile fare riferimento anche a gruppi, any object e membership (se applicabile); ad esempio:

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
index 9214454..b0abf0d 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_pt_BR.properties
@@ -72,3 +72,4 @@ OrderByLink.CSS.none=sorting
 entitlements=Entitlement
 audit=Audit
 connectors.confirm.reload=Esta requis\u00e7\u00e3o \u00e9 potencialmente perigosa para opera\u00e7\u00f5es em execu\u00e7\u00e3o, prosseguir?
+intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships  (if applicable); for example:

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties
index 0b76c8a..2b03a61 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/SyncopeConsoleApplication_ru.properties
@@ -123,3 +123,4 @@ OrderByLink.CSS.none=\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043
 entitlements=\u041f\u043e\u043b\u043d\u043e\u043c\u043e\u0447\u0438\u044f
 audit=Audit
 connectors.confirm.reload=This request is potentially dangerous for running operations, continue?
+intAttrNameInfo.help=Besides auto-completed attributes, you can also refer to groups, any objects or memberships  (if applicable); for example:

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.html b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.html
index 1ceee21..05ce8cf 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.html
@@ -27,9 +27,6 @@ under the License.
         <span wicket:id="subject">[subject]</span>
       </div>
       <div class="form-group">
-        <span wicket:id="recipientAttrType">[recipientAttrType]</span>
-      </div>
-      <div class="form-group">
         <span wicket:id="recipientAttrName">[recipientAttrName]</span>
       </div>
       <div class="form-group">

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.properties
index 4021981..72f0e85 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details.properties
@@ -18,6 +18,5 @@ subject=Subject
 sender=Sender
 template=Template
 traceLevel=Trace level
-recipientAttrType=Recipients e-mail attribute type
-recipientAttrName=Recipients e-mail attribute schema
+recipientAttrName=Recipients e-mail attribute
 isActive=Enabled

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_it.properties
index 6b7a1ca..85ee48f 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_it.properties
@@ -18,6 +18,5 @@ subject=Oggetto
 sender=Mittente
 template=Modello
 traceLevel=Livello di tracciamento
-recipientAttrType=Tipo attributo e-mail destinatari
-recipientAttrName=Schema attributo e-mail destinatari
+recipientAttrName=Attributo e-mail destinatari
 isActive=Abilitata

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_pt_BR.properties
index d2ffaf6..7838db0 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_pt_BR.properties
@@ -18,6 +18,5 @@ subject=Assunto
 sender=Remetente
 template=Template
 traceLevel=N\u00edvel de Trace
-recipientAttrType=Tipo de atributo de destinat\u00e1rio de email.
-recipientAttrName=Destinat\u00e1rios de e-mail para atributos de esquema
+recipientAttrName=Destinat\u00e1rios de e-mail para atributos
 isActive=Ativada

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_ru.properties
index 48aa402..75a3fd8 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Details_ru.properties
@@ -16,17 +16,15 @@
 # under the License.
 #
 #
-# subject=\u0422\u0435\u043c\u0430
+# subject=\u00d0\u00a2\u00d0\u00b5\u00d0\u00bc\u00d0\u00b0
 subject=\u0422\u0435\u043c\u0430
-# sender=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c
+# sender=\u00d0\u009e\u00d1\u0082\u00d0\u00bf\u00d1\u0080\u00d0\u00b0\u00d0\u00b2\u00d0\u00b8\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c
 sender=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c
-# template=\u0428\u0430\u0431\u043b\u043e\u043d
+# template=\u00d0\u00a8\u00d0\u00b0\u00d0\u00b1\u00d0\u00bb\u00d0\u00be\u00d0\u00bd
 template=\u0428\u0430\u0431\u043b\u043e\u043d
-# traceLevel=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f
+# traceLevel=\u00d0\u00a3\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b5\u00d0\u00bd\u00d1\u008c \u00d0\u00bb\u00d0\u00be\u00d0\u00b3\u00d0\u00b8\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 traceLevel=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f
-# recipientAttrType=\u0422\u0438\u043f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-recipientAttrType=\u0422\u0438\u043f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
+# recipientAttrName=\u00d0\u009d\u00d0\u00b0\u00d0\u00b8\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00b0\u00d1\u0082\u00d1\u0080\u00d0\u00b8\u00d0\u00b1\u00d1\u0083\u00d1\u0082\u00d0\u00b0 \u00d1\u0081 \u00d0\u00b0\u00d0\u00b4\u00d1\u0080\u00d0\u00b5\u00d1\u0081\u00d0\u00be\u00d0\u00bc \u00d1\u008d\u00d0\u00bb\u00d0\u00b5\u00d0\u00ba\u00d1\u0082\u00d1\u0080\u00d0\u00be\u00d0\u00bd\u00d0\u00bd\u00d0\u00be\u00d0\u00b9 \u00d0\u00bf\u00d0\u00be\u00d1\u0087\u00d1\u0082\u00d1\u008b \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# isActive=\u0410\u043a\u0442\u0438\u0432\u043d\u043e
+# isActive=\u00d0\u0090\u00d0\u00ba\u00d1\u0082\u00d0\u00b8\u00d0\u00b2\u00d0\u00bd\u00d0\u00be
 isActive=\u0410\u043a\u0442\u0438\u0432\u043d\u043e

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events.properties
index 690ae7e..879b380 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events.properties
@@ -25,8 +25,6 @@ about=About
 events=Events
 recipients=Recipients
 selfAsRecipient=Include users matching About
-recipientAttrType=Recipients e-mail attribute type
-recipientAttrName=Recipients e-mail attribute schema
 checkRecipients=Search recipients
 checkAbout=All
 userFilter=User filter

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_it.properties
index db3bb59..ae80bb2 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_it.properties
@@ -25,8 +25,6 @@ about=Soggetti
 events=Eventi
 recipients=Destinatari
 selfAsRecipient=Includi i soggetti
-recipientAttrType=Tipo attributo e-mail destinatari
-recipientAttrName=Schema attributo e-mail destinatari
 checkRecipients=Cerca i destinatari
 checkAbout=Tutto
 userFilter=Filtro utenti

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_pt_BR.properties
index 9b13d12..5c70e66 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_pt_BR.properties
@@ -25,8 +25,6 @@ about=Sobre
 events=Eventos
 recipients=Destinat\u00e1rios
 selfAsRecipient=Incluir usu\u00e1rios relacionados Sobre
-recipientAttrType=Tipo de atributo de destinat\u00e1rio de email.
-recipientAttrName=Destinat\u00e1rios de e-mail para atributos de esquema
 checkRecipients=Buscar Destinat\u00e1rios
 checkAbout=Todos
 userFilter=Filtro usu\u00e1rio

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_ru.properties
index 6b08f78..2d461d5 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/notifications/NotificationWizardBuilder$Events_ru.properties
@@ -15,55 +15,51 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# title=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
+# title=\u00d0\u0098\u00d0\u00b7\u00d0\u00bc\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d1\u0083\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 title=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
-# submit=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
+# submit=\u00d0\u00a1\u00d0\u00be\u00d1\u0085\u00d1\u0080\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d1\u0082\u00d1\u008c
 submit=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c
-# subject=\u0422\u0435\u043c\u0430
+# subject=\u00d0\u00a2\u00d0\u00b5\u00d0\u00bc\u00d0\u00b0
 subject=\u0422\u0435\u043c\u0430
-# sender=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c
+# sender=\u00d0\u009e\u00d1\u0082\u00d0\u00bf\u00d1\u0080\u00d0\u00b0\u00d0\u00b2\u00d0\u00b8\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c
 sender=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c
-# template=\u0428\u0430\u0431\u043b\u043e\u043d
+# template=\u00d0\u00a8\u00d0\u00b0\u00d0\u00b1\u00d0\u00bb\u00d0\u00be\u00d0\u00bd
 template=\u0428\u0430\u0431\u043b\u043e\u043d
-# traceLevel=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f
+# traceLevel=\u00d0\u00a3\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b5\u00d0\u00bd\u00d1\u008c \u00d0\u00bb\u00d0\u00be\u00d0\u00b3\u00d0\u00b8\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 traceLevel=\u0423\u0440\u043e\u0432\u0435\u043d\u044c \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f
-# notification=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
+# notification=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 notification=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
-# about=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e
+# about=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00be
 about=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e
-# events=\u0421\u043e\u0431\u044b\u0442\u0438\u044f
+# events=\u00d0\u00a1\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d1\u008f
 events=\u0421\u043e\u0431\u044b\u0442\u0438\u044f
-# recipients=\u041f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0438
+# recipients=\u00d0\u009f\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b8
 recipients=\u041f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0438
-# selfAsRecipient=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
+# selfAsRecipient=\u00d0\u0092\u00d0\u00ba\u00d0\u00bb\u00d1\u008e\u00d1\u0087\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00b2 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b8 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9, \u00d0\u00be \u00d0\u00ba\u00d0\u00be\u00d1\u0082\u00d0\u00be\u00d1\u0080\u00d1\u008b\u00d1\u0085 \u00d1\u0080\u00d0\u00b0\u00d1\u0081\u00d1\u0081\u00d1\u008b\u00d0\u00bb\u00d0\u00b0\u00d0\u00b5\u00d1\u0082\u00d1\u0081\u00d1\u008f \u00d1\u0083\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 selfAsRecipient=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
-# recipientAttrType=\u0422\u0438\u043f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-recipientAttrType=\u0422\u0438\u043f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# checkRecipients=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
+# checkRecipients=\u00d0\u009f\u00d0\u00be\u00d0\u00b8\u00d1\u0081\u00d0\u00ba \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 checkRecipients=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# checkAbout=\u041e\u0431\u043e \u0432\u0441\u0451\u043c
+# checkAbout=\u00d0\u009e\u00d0\u00b1\u00d0\u00be \u00d0\u00b2\u00d1\u0081\u00d1\u0091\u00d0\u00bc
 checkAbout=\u041e\u0431\u043e \u0432\u0441\u0451\u043c
-# userFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userFilter=\u00d0\u00a4\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# userFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userFilterWarning=\u00d0\u009d\u00d0\u00b5 \u00d0\u00b8\u00d1\u0081\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d1\u0083\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# userNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userNotifications=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# userNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userNotificationsWarning=\u00d0\u009d\u00d0\u00b5 \u00d1\u0083\u00d1\u0081\u00d1\u0082\u00d0\u00b0\u00d0\u00bd\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b8\u00d0\u00b2\u00d0\u00b0\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00bb\u00d0\u00b0\u00d0\u00b6\u00d0\u00be\u00d0\u00ba, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# roleFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u043e\u043b\u0435\u0439
+# roleFilter=\u00d0\u00a4\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080 \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u043e\u043b\u0435\u0439
-# roleFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
+# roleFilterWarning=\u00d0\u009d\u00d0\u00b5 \u00d0\u00b8\u00d1\u0081\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d1\u0083\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
-# roleNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u043e\u043b\u0435\u0439
+# roleNotifications=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f \u00d0\u00bd\u00d0\u00b0 \u00d0\u00be\u00d1\u0081\u00d0\u00bd\u00d0\u00be\u00d0\u00b2\u00d0\u00b5 \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u043e\u043b\u0435\u0439
-# roleNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
+# roleNotificationsWarning=\u00d0\u009d\u00d0\u00b5 \u00d1\u0083\u00d1\u0081\u00d1\u0082\u00d0\u00b0\u00d0\u00bd\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b8\u00d0\u00b2\u00d0\u00b0\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00bb\u00d0\u00b0\u00d0\u00b6\u00d0\u00be\u00d0\u00ba, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
-# isActive=\u0410\u043a\u0442\u0438\u0432\u043d\u043e
+# isActive=\u00d0\u0090\u00d0\u00ba\u00d1\u0082\u00d0\u00b8\u00d0\u00b2\u00d0\u00bd\u00d0\u00be
 isActive=\u0410\u043a\u0442\u0438\u0432\u043d\u043e
-# checkUserAbout=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438
+# checkUserAbout=\u00d0\u009f\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b8
 checkUserAbout=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438
-# checkRoleAbout=\u0420\u043e\u043b\u0438
+# checkRoleAbout=\u00d0\u00a0\u00d0\u00be\u00d0\u00bb\u00d0\u00b8
 checkRoleAbout=\u0420\u043e\u043b\u0438

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
index 3456c87..c8b5711 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications.properties
@@ -24,8 +24,6 @@ notification=Notification
 about=About
 events=Events
 selfAsRecipient=Include users matching About
-recipientAttrType=Recipients e-mail attribute type
-recipientAttrName=Recipients e-mail attribute schema
 checkRecipients=Search recipients
 checkAbout=All
 userFilter=User filter

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
index 8b8a257..94113c6 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_it.properties
@@ -24,8 +24,6 @@ notification=Notifica
 about=Soggetti
 events=Eventi
 selfAsRecipient=Includi i soggetti
-recipientAttrType=Tipo attributo e-mail destinatari
-recipientAttrName=Schema attributo e-mail destinatari
 checkRecipients=Cerca i destinatari
 checkAbout=Tutto
 userFilter=Filtro utenti

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
index 97483b8..8ac31ef 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_pt_BR.properties
@@ -24,8 +24,6 @@ notification=Notifica\u00e7\u00e3o
 about=Sobre
 events=Eventos
 selfAsRecipient=Incluir usu\u00e1rios relacionados Sobre
-recipientAttrType=Tipo de atributo de destinat\u00e1rio de email.
-recipientAttrName=Destinat\u00e1rios de e-mail para atributos de esquema
 checkRecipients=Buscar Destinat\u00e1rios
 checkAbout=Todos
 userFilter=Filtro usu\u00e1rio


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

Posted by il...@apache.org.
[SYNCOPE-862] Preliminary work


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

Branch: refs/heads/SYNCOPE-862
Commit: acce340d1289f1529fe6342f0a4d7c0a3507c6f4
Parents: f5f6270
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Tue May 31 17:59:00 2016 +0200
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Tue Jun 14 17:59:30 2016 +0200

----------------------------------------------------------------------
 .../AnyObjectDisplayAttributesModalPanel.java   |   2 +-
 .../html/repeater/data/table/AttrColumn.java    |  19 +-
 .../data/table/ConnObjectAttrColumn.java        |  63 +++++
 .../console/wizards/any/AnyObjectDetails.java   |  53 ++++
 .../wizards/any/AnyObjectWizardBuilder.java     |  22 +-
 .../console/wizards/any/AnyWizardBuilder.java   |   3 -
 .../console/wizards/any/ConnObjectPanel.java    |   4 +-
 .../console/wizards/any/GroupDetails.java       |   4 +-
 .../client/console/wizards/any/Groups.java      |   1 -
 .../wizards/resources/ResourceMappingPanel.java |   1 +
 .../console/wizards/any/AnyObjectDetails.html   |  25 ++
 .../syncope/common/lib/AnyOperations.java       |  90 +++++--
 .../common/lib/patch/AnyObjectPatch.java        |  10 +
 .../syncope/common/lib/patch/AnyPatch.java      |  10 +-
 .../common/lib/patch/AttributablePatch.java     |  38 +++
 .../common/lib/patch/MembershipPatch.java       |  33 ++-
 .../syncope/common/lib/to/AnyObjectTO.java      |  10 +
 .../org/apache/syncope/common/lib/to/AnyTO.java |  34 ++-
 .../syncope/common/lib/to/AttributableTO.java   |  53 ++++
 .../syncope/common/lib/to/ConnObjectTO.java     |   9 +-
 .../syncope/common/lib/to/MembershipTO.java     |  75 +++++-
 .../syncope/common/lib/to/RelationshipTO.java   |  26 --
 .../common/lib/types/EntityViolationType.java   |   4 +-
 .../common/lib/types/IntMappingType.java        |   8 +-
 .../persistence/api/dao/AllowedSchemas.java     | 114 +++++++++
 .../core/persistence/api/dao/AnyDAO.java        |   3 +-
 .../core/persistence/api/dao/AnyObjectDAO.java  |   4 +
 .../core/persistence/api/entity/Any.java        |   2 +
 .../core/persistence/api/entity/AnyUtils.java   |   3 +-
 .../api/entity/GroupablePlainAttr.java          |  26 ++
 .../api/entity/GroupableRelatable.java          | 100 ++++++++
 .../api/entity/anyobject/APlainAttr.java        |   4 +-
 .../api/entity/anyobject/AnyObject.java         |  24 +-
 .../persistence/api/entity/user/UPlainAttr.java |   4 +-
 .../core/persistence/api/entity/user/User.java  |  32 +--
 .../persistence/jpa/dao/AbstractAnyDAO.java     |  56 +++--
 .../persistence/jpa/dao/JPAAnyObjectDAO.java    |  34 +++
 .../core/persistence/jpa/dao/JPAConfDAO.java    |  12 +-
 .../core/persistence/jpa/dao/JPAGroupDAO.java   |  32 ++-
 .../persistence/jpa/dao/JPAPlainAttrDAO.java    |   2 +-
 .../persistence/jpa/entity/AbstractAny.java     |  28 ---
 .../jpa/entity/AbstractGroupableRelatable.java  | 158 ++++++++++++
 .../persistence/jpa/entity/JPAAnyUtils.java     |  13 +-
 .../jpa/entity/anyobject/JPAAPlainAttr.java     |  22 +-
 .../jpa/entity/anyobject/JPAAnyObject.java      |  95 +++----
 .../persistence/jpa/entity/conf/JPAConf.java    |   8 +-
 .../jpa/entity/group/JPAGPlainAttr.java         |   4 +-
 .../persistence/jpa/entity/group/JPAGroup.java  |  45 +++-
 .../jpa/entity/resource/JPAMappingItem.java     |   4 +
 .../jpa/entity/user/JPAUPlainAttr.java          |  22 +-
 .../persistence/jpa/entity/user/JPAUser.java    |  73 ++----
 .../jpa/validation/entity/AnyValidator.java     |  55 ++--
 .../entity/EntityValidationListener.java        |   5 +-
 .../entity/PlainAttrValueValidator.java         |   2 +-
 .../persistence/jpa/inner/AnyObjectTest.java    |   1 +
 .../persistence/jpa/inner/PlainAttrTest.java    |   2 +-
 .../core/persistence/jpa/outer/ConfTest.java    |  72 ++++++
 .../core/persistence/jpa/outer/GroupTest.java   |   1 +
 .../core/persistence/jpa/outer/UserTest.java    |  91 ++++++-
 .../test/resources/domains/MasterContent.xml    |  11 +-
 .../core/provisioning/api/DerAttrHandler.java   |  23 +-
 .../core/provisioning/api/VirAttrHandler.java   |  28 ++-
 .../provisioning/java/DerAttrHandlerImpl.java   |  32 ++-
 .../provisioning/java/MappingManagerImpl.java   |  20 ++
 .../provisioning/java/VirAttrHandlerImpl.java   |  36 ++-
 .../java/data/AbstractAnyDataBinder.java        | 248 ++++++++++++-------
 .../java/data/AnyObjectDataBinderImpl.java      | 115 +++++++--
 .../java/data/GroupDataBinderImpl.java          |   6 +-
 .../java/data/UserDataBinderImpl.java           |  90 +++++--
 .../java/job/SetUMembershipsJob.java            |   3 +-
 .../provisioning/java/pushpull/PullUtils.java   |   8 +
 .../java/utils/ConnObjectUtils.java             |   2 +-
 .../activiti/ActivitiUserWorkflowAdapter.java   |   2 +-
 fit/build-tools/src/main/resources/testdb.sql   |   1 +
 .../syncope/fit/console/AnyObjectsITCase.java   |   6 +-
 .../syncope/fit/console/BulkActionITCase.java   |   2 +-
 .../fit/console/DisplayAttributesITCase.java    |   4 +-
 .../syncope/fit/core/AnyObjectITCase.java       |   1 +
 .../syncope/fit/core/AuthenticationITCase.java  |   1 +
 .../syncope/fit/core/CamelRouteITCase.java      |   6 +-
 .../syncope/fit/core/MembershipITCase.java      | 206 +++++++++++++++
 .../org/apache/syncope/fit/core/UserITCase.java |  13 +-
 .../apache/syncope/fit/core/UserSelfITCase.java |   3 +-
 .../resources/scriptedsql/CreateScript.groovy   |   3 +-
 .../resources/scriptedsql/SchemaScript.groovy   |   1 +
 .../resources/scriptedsql/SearchScript.groovy   |   2 +-
 .../resources/scriptedsql/SyncScript.groovy     |   3 +-
 .../resources/scriptedsql/TestScript.groovy     |   2 +-
 .../resources/scriptedsql/UpdateScript.groovy   |   7 +-
 89 files changed, 2085 insertions(+), 550 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
index b99a323..39f30ad 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/AnyObjectDisplayAttributesModalPanel.java
@@ -35,7 +35,7 @@ public class AnyObjectDisplayAttributesModalPanel<T extends Serializable> extend
 
     private static final long serialVersionUID = 5194630813773543054L;
 
-    public static final String[] DEFAULT_SELECTION = { "key" };
+    public static final String[] DEFAULT_SELECTION = { "key", "name" };
 
     public AnyObjectDisplayAttributesModalPanel(
             final BaseModal<T> modal,

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
index 9a90ef6..b756a05 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/AttrColumn.java
@@ -26,10 +26,9 @@ import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.ResourceModel;
-import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.ConnObjectTO;
+import org.apache.syncope.common.lib.to.AttributableTO;
 
-public class AttrColumn<T extends ConnObjectTO> extends AbstractColumn<T, String> {
+public class AttrColumn<T extends AttributableTO> extends AbstractColumn<T, String> {
 
     private static final long serialVersionUID = 2624734332447371372L;
 
@@ -59,20 +58,14 @@ public class AttrColumn<T extends ConnObjectTO> extends AbstractColumn<T, String
                 break;
 
             case DERIVED:
-                if (rowModel.getObject() instanceof AnyTO) {
-                    AnyTO obj = AnyTO.class.cast(rowModel.getObject());
-                    if (obj.getDerAttrMap().containsKey(name)) {
-                        values = obj.getDerAttrMap().get(name).getValues();
-                    }
+                if (rowModel.getObject().getDerAttrMap().containsKey(name)) {
+                    values = rowModel.getObject().getDerAttrMap().get(name).getValues();
                 }
                 break;
 
             case VIRTUAL:
-                if (rowModel.getObject() instanceof AnyTO) {
-                    AnyTO obj = AnyTO.class.cast(rowModel.getObject());
-                    if (obj.getVirAttrMap().containsKey(name)) {
-                        values = obj.getVirAttrMap().get(name).getValues();
-                    }
+                if (rowModel.getObject().getVirAttrMap().containsKey(name)) {
+                    values = rowModel.getObject().getVirAttrMap().get(name).getValues();
                 }
                 break;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java
new file mode 100644
index 0000000..56ead58
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/ConnObjectAttrColumn.java
@@ -0,0 +1,63 @@
+/*
+ * 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.client.console.wicket.extensions.markup.html.repeater.data.table;
+
+import java.util.List;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.ResourceModel;
+import org.apache.syncope.common.lib.to.ConnObjectTO;
+
+public class ConnObjectAttrColumn extends AbstractColumn<ConnObjectTO, String> {
+
+    private static final long serialVersionUID = 2624734332447371372L;
+
+    private final String name;
+
+    public ConnObjectAttrColumn(final String name, final SchemaType schemaType) {
+        // set sortProperty to schematype#name (e.g. derivedSchema#cn, 
+        // for use with SortableUserProviderComparator.AttrModel#getObject)
+        super(new ResourceModel(name, name), schemaType.name() + "#" + name);
+        this.name = name;
+    }
+
+    @Override
+    public void populateItem(
+            final Item<ICellPopulator<ConnObjectTO>> cellItem,
+            final String componentId,
+            final IModel<ConnObjectTO> rowModel) {
+
+        List<String> values = null;
+        if (rowModel.getObject().getPlainAttrMap().containsKey(name)) {
+            values = rowModel.getObject().getPlainAttrMap().get(name).getValues();
+        }
+
+        if (values == null || values.isEmpty()) {
+            cellItem.add(new Label(componentId, ""));
+        } else if (values.size() == 1) {
+            cellItem.add(new Label(componentId, values.get(0)));
+        } else {
+            cellItem.add(new Label(componentId, values.toString()));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java
new file mode 100644
index 0000000..5d149e7
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.java
@@ -0,0 +1,53 @@
+/*
+ * 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.client.console.wizards.any;
+
+import java.util.List;
+import org.apache.syncope.client.console.commons.status.StatusBean;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.PropertyModel;
+
+public class AnyObjectDetails extends Details<AnyObjectTO> {
+
+    private static final long serialVersionUID = 855618618337931784L;
+
+    public AnyObjectDetails(
+            final AnyWrapper<AnyObjectTO> wrapper,
+            final IModel<List<StatusBean>> statusModel,
+            final boolean templateMode,
+            final boolean includeStatusPanel,
+            final PageReference pageRef) {
+
+        super(wrapper, statusModel, includeStatusPanel, pageRef);
+
+        AnyObjectTO anyObjectTO = wrapper.getInnerObject();
+
+        AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", "name",
+                new PropertyModel<String>(anyObjectTO, "name"), false);
+        if (templateMode) {
+            name.enableJexlHelp();
+        } else {
+            name.addRequiredLabel();
+        }
+        this.add(name);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
index f92bb31..5952017 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyObjectWizardBuilder.java
@@ -19,20 +19,27 @@
 package org.apache.syncope.client.console.wizards.any;
 
 import java.io.Serializable;
-
+import java.util.Collections;
 import java.util.List;
+import org.apache.syncope.client.console.commons.status.StatusBean;
 import org.apache.syncope.client.console.layout.AnyObjectForm;
 import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
+import org.apache.syncope.client.console.rest.AnyObjectRestClient;
+import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.patch.AnyObjectPatch;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.wizard.WizardModel;
+import org.apache.wicket.model.util.ListModel;
 
 public class AnyObjectWizardBuilder extends AnyWizardBuilder<AnyObjectTO> implements AnyObjectForm {
 
     private static final long serialVersionUID = -2480279868319546243L;
 
+    private final AnyObjectRestClient anyObjectRestClient = new AnyObjectRestClient();
+
     public AnyObjectWizardBuilder(
             final AnyObjectTO anyObjectTO,
             final List<String> anyTypeClasses,
@@ -48,7 +55,7 @@ public class AnyObjectWizardBuilder extends AnyWizardBuilder<AnyObjectTO> implem
 
         ProvisioningResult<AnyObjectTO> actual;
         if (inner.getKey() == null) {
-            actual = anyObjectRestClient.create(AnyObjectTO.class.cast(inner));
+            actual = anyObjectRestClient.create(inner);
         } else {
             AnyObjectPatch patch = AnyOperations.diff(inner, getOriginalItem().getInnerObject(), false);
 
@@ -63,4 +70,15 @@ public class AnyObjectWizardBuilder extends AnyWizardBuilder<AnyObjectTO> implem
 
         return actual;
     }
+
+    @Override
+    protected AnyObjectWizardBuilder addOptionalDetailsPanel(
+            final AnyWrapper<AnyObjectTO> modelObject, final WizardModel wizardModel) {
+        wizardModel.add(new AnyObjectDetails(
+                modelObject,
+                new ListModel<>(Collections.<StatusBean>emptyList()),
+                mode == AjaxWizard.Mode.TEMPLATE,
+                modelObject.getInnerObject().getKey() != null, pageRef));
+        return this;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
index a63a757..41fa6bb 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/AnyWizardBuilder.java
@@ -26,7 +26,6 @@ import org.apache.syncope.client.console.layout.AnyForm;
 import org.apache.syncope.client.console.layout.AnyObjectFormLayoutInfo;
 import org.apache.syncope.client.console.layout.GroupFormLayoutInfo;
 import org.apache.syncope.client.console.layout.UserFormLayoutInfo;
-import org.apache.syncope.client.console.rest.AnyObjectRestClient;
 import org.apache.syncope.client.console.wizards.AjaxWizard;
 import org.apache.syncope.client.console.wizards.AjaxWizardBuilder;
 import org.apache.syncope.common.lib.to.AnyTO;
@@ -40,8 +39,6 @@ public abstract class AnyWizardBuilder<A extends AnyTO> extends AjaxWizardBuilde
 
     private static final long serialVersionUID = -2480279868319546243L;
 
-    protected final AnyObjectRestClient anyObjectRestClient = new AnyObjectRestClient();
-
     protected final List<String> anyTypeClasses;
 
     protected AbstractAnyFormLayout<A, ? extends AnyForm<A>> formLayoutInfo;

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
index 14e3e33..49f6801 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/ConnObjectPanel.java
@@ -57,7 +57,7 @@ public class ConnObjectPanel extends Panel {
             protected List<AttrTO> load() {
                 List<AttrTO> attrs = new ArrayList<>(connObjectTOs == null || connObjectTOs.getRight() == null
                         ? Collections.<AttrTO>emptyList()
-                        : connObjectTOs.getRight().getPlainAttrs());
+                        : connObjectTOs.getRight().getAttrs());
 
                 Collections.sort(attrs, new Comparator<AttrTO>() {
 
@@ -77,7 +77,7 @@ public class ConnObjectPanel extends Panel {
             }
         };
 
-        final Map<String, AttrTO> beforeProfile = connObjectTOs.getLeft() == null
+        final Map<String, AttrTO> beforeProfile = connObjectTOs == null || connObjectTOs.getLeft() == null
                 ? null
                 : connObjectTOs.getLeft().getPlainAttrMap();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
index 7b4f4ce..e61e89c 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/any/GroupDetails.java
@@ -39,9 +39,9 @@ public class GroupDetails extends Details<GroupTO> {
 
         super(wrapper, statusModel, includeStatusPanel, pageRef);
 
-        final GroupTO groupTO = GroupWrapper.class.cast(wrapper).getInnerObject();
+        GroupTO groupTO = GroupWrapper.class.cast(wrapper).getInnerObject();
 
-        final AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", "name",
+        AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", "name",
                 new PropertyModel<String>(groupTO, "name"), false);
         if (templateMode) {
             name.enableJexlHelp();

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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 8c84cda..401f8e0 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
@@ -105,7 +105,6 @@ public class Groups extends WizardStep {
                     public MembershipTO transform(final GroupTO input) {
                         return new MembershipTO.Builder().
                                 group(input.getKey(), input.getName()).
-                                left(anyTO.getKey(), anyTO.getType()).
                                 build();
                     }
                 }, new ArrayList<MembershipTO>());

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
index 5020bd7..06ea7c8 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.java
@@ -570,6 +570,7 @@ public class ResourceMappingPanel extends Panel {
                 case GroupKey:
                 case GroupName:
                 case AnyObjectKey:
+                case AnyObjectName:
                 default:
                     toBeUpdated.setRequired(false);
                     toBeUpdated.setEnabled(false);

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.html b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.html
new file mode 100644
index 0000000..4d821fe
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/any/AnyObjectDetails.html
@@ -0,0 +1,25 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:extend>
+    <div class="form-group">
+      <span wicket:id="name"/>
+    </div>
+  </wicket:extend>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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 39fbc63..1f985a4 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
@@ -25,6 +25,7 @@ import java.util.Set;
 import org.apache.commons.collections4.Closure;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
@@ -173,7 +174,10 @@ public final class AnyOperations {
 
         diff(updated, original, result, incremental);
 
-        // 1. relationships
+        // 1. name
+        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();
 
@@ -193,21 +197,21 @@ public final class AnyOperations {
             }
         }
 
-        // 2. memberships
+        // 3. memberships
         Map<String, MembershipTO> updatedMembs = updated.getMembershipMap();
         Map<String, MembershipTO> originalMembs = original.getMembershipMap();
 
         for (Map.Entry<String, MembershipTO> entry : updatedMembs.entrySet()) {
             if (!originalMembs.containsKey(entry.getKey())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.ADD_REPLACE).membershipTO(entry.getValue()).build());
+                        operation(PatchOperation.ADD_REPLACE).group(entry.getValue().getGroupKey()).build());
             }
         }
 
         if (!incremental) {
             for (String key : CollectionUtils.subtract(originalMembs.keySet(), updatedMembs.keySet())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.DELETE).membershipTO(originalMembs.get(key)).build());
+                        operation(PatchOperation.DELETE).group(originalMembs.get(key).getGroupKey()).build());
             }
         }
 
@@ -294,14 +298,14 @@ public final class AnyOperations {
         for (Map.Entry<String, MembershipTO> entry : updatedMembs.entrySet()) {
             if (!originalMembs.containsKey(entry.getKey())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.ADD_REPLACE).membershipTO(entry.getValue()).build());
+                        operation(PatchOperation.ADD_REPLACE).group(entry.getValue().getGroupKey()).build());
             }
         }
 
         if (!incremental) {
             for (String key : CollectionUtils.subtract(originalMembs.keySet(), updatedMembs.keySet())) {
                 result.getMemberships().add(new MembershipPatch.Builder().
-                        operation(PatchOperation.DELETE).membershipTO(originalMembs.get(key)).build());
+                        operation(PatchOperation.DELETE).group(originalMembs.get(key).getGroupKey()).build());
             }
         }
 
@@ -410,7 +414,7 @@ public final class AnyOperations {
 
         // 2. plain attributes
         result.getPlainAttrs().clear();
-        result.getPlainAttrs().addAll(AnyOperations.patch(to.getPlainAttrMap(), patch.getPlainAttrs()));
+        result.getPlainAttrs().addAll(patch(to.getPlainAttrMap(), patch.getPlainAttrs()));
 
         // 3. virtual attributes
         result.getVirAttrs().clear();
@@ -432,7 +436,7 @@ public final class AnyOperations {
 
     public static GroupTO patch(final GroupTO groupTO, final GroupPatch groupPatch) {
         GroupTO result = SerializationUtils.clone(groupTO);
-        AnyOperations.patch(groupTO, groupPatch, result);
+        patch(groupTO, groupPatch, result);
 
         if (groupPatch.getName() != null) {
             result.setName(groupPatch.getName().getValue());
@@ -454,10 +458,10 @@ public final class AnyOperations {
 
     public static AnyObjectTO patch(final AnyObjectTO anyObjectTO, final AnyObjectPatch anyObjectPatch) {
         AnyObjectTO result = SerializationUtils.clone(anyObjectTO);
-        AnyOperations.patch(anyObjectTO, anyObjectPatch, result);
+        patch(anyObjectTO, anyObjectPatch, result);
 
         // 1. relationships
-        for (final RelationshipPatch relPatch : anyObjectPatch.getRelationships()) {
+        for (RelationshipPatch relPatch : anyObjectPatch.getRelationships()) {
             if (relPatch.getRelationshipTO() == null) {
                 LOG.warn("Invalid {} specified: {}", RelationshipPatch.class.getName(), relPatch);
             } else {
@@ -470,12 +474,37 @@ public final class AnyOperations {
 
         // 2. memberships
         for (final MembershipPatch membPatch : anyObjectPatch.getMemberships()) {
-            if (membPatch.getMembershipTO() == null) {
+            if (membPatch.getGroup() == null) {
                 LOG.warn("Invalid {} specified: {}", MembershipPatch.class.getName(), membPatch);
             } else {
-                result.getMemberships().remove(membPatch.getMembershipTO());
+                MembershipTO memb = IterableUtils.find(result.getMemberships(), new Predicate<MembershipTO>() {
+
+                    @Override
+                    public boolean evaluate(final MembershipTO object) {
+                        return membPatch.getGroup().equals(object.getGroupKey());
+                    }
+                });
+                if (memb != null) {
+                    result.getMemberships().remove(memb);
+                }
+
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    result.getMemberships().add(membPatch.getMembershipTO());
+                    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(memb.getPlainAttrMap(), membPatch.getPlainAttrs()));
+                    }
+
+                    // 3. virtual attributes
+                    newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
+
+                    result.getMemberships().add(newMembershipTO);
                 }
             }
         }
@@ -485,7 +514,7 @@ public final class AnyOperations {
 
     public static UserTO patch(final UserTO userTO, final UserPatch userPatch) {
         UserTO result = SerializationUtils.clone(userTO);
-        AnyOperations.patch(userTO, userPatch, result);
+        patch(userTO, userPatch, result);
 
         // 1. password
         if (userPatch.getPassword() != null) {
@@ -498,7 +527,7 @@ public final class AnyOperations {
         }
 
         // 3. relationships
-        for (final RelationshipPatch relPatch : userPatch.getRelationships()) {
+        for (RelationshipPatch relPatch : userPatch.getRelationships()) {
             if (relPatch.getRelationshipTO() == null) {
                 LOG.warn("Invalid {} specified: {}", RelationshipPatch.class.getName(), relPatch);
             } else {
@@ -511,12 +540,37 @@ public final class AnyOperations {
 
         // 4. memberships
         for (final MembershipPatch membPatch : userPatch.getMemberships()) {
-            if (membPatch.getMembershipTO() == null) {
+            if (membPatch.getGroup() == null) {
                 LOG.warn("Invalid {} specified: {}", MembershipPatch.class.getName(), membPatch);
             } else {
-                result.getMemberships().remove(membPatch.getMembershipTO());
+                MembershipTO memb = IterableUtils.find(result.getMemberships(), new Predicate<MembershipTO>() {
+
+                    @Override
+                    public boolean evaluate(final MembershipTO object) {
+                        return membPatch.getGroup().equals(object.getGroupKey());
+                    }
+                });
+                if (memb != null) {
+                    result.getMemberships().remove(memb);
+                }
+
                 if (membPatch.getOperation() == PatchOperation.ADD_REPLACE) {
-                    result.getMemberships().add(membPatch.getMembershipTO());
+                    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(memb.getPlainAttrMap(), membPatch.getPlainAttrs()));
+                    }
+
+                    // 3. virtual attributes
+                    newMembershipTO.getVirAttrs().addAll(membPatch.getVirAttrs());
+
+                    result.getMemberships().add(newMembershipTO);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
index e473e06..ddb4ac3 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyObjectPatch.java
@@ -32,10 +32,20 @@ public class AnyObjectPatch extends AnyPatch {
 
     private static final long serialVersionUID = -1644118942622556097L;
 
+    private StringReplacePatchItem name;
+
     private final Set<RelationshipPatch> relationships = new HashSet<>();
 
     private final Set<MembershipPatch> memberships = new HashSet<>();
 
+    public StringReplacePatchItem getName() {
+        return name;
+    }
+
+    public void setName(final StringReplacePatchItem name) {
+        this.name = name;
+    }
+
     @XmlElementWrapper(name = "relationships")
     @XmlElement(name = "relationship")
     @JsonProperty("relationships")

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
index 3ec141d..78e61dd 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AnyPatch.java
@@ -30,7 +30,7 @@ import org.apache.syncope.common.lib.AbstractBaseBean;
 import org.apache.syncope.common.lib.to.AttrTO;
 
 @XmlType
-public abstract class AnyPatch extends AbstractBaseBean {
+public abstract class AnyPatch extends AbstractBaseBean implements AttributablePatch {
 
     private static final long serialVersionUID = -7445489774552440544L;
 
@@ -70,16 +70,12 @@ public abstract class AnyPatch extends AbstractBaseBean {
         return auxClasses;
     }
 
-    @XmlElementWrapper(name = "plainAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("plainAttrs")
+    @Override
     public Set<AttrPatch> 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/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java
new file mode 100644
index 0000000..fa9d189
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/patch/AttributablePatch.java
@@ -0,0 +1,38 @@
+/*
+ * 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.common.lib.patch;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import org.apache.syncope.common.lib.to.AttrTO;
+
+public interface AttributablePatch {
+
+    @XmlElementWrapper(name = "plainAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("plainAttrs")
+    Set<AttrPatch> getPlainAttrs();
+
+    @XmlElementWrapper(name = "virAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrs")
+    Set<AttrTO> getVirAttrs();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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 b29a6de..0ed42c1 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
@@ -18,13 +18,15 @@
  */
 package org.apache.syncope.common.lib.patch;
 
+import java.util.HashSet;
+import java.util.Set;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.AttrTO;
 
 @XmlRootElement(name = "membershipPatch")
 @XmlType
-public class MembershipPatch extends AbstractPatch {
+public class MembershipPatch extends AbstractPatch implements AttributablePatch {
 
     private static final long serialVersionUID = -6783121761221554433L;
 
@@ -35,20 +37,33 @@ public class MembershipPatch extends AbstractPatch {
             return new MembershipPatch();
         }
 
-        public Builder membershipTO(final MembershipTO membershipTO) {
-            getInstance().setMembershipTO(membershipTO);
+        public Builder group(final String group) {
+            getInstance().setGroup(group);
             return this;
         }
     }
 
-    private MembershipTO membershipTO;
+    private String group;
 
-    public MembershipTO getMembershipTO() {
-        return membershipTO;
+    private final Set<AttrPatch> plainAttrs = new HashSet<>();
+
+    private final Set<AttrTO> virAttrs = new HashSet<>();
+
+    public String getGroup() {
+        return group;
     }
 
-    public void setMembershipTO(final MembershipTO membershipTO) {
-        this.membershipTO = membershipTO;
+    public void setGroup(final String group) {
+        this.group = group;
     }
 
+    @Override
+    public Set<AttrPatch> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public Set<AttrTO> getVirAttrs() {
+        return virAttrs;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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 f652d76..d0bf7d4 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
@@ -37,12 +37,22 @@ public class AnyObjectTO extends AnyTO implements RelatableTO, GroupableTO {
 
     private static final long serialVersionUID = 8841697496476959639L;
 
+    private String name;
+
     private final List<RelationshipTO> relationships = new ArrayList<>();
 
     private final List<MembershipTO> memberships = new ArrayList<>();
 
     private final List<String> dynGroups = new ArrayList<>();
 
+    public String getName() {
+        return name;
+    }
+
+    public void setName(final String name) {
+        this.name = name;
+    }
+
     @XmlElementWrapper(name = "relationships")
     @XmlElement(name = "relationship")
     @JsonProperty("relationships")

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index 4651835..7732bcc 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.common.lib.to;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import java.util.ArrayList;
@@ -30,15 +29,13 @@ import java.util.Map;
 import java.util.Set;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
 
-@XmlRootElement(name = "any")
 @XmlType
 @XmlSeeAlso({ UserTO.class, GroupTO.class, AnyObjectTO.class })
 @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
-public abstract class AnyTO extends ConnObjectTO implements EntityTO {
+public abstract class AnyTO extends AbstractAnnotatedBean implements EntityTO, AttributableTO {
 
     private static final long serialVersionUID = -754311920679872084L;
 
@@ -52,6 +49,8 @@ public abstract class AnyTO extends ConnObjectTO implements EntityTO {
 
     private final List<String> auxClasses = new ArrayList<>();
 
+    private final Set<AttrTO> plainAttrs = new HashSet<>();
+
     private final Set<AttrTO> derAttrs = new HashSet<>();
 
     private final Set<AttrTO> virAttrs = new HashSet<>();
@@ -99,14 +98,27 @@ public abstract class AnyTO extends ConnObjectTO implements EntityTO {
         return auxClasses;
     }
 
-    @XmlElementWrapper(name = "derAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("derAttrs")
+    @Override
+    public Set<AttrTO> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getPlainAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(plainAttrs.size());
+        for (AttrTO attributeTO : plainAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    @Override
     public Set<AttrTO> getDerAttrs() {
         return derAttrs;
     }
 
-    @JsonIgnore
+    @Override
     public Map<String, AttrTO> getDerAttrMap() {
         Map<String, AttrTO> result = new HashMap<>(derAttrs.size());
         for (AttrTO attributeTO : derAttrs) {
@@ -116,14 +128,12 @@ public abstract class AnyTO extends ConnObjectTO implements EntityTO {
         return Collections.unmodifiableMap(result);
     }
 
-    @XmlElementWrapper(name = "virAttrs")
-    @XmlElement(name = "attribute")
-    @JsonProperty("virAttrs")
+    @Override
     public Set<AttrTO> getVirAttrs() {
         return virAttrs;
     }
 
-    @JsonIgnore
+    @Override
     public Map<String, AttrTO> getVirAttrMap() {
         Map<String, AttrTO> result = new HashMap<>(virAttrs.size());
         for (AttrTO attributeTO : virAttrs) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java
new file mode 100644
index 0000000..51ee0fc
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttributableTO.java
@@ -0,0 +1,53 @@
+/*
+ * 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.common.lib.to;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.Map;
+import java.util.Set;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+public interface AttributableTO {
+
+    @XmlElementWrapper(name = "plainAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("plainAttrs")
+    Set<AttrTO> getPlainAttrs();
+
+    @JsonIgnore
+    Map<String, AttrTO> getPlainAttrMap();
+
+    @XmlElementWrapper(name = "derAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("derAttrs")
+    Set<AttrTO> getDerAttrs();
+
+    @JsonIgnore
+    Map<String, AttrTO> getDerAttrMap();
+
+    @XmlElementWrapper(name = "virAttrs")
+    @XmlElement(name = "attribute")
+    @JsonProperty("virAttrs")
+    Set<AttrTO> getVirAttrs();
+
+    @JsonIgnore
+    Map<String, AttrTO> getVirAttrMap();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
index 82878f8..8f65b70 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ConnObjectTO.java
@@ -29,19 +29,20 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.AbstractBaseBean;
 
 @XmlRootElement(name = "connObject")
 @XmlType
-public class ConnObjectTO extends AbstractAnnotatedBean {
+public class ConnObjectTO extends AbstractBaseBean {
 
     private static final long serialVersionUID = 5139554911265442497L;
 
     private final Set<AttrTO> attrs = new LinkedHashSet<>();
 
-    @XmlElementWrapper(name = "plainAttrs")
+    @XmlElementWrapper(name = "attrs")
     @XmlElement(name = "attribute")
-    @JsonProperty("plainAttrs")
-    public Set<AttrTO> getPlainAttrs() {
+    @JsonProperty("attrs")
+    public Set<AttrTO> getAttrs() {
         return attrs;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
index 6ded46b..58f3d9d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
@@ -18,13 +18,19 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "membership")
 @XmlType
-public class MembershipTO extends RelationshipTO {
+public class MembershipTO extends RelationshipTO implements AttributableTO {
 
     private static final long serialVersionUID = 5992828670273935861L;
 
@@ -32,12 +38,6 @@ public class MembershipTO extends RelationshipTO {
 
         private final MembershipTO instance = new MembershipTO();
 
-        public Builder left(final String leftType, final String leftKey) {
-            instance.setLeftType(leftType);
-            instance.setLeftKey(leftKey);
-            return this;
-        }
-
         public Builder group(final String groupKey) {
             instance.setRightKey(groupKey);
             return this;
@@ -56,6 +56,12 @@ public class MembershipTO extends RelationshipTO {
 
     private String groupName;
 
+    private final Set<AttrTO> plainAttrs = new HashSet<>();
+
+    private final Set<AttrTO> derAttrs = new HashSet<>();
+
+    private final Set<AttrTO> virAttrs = new HashSet<>();
+
     @Override
     public String getType() {
         return "Membership";
@@ -76,6 +82,15 @@ public class MembershipTO extends RelationshipTO {
         // ignore
     }
 
+    @JsonIgnore
+    public String getGroupKey() {
+        return getRightKey();
+    }
+
+    public void setGroupKey(final String groupKey) {
+        setRightKey(groupKey);
+    }
+
     public String getGroupName() {
         return groupName;
     }
@@ -83,4 +98,50 @@ public class MembershipTO extends RelationshipTO {
     public void setGroupName(final String groupName) {
         this.groupName = groupName;
     }
+
+    @Override
+    public Set<AttrTO> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getPlainAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(plainAttrs.size());
+        for (AttrTO attributeTO : plainAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Set<AttrTO> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getDerAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(derAttrs.size());
+        for (AttrTO attributeTO : derAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
+    @Override
+    public Set<AttrTO> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @Override
+    public Map<String, AttrTO> getVirAttrMap() {
+        Map<String, AttrTO> result = new HashMap<>(virAttrs.size());
+        for (AttrTO attributeTO : virAttrs) {
+            result.put(attributeTO.getSchema(), attributeTO);
+        }
+
+        return Collections.unmodifiableMap(result);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
index 29326c2..fc5de4f 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
@@ -37,12 +37,6 @@ public class RelationshipTO extends AbstractBaseBean {
             return this;
         }
 
-        public Builder left(final String leftType, final String leftKey) {
-            instance.setLeftType(leftType);
-            instance.setLeftKey(leftKey);
-            return this;
-        }
-
         public Builder right(final String rightType, final String rightKey) {
             instance.setRightType(rightType);
             instance.setRightKey(rightKey);
@@ -56,10 +50,6 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private String type;
 
-    private String leftType;
-
-    private String leftKey;
-
     private String rightType;
 
     private String rightKey;
@@ -72,22 +62,6 @@ public class RelationshipTO extends AbstractBaseBean {
         this.type = type;
     }
 
-    public String getLeftType() {
-        return leftType;
-    }
-
-    public void setLeftType(final String leftType) {
-        this.leftType = leftType;
-    }
-
-    public String getLeftKey() {
-        return leftKey;
-    }
-
-    public void setLeftKey(final String leftKey) {
-        this.leftKey = leftKey;
-    }
-
     public String getRightType() {
         return rightType;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
index 7532730..db3e329 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/EntityViolationType.java
@@ -43,9 +43,7 @@ public enum EntityViolationType {
     InvalidSchemaMultivalueUnique("org.apache.syncope.core.persistence.validation.schema.multivalueUnique"),
     InvalidSchedTask("org.apache.syncope.core.persistence.validation.schedtask"),
     InvalidProvisioningTask("org.apache.syncope.core.persistence.validation.provisioningtask"),
-    InvalidPlainSchema("org.apache.syncope.core.persistence.validation.attrvalue.plainSchema"),
-    InvalidDerSchema("org.apache.syncope.core.persistence.validation.attrvalue.derSchema"),
-    InvalidVirSchema("org.apache.syncope.core.persistence.validation.attrvalue.virSchema"),
+    InvalidPlainAttr("org.apache.syncope.core.persistence.validation.plainattr"),
     InvalidUsername("org.apache.syncope.core.persistence.validation.user.username"),
     InvalidValueList("org.apache.syncope.core.persistence.validation.attr.valueList"),
     MoreThanOneNonNull("org.apache.syncope.core.persistence.validation.attrvalue.moreThanOneNonNull");

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
index eccb89d..8553348 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/IntMappingType.java
@@ -56,7 +56,8 @@ public enum IntMappingType {
     AnyObjectPlainSchema(AnyTypeKind.ANY_OBJECT),
     AnyObjectDerivedSchema(AnyTypeKind.ANY_OBJECT),
     AnyObjectVirtualSchema(AnyTypeKind.ANY_OBJECT),
-    AnyObjectKey(AnyTypeKind.ANY_OBJECT);
+    AnyObjectKey(AnyTypeKind.ANY_OBJECT),
+    AnyObjectName(AnyTypeKind.ANY_OBJECT);
 
     private final AnyTypeKind anyTypeKind;
 
@@ -119,7 +120,7 @@ public enum IntMappingType {
     public static Set<IntMappingType> getEmbedded() {
         return EnumSet.of(IntMappingType.UserKey, IntMappingType.Username, IntMappingType.Password,
                 IntMappingType.GroupKey, IntMappingType.GroupName, IntMappingType.GroupOwnerSchema,
-                IntMappingType.AnyObjectKey);
+                IntMappingType.AnyObjectKey, IntMappingType.AnyObjectName);
     }
 
     /**
@@ -195,7 +196,8 @@ public enum IntMappingType {
         AnyObjectPlainSchema,
         AnyObjectDerivedSchema,
         AnyObjectVirtualSchema,
-        AnyObjectKey;
+        AnyObjectKey,
+        AnyObjectName;
 
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java
new file mode 100644
index 0000000..6c04ac4
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AllowedSchemas.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.api.dao;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.IterableUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.collections4.PredicateUtils;
+import org.apache.commons.collections4.SetUtils;
+import org.apache.syncope.core.persistence.api.entity.Schema;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+
+public class AllowedSchemas<S extends Schema> {
+
+    private final Set<S> forSelf = new HashSet<>();
+
+    private final Map<Group, Set<S>> forMemberships = new HashMap<>();
+
+    public Set<S> getForSelf() {
+        return forSelf;
+    }
+
+    public Set<S> getForMembership(final Group group) {
+        return SetUtils.emptyIfNull(forMemberships.get(group));
+    }
+
+    public Map<Group, Set<S>> getForMemberships() {
+        return forMemberships;
+    }
+
+    public boolean forSelfContains(final S schema) {
+        return forSelf.contains(schema);
+    }
+
+    public boolean forSelfContains(final String schema) {
+        return IterableUtils.matchesAny(forSelf, new KeyMatches(schema));
+    }
+
+    public boolean forMembershipsContains(final Group group, final S schema) {
+        return IterableUtils.matchesAny(forMemberships.get(group), PredicateUtils.equalPredicate(schema));
+    }
+
+    public boolean forMembershipsContains(final S schema) {
+        for (Map.Entry<Group, Set<S>> entry : forMemberships.entrySet()) {
+            if (entry.getValue().contains(schema)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean forMembershipsContains(final Group group, final String schema) {
+        return IterableUtils.matchesAny(forMemberships.get(group), new KeyMatches(schema));
+    }
+
+    public boolean forMembershipsContains(final String schema) {
+        KeyMatches keyMatches = new KeyMatches(schema);
+
+        for (Map.Entry<Group, Set<S>> entry : forMemberships.entrySet()) {
+            if (IterableUtils.matchesAny(entry.getValue(), keyMatches)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean contains(final S schema) {
+        if (forSelfContains(schema)) {
+            return true;
+        }
+        return forMembershipsContains(schema);
+    }
+
+    public boolean contains(final String schema) {
+        if (forSelfContains(schema)) {
+            return true;
+        }
+        return forMembershipsContains(schema);
+    }
+
+    private class KeyMatches implements Predicate<S> {
+
+        private final String schema;
+
+        KeyMatches(final String schema) {
+            this.schema = schema;
+        }
+
+        @Override
+        public boolean evaluate(final S object) {
+            return object.getKey().equals(schema);
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
index b6d78fd..6b2fd4e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyDAO.java
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.persistence.api.dao;
 
-import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
@@ -72,7 +71,7 @@ public interface AnyDAO<A extends Any<?>> extends DAO<A> {
      */
     List<A> findAll(Set<String> adminRealms, int page, int itemsPerPage, List<OrderByClause> orderBy);
 
-    <S extends Schema> Collection<S> findAllowedSchemas(A any, Class<S> reference);
+    <S extends Schema> AllowedSchemas<S> findAllowedSchemas(A any, Class<S> reference);
 
     int count(Set<String> adminRealms);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
index bdf9642..c24b37d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/AnyObjectDAO.java
@@ -40,6 +40,10 @@ public interface AnyObjectDAO extends AnyDAO<AnyObject> {
 
     Map<String, Integer> countByRealm(AnyType anyType);
 
+    AnyObject findByName(String name);
+
+    AnyObject authFindByName(String name);
+
     List<Group> findDynGroupMemberships(AnyObject anyObject);
 
     List<ARelationship> findARelationships(AnyObject anyObject);

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
index b1580e3..82359e9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Any.java
@@ -41,6 +41,8 @@ public interface Any<P extends PlainAttr<?>> extends AnnotatedEntity {
 
     boolean add(P attr);
 
+    boolean remove(P attr);
+
     P getPlainAttr(String plainSchemaName);
 
     List<? extends P> getPlainAttrs();

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
index 377f7fe..0e0c8cc 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AnyUtils.java
@@ -22,6 +22,7 @@ import java.util.Set;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 
 public interface AnyUtils {
@@ -52,5 +53,5 @@ public interface AnyUtils {
 
     Set<ExternalResource> getAllResources(Any<?> any);
 
-    <S extends Schema> Set<S> getAllowedSchemas(Any<?> any, Class<S> reference);
+    <S extends Schema> AllowedSchemas<S> getAllowedSchemas(Any<?> any, Class<S> reference);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java
new file mode 100644
index 0000000..7e345a5
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupablePlainAttr.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.api.entity;
+
+public interface GroupablePlainAttr<A extends Any<?>, M extends Membership<A>> extends PlainAttr<A> {
+
+    M getMembership();
+
+    void setMembership(M membership);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java
new file mode 100644
index 0000000..147f469
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/GroupableRelatable.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.api.entity;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface GroupableRelatable<
+        L extends Any<P>, 
+        M extends Membership<L>, 
+        P extends GroupablePlainAttr<L, M>,
+        R extends Any<?>,
+        REL extends Relationship<L, R>> extends Any<P> {
+
+    @Override
+    boolean add(final P attr);
+
+    @Override
+    boolean remove(final P attr);
+
+    /**
+     * Returns the plain attribute for this instance and the given schema name - if found, {@code NULL} otherwise.
+     * <b>IMPORTANT:</b> This method won't return any attribute related to memberships.
+     *
+     * @param plainSchemaName plain schema name
+     * @return plain attribute for this instance and the given schema name - if found, {@code NULL} otherwise
+     */
+    @Override
+    P getPlainAttr(String plainSchemaName);
+
+    /**
+     * Returns the plain attribute for this instance, the given schema name and the given membership -
+     * if found, {@code NULL} otherwise.
+     *
+     * @param plainSchemaName plain schema name
+     * @param membership membership
+     * @return plain attribute for this instance, the given schema name and the given membership -
+     * if found, {@code NULL} otherwise
+     */
+    P getPlainAttr(String plainSchemaName, Membership<?> membership);
+
+    /**
+     * Returns the plain attributes for this instance.
+     * <b>IMPORTANT:</b> This method won't return any attribute related to memberships.
+     *
+     * @return plain attribute for this instance
+     */
+    @Override
+    List<? extends P> getPlainAttrs();
+
+    /**
+     * Returns the list of plain attributes for this instance and the given schema name (including membeship attributes,
+     * as opposite to {@link Any#getPlainAttr(java.lang.String)}).
+     *
+     * @param plainSchemaName plain schema name
+     * @return list of plain attributes for this instance and the given schema name (including membeship attributes)
+     */
+    Collection<? extends P> getPlainAttrs(String plainSchemaName);
+
+    /**
+     * Returns the list of plain attributes for this instance and the given membership.
+     *
+     * @param membership membership
+     * @return list of plain attributes for this instance and the given membership
+     */
+    Collection<? extends P> getPlainAttrs(Membership<?> membership);
+
+    boolean add(M membership);
+
+    M getMembership(String groupKey);
+
+    List<? extends M> getMemberships();
+
+    boolean add(REL relationship);
+
+    REL getRelationship(RelationshipType relationshipType, String otherEndKey);
+
+    Collection<? extends REL> getRelationships(String otherEndKey);
+
+    Collection<? extends REL> getRelationships(RelationshipType relationshipType);
+
+    List<? extends REL> getRelationships();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
index 46d2297..64a58ce 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/APlainAttr.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.core.persistence.api.entity.anyobject;
 
 import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
 
-public interface APlainAttr extends PlainAttr<AnyObject> {
+public interface APlainAttr extends GroupablePlainAttr<AnyObject, AMembership> {
 
     @Override
     List<? extends APlainAttrValue> getValues();

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
index ac5fda0..7b0f434 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
@@ -18,27 +18,13 @@
  */
 package org.apache.syncope.core.persistence.api.entity.anyobject;
 
-import java.util.Collection;
-import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.RelationshipType;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 
-public interface AnyObject extends Any<APlainAttr> {
+public interface AnyObject extends
+        GroupableRelatable<AnyObject, AMembership, APlainAttr, AnyObject, ARelationship> {
 
-    boolean add(ARelationship relationship);
+    String getName();
 
-    ARelationship getRelationship(RelationshipType relationshipType, String anyObjectKey);
-
-    Collection<? extends ARelationship> getRelationships(String anyObjectKey);
-
-    Collection<? extends ARelationship> getRelationships(RelationshipType relationshipType);
-
-    List<? extends ARelationship> getRelationships();
-
-    boolean add(AMembership membership);
-
-    AMembership getMembership(String membershipKey);
-
-    List<? extends AMembership> getMemberships();
+    void setName(String name);
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
index 5c91acf..503352f 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/UPlainAttr.java
@@ -19,9 +19,9 @@
 package org.apache.syncope.core.persistence.api.entity.user;
 
 import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
 
-public interface UPlainAttr extends PlainAttr<User> {
+public interface UPlainAttr extends GroupablePlainAttr<User, UMembership> {
 
     @Override
     List<? extends UPlainAttrValue> getValues();

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
index b7e14bf..fa81fd1 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
@@ -18,15 +18,15 @@
  */
 package org.apache.syncope.core.persistence.api.entity.user;
 
-import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.RelationshipType;
 import org.apache.syncope.core.persistence.api.entity.Role;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 
-public interface User extends Any<UPlainAttr> {
+public interface User extends
+        GroupableRelatable<User, UMembership, UPlainAttr, AnyObject, URelationship> {
 
     String getUsername();
 
@@ -92,32 +92,8 @@ public interface User extends Any<UPlainAttr> {
 
     void setMustChangePassword(boolean mustChangePassword);
 
-    @Override
-    boolean add(UPlainAttr attr);
-
-    @Override
-    UPlainAttr getPlainAttr(String plainSchemaName);
-
-    @Override
-    List<? extends UPlainAttr> getPlainAttrs();
-
     boolean add(Role role);
 
     List<? extends Role> getRoles();
 
-    boolean add(URelationship relationship);
-
-    URelationship getRelationship(RelationshipType relationshipType, String anyObjectKey);
-
-    Collection<? extends URelationship> getRelationships(String anyObjectKey);
-
-    Collection<? extends URelationship> getRelationships(RelationshipType relationshipType);
-
-    List<? extends URelationship> getRelationships();
-
-    boolean add(UMembership membership);
-
-    UMembership getMembership(String groupKey);
-
-    List<? extends UMembership> getMemberships();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 379d386..0eb38ac 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -23,8 +23,10 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.regex.Pattern;
 import javax.persistence.NoResultException;
@@ -35,6 +37,7 @@ import org.apache.commons.jexl3.parser.ParserConstants;
 import org.apache.commons.jexl3.parser.Token;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
@@ -54,6 +57,7 @@ import org.apache.syncope.core.persistence.api.entity.Schema;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 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.group.TypeExtension;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
@@ -420,33 +424,55 @@ public abstract class AbstractAnyDAO<A extends Any<?>> extends AbstractDAO<A> im
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
     @Override
     @SuppressWarnings("unchecked")
-    public <S extends Schema> Collection<S> findAllowedSchemas(final A any, final Class<S> reference) {
-        Set<AnyTypeClass> classes = new HashSet<>();
-        classes.addAll(any.getType().getClasses());
-        classes.addAll(any.getAuxClasses());
+    public <S extends Schema> AllowedSchemas<S> findAllowedSchemas(final A any, final Class<S> reference) {
+        AllowedSchemas<S> result = new AllowedSchemas<>();
+
+        // schemas given by type and aux classes
+        Set<AnyTypeClass> typeOwnClasses = new HashSet<>();
+        typeOwnClasses.addAll(any.getType().getClasses());
+        typeOwnClasses.addAll(any.getAuxClasses());
+
+        for (AnyTypeClass typeClass : typeOwnClasses) {
+            if (reference.equals(PlainSchema.class)) {
+                result.getForSelf().addAll((Collection<? extends S>) typeClass.getPlainSchemas());
+            } else if (reference.equals(DerSchema.class)) {
+                result.getForSelf().addAll((Collection<? extends S>) typeClass.getDerSchemas());
+            } else if (reference.equals(VirSchema.class)) {
+                result.getForSelf().addAll((Collection<? extends S>) typeClass.getVirSchemas());
+            }
+        }
+
+        // schemas given by type extensions
+        Map<Group, List<? extends AnyTypeClass>> typeExtensionClasses = new HashMap<>();
         if (any instanceof User) {
             for (UMembership memb : ((User) any).getMemberships()) {
                 for (TypeExtension typeExtension : memb.getRightEnd().getTypeExtensions()) {
-                    classes.addAll(typeExtension.getAuxClasses());
+                    typeExtensionClasses.put(memb.getRightEnd(), typeExtension.getAuxClasses());
                 }
             }
         } else if (any instanceof AnyObject) {
             for (AMembership memb : ((AnyObject) any).getMemberships()) {
                 for (TypeExtension typeExtension : memb.getRightEnd().getTypeExtensions()) {
-                    classes.addAll(typeExtension.getAuxClasses());
+                    if (any.getType().equals(typeExtension.getAnyType())) {
+                        typeExtensionClasses.put(memb.getRightEnd(), typeExtension.getAuxClasses());
+                    }
                 }
             }
         }
 
-        Set<S> result = new HashSet<>();
-
-        for (AnyTypeClass typeClass : classes) {
-            if (reference.equals(PlainSchema.class)) {
-                result.addAll((Collection<? extends S>) typeClass.getPlainSchemas());
-            } else if (reference.equals(DerSchema.class)) {
-                result.addAll((Collection<? extends S>) typeClass.getDerSchemas());
-            } else if (reference.equals(VirSchema.class)) {
-                result.addAll((Collection<? extends S>) typeClass.getVirSchemas());
+        for (Map.Entry<Group, List<? extends AnyTypeClass>> entry : typeExtensionClasses.entrySet()) {
+            result.getForMemberships().put(entry.getKey(), new HashSet<S>());
+            for (AnyTypeClass typeClass : entry.getValue()) {
+                if (reference.equals(PlainSchema.class)) {
+                    result.getForMemberships().get(entry.getKey()).
+                            addAll((Collection<? extends S>) typeClass.getPlainSchemas());
+                } else if (reference.equals(DerSchema.class)) {
+                    result.getForMemberships().get(entry.getKey()).
+                            addAll((Collection<? extends S>) typeClass.getDerSchemas());
+                } else if (reference.equals(VirSchema.class)) {
+                    result.getForMemberships().get(entry.getKey()).
+                            addAll((Collection<? extends S>) typeClass.getVirSchemas());
+                }
             }
         }
 


[13/15] syncope git commit: [SYNCOPE-862] Preliminary work

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
index b65cc79..67a821c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -29,6 +29,7 @@ import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -48,6 +49,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
+@Transactional(readOnly = true)
 @Component
 public class VirAttrHandlerImpl implements VirAttrHandler {
 
@@ -122,7 +124,8 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
                             if (attr != null) {
                                 VirAttrCacheValue virAttrCacheValue = new VirAttrCacheValue();
                                 virAttrCacheValue.setValues(attr.getValue());
-                                virAttrCache.put(any.getType().getKey(), any.getKey(), schema.getKey(),
+                                virAttrCache.put(
+                                        any.getType().getKey(), any.getKey(), schema.getKey(),
                                         virAttrCacheValue);
                                 LOG.debug("Values for {} set in cache: {}", schema, virAttrCacheValue);
 
@@ -139,10 +142,23 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
         return result;
     }
 
-    @Transactional(readOnly = true)
     @Override
     public List<String> getValues(final Any<?> any, final VirSchema schema) {
-        if (!anyUtilsFactory.getInstance(any).getAllowedSchemas(any, VirSchema.class).contains(schema)) {
+        if (!anyUtilsFactory.getInstance(any).
+                getAllowedSchemas(any, VirSchema.class).forSelfContains(schema)) {
+
+            LOG.debug("{} not allowed for {}", schema, any);
+            return Collections.emptyList();
+        }
+
+        return ListUtils.emptyIfNull(getValues(any, Collections.singleton(schema)).get(schema));
+    }
+
+    @Override
+    public List<String> getValues(final Any<?> any, final Membership<?> membership, final VirSchema schema) {
+        if (!anyUtilsFactory.getInstance(any).
+                getAllowedSchemas(any, VirSchema.class).getForMembership(membership.getRightEnd()).contains(schema)) {
+
             LOG.debug("{} not allowed for {}", schema, any);
             return Collections.emptyList();
         }
@@ -150,9 +166,19 @@ public class VirAttrHandlerImpl implements VirAttrHandler {
         return ListUtils.emptyIfNull(getValues(any, Collections.singleton(schema)).get(schema));
     }
 
-    @Transactional(readOnly = true)
     @Override
     public Map<VirSchema, List<String>> getValues(final Any<?> any) {
-        return getValues(any, anyUtilsFactory.getInstance(any).getAllowedSchemas(any, VirSchema.class));
+        return getValues(
+                any,
+                anyUtilsFactory.getInstance(any).getAllowedSchemas(any, VirSchema.class).getForSelf());
     }
+
+    @Override
+    public Map<VirSchema, List<String>> getValues(final Any<?> any, final Membership<?> membership) {
+        return getValues(
+                any,
+                anyUtilsFactory.getInstance(any).getAllowedSchemas(any, VirSchema.class).
+                getForMembership(membership.getRightEnd()));
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index a144d67..0ccbe14 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -26,7 +26,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Transformer;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
@@ -41,6 +40,7 @@ import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.InvalidPlainAttrValueException;
 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
@@ -59,6 +59,7 @@ 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.group.Group;
 import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
 import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
@@ -73,6 +74,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.GroupablePlainAttr;
 import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Relationship;
@@ -88,6 +90,7 @@ import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.apache.syncope.core.persistence.api.entity.GroupableRelatable;
 
 abstract class AbstractAnyDataBinder {
 
@@ -150,7 +153,7 @@ abstract class AbstractAnyDataBinder {
     protected DerAttrHandler derAttrHandler;
 
     @Autowired
-    protected VirAttrHandler virAttrHander;
+    protected VirAttrHandler virAttrHandler;
 
     @Autowired
     protected ConnObjectUtils connObjectUtils;
@@ -186,20 +189,12 @@ abstract class AbstractAnyDataBinder {
         return schema;
     }
 
-    private DerSchema getDerSchema(final String derSchemaName) {
-        DerSchema schema = null;
-        if (StringUtils.isNotBlank(derSchemaName)) {
-            schema = derSchemaDAO.find(derSchemaName);
-            if (schema == null) {
-                LOG.debug("Ignoring invalid derived schema {}", derSchemaName);
-            }
-        }
-
-        return schema;
-    }
-
-    private void fillAttr(final List<String> values, final AnyUtils anyUtils,
-            final PlainSchema schema, final PlainAttr<?> attr, final SyncopeClientException invalidValues) {
+    private void fillAttr(
+            final List<String> values,
+            final AnyUtils anyUtils,
+            final PlainSchema schema,
+            final PlainAttr<?> attr,
+            final SyncopeClientException invalidValues) {
 
         // if schema is multivalue, all values are considered for addition;
         // otherwise only the fist one - if provided - is considered
@@ -210,7 +205,7 @@ abstract class AbstractAnyDataBinder {
                         : Collections.singletonList(values.iterator().next()));
 
         for (String value : valuesProvided) {
-            if (value == null || value.isEmpty()) {
+            if (StringUtils.isBlank(value)) {
                 LOG.debug("Null value for {}, ignoring", schema.getKey());
             } else {
                 try {
@@ -265,18 +260,37 @@ abstract class AbstractAnyDataBinder {
         return reqValMissing;
     }
 
+    private void checkMandatory(
+            final PlainSchema schema,
+            final PlainAttr<?> attr,
+            final Any<?> any,
+            final SyncopeClientException reqValMissing) {
+
+        if (attr == null
+                && !schema.isReadonly()
+                && JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any)) {
+
+            LOG.error("Mandatory schema " + schema.getKey() + " not provided with values");
+
+            reqValMissing.getElements().add(schema.getKey());
+        }
+    }
+
     private SyncopeClientException checkMandatory(final Any<?> any, final AnyUtils anyUtils) {
         SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
         // Check if there is some mandatory schema defined for which no value has been provided
-        for (PlainSchema schema : anyUtils.getAllowedSchemas(any, PlainSchema.class)) {
-            if (any.getPlainAttr(schema.getKey()) == null
-                    && !schema.isReadonly()
-                    && JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any)) {
-
-                LOG.error("Mandatory schema " + schema.getKey() + " not provided with values");
-
-                reqValMissing.getElements().add(schema.getKey());
+        AllowedSchemas<PlainSchema> allowedPlainSchemas = anyUtils.getAllowedSchemas(any, PlainSchema.class);
+        for (PlainSchema schema : allowedPlainSchemas.getForSelf()) {
+            checkMandatory(schema, any.getPlainAttr(schema.getKey()), any, reqValMissing);
+        }
+        for (Map.Entry<Group, Set<PlainSchema>> entry : allowedPlainSchemas.getForMemberships().entrySet()) {
+            if (any instanceof GroupableRelatable) {
+                GroupableRelatable<?, ?, ?, ?, ?> groupable = GroupableRelatable.class.cast(any);
+                Membership<?> membership = groupable.getMembership(entry.getKey().getKey());
+                for (PlainSchema schema : entry.getValue()) {
+                    checkMandatory(schema, groupable.getPlainAttr(schema.getKey(), membership), any, reqValMissing);
+                }
             }
         }
 
@@ -284,28 +298,16 @@ abstract class AbstractAnyDataBinder {
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    private void processAttrPatch(final Any any, final AttrPatch patch, final PlainSchema schema,
-            final AnyUtils anyUtils, final Set<ExternalResource> resources, final PropagationByResource propByRes,
+    protected void processAttrPatch(
+            final Any any,
+            final AttrPatch patch,
+            final PlainSchema schema,
+            final PlainAttr<?> attr,
+            final AnyUtils anyUtils,
+            final Set<ExternalResource> resources,
+            final PropagationByResource propByRes,
             final SyncopeClientException invalidValues) {
 
-        PlainAttr<?> attr = any.getPlainAttr(schema.getKey());
-        if (attr == null) {
-            LOG.debug("No plain attribute found for schema {}", schema);
-
-            switch (patch.getOperation()) {
-                case ADD_REPLACE:
-                    attr = anyUtils.newPlainAttr();
-                    ((PlainAttr) attr).setOwner(any);
-                    attr.setSchema(schema);
-                    any.add(attr);
-                    break;
-
-                case DELETE:
-                default:
-                    return;
-            }
-        }
-
         switch (patch.getOperation()) {
             case ADD_REPLACE:
                 // 1.1 remove values
@@ -317,14 +319,8 @@ abstract class AbstractAnyDataBinder {
                         plainAttrValueDAO.delete(attr.getUniqueValue().getKey(), anyUtils.plainAttrUniqueValueClass());
                     }
                 } else {
-                    Collection<String> valuesToBeRemoved = CollectionUtils.collect(attr.getValues(),
-                            new Transformer<PlainAttrValue, String>() {
-
-                        @Override
-                        public String transform(final PlainAttrValue input) {
-                            return input.getKey();
-                        }
-                    });
+                    Collection<String> valuesToBeRemoved =
+                            CollectionUtils.collect(attr.getValues(), EntityUtils.keyTransformer());
                     for (String attrValueKey : valuesToBeRemoved) {
                         plainAttrValueDAO.delete(attrValueKey, anyUtils.plainAttrValueClass());
                     }
@@ -347,13 +343,14 @@ abstract class AbstractAnyDataBinder {
 
             case DELETE:
             default:
-                any.getPlainAttrs().remove(attr);
+                any.remove(attr);
                 plainAttrDAO.delete(attr.getKey(), anyUtils.plainAttrClass());
         }
 
         for (ExternalResource resource : resources) {
-            for (MappingItem mapItem : MappingManagerImpl.getPropagationMappingItems(resource.
-                    getProvision(any.getType()))) {
+            for (MappingItem mapItem
+                    : MappingManagerImpl.getPropagationMappingItems(resource.getProvision(any.getType()))) {
+
                 if (schema.getKey().equals(mapItem.getIntAttrName())
                         && mapItem.getIntMappingType() == anyUtils.plainIntMappingType()) {
 
@@ -367,7 +364,11 @@ abstract class AbstractAnyDataBinder {
         }
     }
 
-    protected PropagationByResource fill(final Any<?> any, final AnyPatch anyPatch, final AnyUtils anyUtils,
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected PropagationByResource fill(
+            final Any any,
+            final AnyPatch anyPatch,
+            final AnyUtils anyUtils,
             final SyncopeClientCompositeException scce) {
 
         PropagationByResource propByRes = new PropagationByResource();
@@ -421,7 +422,21 @@ abstract class AbstractAnyDataBinder {
                     LOG.debug("Invalid " + PlainSchema.class.getSimpleName()
                             + "{}, ignoring...", patch.getAttrTO().getSchema());
                 } else {
-                    processAttrPatch(any, patch, schema, anyUtils, resources, propByRes, invalidValues);
+                    PlainAttr<?> attr = any.getPlainAttr(schema.getKey());
+                    if (attr == null) {
+                        LOG.debug("No plain attribute found for schema {}", schema);
+
+                        if (patch.getOperation() == PatchOperation.ADD_REPLACE) {
+                            attr = anyUtils.newPlainAttr();
+                            ((PlainAttr) attr).setOwner(any);
+                            attr.setSchema(schema);
+                            any.add(attr);
+
+                        }
+                    }
+                    if (attr != null) {
+                        processAttrPatch(any, patch, schema, attr, anyUtils, resources, propByRes, invalidValues);
+                    }
                 }
             }
         }
@@ -443,7 +458,10 @@ abstract class AbstractAnyDataBinder {
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     protected void fill(
-            final Any any, final AnyTO anyTO, final AnyUtils anyUtils, final SyncopeClientCompositeException scce) {
+            final Any any,
+            final AnyTO anyTO,
+            final AnyUtils anyUtils,
+            final SyncopeClientCompositeException scce) {
 
         // 0. aux classes
         any.getAuxClasses().clear();
@@ -459,9 +477,9 @@ abstract class AbstractAnyDataBinder {
         // 1. attributes
         SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
 
-        // Only consider attributeTO with values
         for (AttrTO attrTO : anyTO.getPlainAttrs()) {
-            if (attrTO.getValues() != null && !attrTO.getValues().isEmpty()) {
+            // Only consider attributeTO with values
+            if (!attrTO.getValues().isEmpty()) {
                 PlainSchema schema = getPlainSchema(attrTO.getSchema());
                 if (schema != null) {
                     PlainAttr attr = any.getPlainAttr(schema.getKey());
@@ -506,6 +524,44 @@ abstract class AbstractAnyDataBinder {
         }
     }
 
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    protected void fill(
+            final Any any,
+            final Membership membership,
+            final MembershipTO membershipTO,
+            final AnyUtils anyUtils,
+            final SyncopeClientCompositeException scce) {
+
+        SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
+
+        for (AttrTO attrTO : membershipTO.getPlainAttrs()) {
+            if (!attrTO.getValues().isEmpty()) {
+                PlainSchema schema = getPlainSchema(attrTO.getSchema());
+                if (schema != null) {
+                    GroupablePlainAttr attr = GroupableRelatable.class.cast(any).
+                            getPlainAttr(schema.getKey(), membership);
+                    if (attr == null) {
+                        attr = anyUtils.newPlainAttr();
+                        attr.setOwner(any);
+                        attr.setMembership(membership);
+                        attr.setSchema(schema);
+                    }
+                    fillAttr(attrTO.getValues(), anyUtils, schema, attr, invalidValues);
+
+                    if (attr.getValuesAsStrings().isEmpty()) {
+                        attr.setOwner(null);
+                    } else {
+                        any.add(attr);
+                    }
+                }
+            }
+        }
+
+        if (!invalidValues.isEmpty()) {
+            scce.addException(invalidValues);
+        }
+    }
+
     protected void fillTO(final AnyTO anyTO,
             final String realmFullPath,
             final Collection<? extends AnyTypeClass> auxClasses,
@@ -519,30 +575,27 @@ abstract class AbstractAnyDataBinder {
         CollectionUtils.collect(auxClasses, EntityUtils.<AnyTypeClass>keyTransformer(), anyTO.getAuxClasses());
 
         for (PlainAttr<?> plainAttr : plainAttrs) {
-            AttrTO attrTO = new AttrTO();
-            attrTO.setSchema(plainAttr.getSchema().getKey());
-            attrTO.getValues().addAll(plainAttr.getValuesAsStrings());
-            attrTO.setReadonly(plainAttr.getSchema().isReadonly());
-
-            anyTO.getPlainAttrs().add(attrTO);
+            anyTO.getPlainAttrs().add(new AttrTO.Builder().
+                    schema(plainAttr.getSchema().getKey()).
+                    values(plainAttr.getValuesAsStrings()).
+                    readonly(plainAttr.getSchema().isReadonly()).
+                    build());
         }
 
         for (Map.Entry<DerSchema, String> entry : derAttrs.entrySet()) {
-            AttrTO attrTO = new AttrTO();
-            attrTO.setSchema(entry.getKey().getKey());
-            attrTO.getValues().add(entry.getValue());
-            attrTO.setReadonly(true);
-
-            anyTO.getDerAttrs().add(attrTO);
+            anyTO.getDerAttrs().add(new AttrTO.Builder().
+                    schema(entry.getKey().getKey()).
+                    value(entry.getValue()).
+                    readonly(true).
+                    build());
         }
 
         for (Map.Entry<VirSchema, List<String>> entry : virAttrs.entrySet()) {
-            AttrTO attrTO = new AttrTO();
-            attrTO.setSchema(entry.getKey().getKey());
-            attrTO.getValues().addAll(entry.getValue());
-            attrTO.setReadonly(entry.getKey().isReadonly());
-
-            anyTO.getVirAttrs().add(attrTO);
+            anyTO.getVirAttrs().add(new AttrTO.Builder().
+                    schema(entry.getKey().getKey()).
+                    values(entry.getValue()).
+                    readonly(entry.getKey().isReadonly()).
+                    build());
         }
 
         for (ExternalResource resource : resources) {
@@ -553,16 +606,45 @@ abstract class AbstractAnyDataBinder {
     protected RelationshipTO getRelationshipTO(final Relationship<? extends Any<?>, AnyObject> relationship) {
         return new RelationshipTO.Builder().
                 type(relationship.getType().getKey()).
-                left(relationship.getLeftEnd().getType().getKey(), relationship.getLeftEnd().getKey()).
                 right(relationship.getRightEnd().getType().getKey(), relationship.getRightEnd().getKey()).
                 build();
     }
 
-    protected MembershipTO getMembershipTO(final Membership<? extends Any<?>> membership) {
-        return new MembershipTO.Builder().
-                left(membership.getLeftEnd().getType().getKey(), membership.getLeftEnd().getKey()).
+    protected MembershipTO getMembershipTO(
+            final Collection<? extends PlainAttr<?>> plainAttrs,
+            final Map<DerSchema, String> derAttrs,
+            final Map<VirSchema, List<String>> virAttrs,
+            final Membership<? extends Any<?>> membership) {
+
+        MembershipTO membershipTO = new MembershipTO.Builder().
                 group(membership.getRightEnd().getKey(), membership.getRightEnd().getName()).
                 build();
+
+        for (PlainAttr<?> plainAttr : plainAttrs) {
+            membershipTO.getPlainAttrs().add(new AttrTO.Builder().
+                    schema(plainAttr.getSchema().getKey()).
+                    values(plainAttr.getValuesAsStrings()).
+                    readonly(plainAttr.getSchema().isReadonly()).
+                    build());
+        }
+
+        for (Map.Entry<DerSchema, String> entry : derAttrs.entrySet()) {
+            membershipTO.getDerAttrs().add(new AttrTO.Builder().
+                    schema(entry.getKey().getKey()).
+                    value(entry.getValue()).
+                    readonly(true).
+                    build());
+        }
+
+        for (Map.Entry<VirSchema, List<String>> entry : virAttrs.entrySet()) {
+            membershipTO.getVirAttrs().add(new AttrTO.Builder().
+                    schema(entry.getKey().getKey()).
+                    values(entry.getValue()).
+                    readonly(entry.getKey().isReadonly()).
+                    build());
+        }
+
+        return membershipTO;
     }
 
     protected Map<String, String> getConnObjectKeys(final Any<?> any) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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 1c1e75c..1df71a4 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
@@ -162,7 +162,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
 
         List<Task> tasks = engine.getTaskService().createTaskQuery().processInstanceId(user.getWorkflowId()).list();
         if (tasks.isEmpty() || tasks.size() > 1) {
-            LOG.warn("While checking if form task: unexpected task number ({})", tasks.size());
+            LOG.debug("While checking if form task: unexpected task number ({})", tasks.size());
         } else {
             try {
                 TaskFormData formData = engine.getFormService().getTaskFormData(tasks.get(0).getId());

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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 79f3bd9..05d9898 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/acce340d/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/acce340d/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..38b3631
--- /dev/null
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MembershipITCase.java
@@ -0,0 +1,206 @@
+/*
+ * 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.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.TypeExtensionTO;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+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());
+    }
+
+    @Test
+    public void onGroupDelete() {
+        // pre: create group with type extension
+        TypeExtensionTO typeExtension = new TypeExtensionTO();
+        typeExtension.setAnyType(AnyTypeKind.USER.name());
+        typeExtension.getAuxClasses().add("csv");
+        typeExtension.getAuxClasses().add("other");
+
+        GroupTO groupTO = GroupITCase.getBasicSampleTO("typeExt");
+        groupTO.getTypeExtensions().add(typeExtension);
+        groupTO = createGroup(groupTO).getAny();
+        assertNotNull(groupTO);
+
+        // pre: create user with membership to such group
+        UserTO user = UserITCase.getUniqueSampleTO("typeExt@apache.org");
+
+        MembershipTO membership = new MembershipTO.Builder().group(groupTO.getKey()).build();
+        membership.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("1454").build());
+        user.getMemberships().add(membership);
+
+        user = createUser(user).getAny();
+
+        // verify that 'aLong' is correctly populated for user's membership
+        assertEquals(1, user.getMemberships().size());
+        membership = user.getMembershipMap().get(groupTO.getKey());
+        assertNotNull(membership);
+        assertEquals(1, membership.getPlainAttrMap().get("aLong").getValues().size());
+        assertEquals("1454", membership.getPlainAttrMap().get("aLong").getValues().get(0));
+
+        // 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());
+
+        // now remove the group -> all related memberships should have been removed as well
+        groupService.delete(groupTO.getKey());
+
+        // re-read user and verify that no memberships are available any more
+        user = userService.read(user.getKey());
+        assertTrue(user.getMemberships().isEmpty());
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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/acce340d/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);
   }


[11/15] syncope git commit: [SYNCOPE-862] Features complete

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_ru.properties
index 302a798..46e6700 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/pages/Notifications_ru.properties
@@ -15,55 +15,51 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-# notifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f
+# notifications=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f
 notifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f
-# notification.templates=\u0428\u0430\u0431\u043b\u043e\u043d\u044b
+# notification.templates=\u00d0\u00a8\u00d0\u00b0\u00d0\u00b1\u00d0\u00bb\u00d0\u00be\u00d0\u00bd\u00d1\u008b
 notification.templates=\u0428\u0430\u0431\u043b\u043e\u043d\u044b
 
-# sender=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c
+# sender=\u00d0\u009e\u00d1\u0082\u00d0\u00bf\u00d1\u0080\u00d0\u00b0\u00d0\u00b2\u00d0\u00b8\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c
 sender=\u041e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u0435\u043b\u044c
-# template=\u0428\u0430\u0431\u043b\u043e\u043d
+# template=\u00d0\u00a8\u00d0\u00b0\u00d0\u00b1\u00d0\u00bb\u00d0\u00be\u00d0\u00bd
 template=\u0428\u0430\u0431\u043b\u043e\u043d
-# traceLevel=\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435
+# traceLevel=\u00d0\u009b\u00d0\u00be\u00d0\u00b3\u00d0\u00b8\u00d1\u0080\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 traceLevel=\u041b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435
-# notification=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
+# notification=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 notification=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
-# about=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e
+# about=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00be
 about=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e
-# events=\u0421\u043e\u0431\u044b\u0442\u0438\u044f
+# events=\u00d0\u00a1\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d1\u008f
 events=\u0421\u043e\u0431\u044b\u0442\u0438\u044f
-# selfAsRecipient=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
+# selfAsRecipient=\u00d0\u0092\u00d0\u00ba\u00d0\u00bb\u00d1\u008e\u00d1\u0087\u00d0\u00b8\u00d1\u0082\u00d1\u008c \u00d0\u00b2 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b8 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9, \u00d0\u00be \u00d0\u00ba\u00d0\u00be\u00d1\u0082\u00d0\u00be\u00d1\u0080\u00d1\u008b\u00d1\u0085 \u00d1\u0080\u00d0\u00b0\u00d1\u0081\u00d1\u0081\u00d1\u008b\u00d0\u00bb\u00d0\u00b0\u00d0\u00b5\u00d1\u0082\u00d1\u0081\u00d1\u008f \u00d1\u0083\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5
 selfAsRecipient=\u0412\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0432 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0440\u0430\u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435
-# recipientAttrType=\u0422\u0438\u043f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-recipientAttrType=\u0422\u0438\u043f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-recipientAttrName=\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u0441 \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# checkRecipients=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
+# checkRecipients=\u00d0\u009f\u00d0\u00be\u00d0\u00b8\u00d1\u0081\u00d0\u00ba \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u0083\u00d1\u0087\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 checkRecipients=\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u0435\u0439
-# checkAbout=\u041e\u0431\u043e \u0432\u0441\u0451\u043c
+# checkAbout=\u00d0\u009e\u00d0\u00b1\u00d0\u00be \u00d0\u00b2\u00d1\u0081\u00d1\u0091\u00d0\u00bc
 checkAbout=\u041e\u0431\u043e \u0432\u0441\u0451\u043c
-# userFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userFilter=\u00d0\u00a4\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# userFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userFilterWarning=\u00d0\u009d\u00d0\u00b5 \u00d0\u00b8\u00d1\u0081\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d1\u0083\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# userNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userNotifications=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# userNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
+# userNotificationsWarning=\u00d0\u009d\u00d0\u00b5 \u00d1\u0083\u00d1\u0081\u00d1\u0082\u00d0\u00b0\u00d0\u00bd\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b8\u00d0\u00b2\u00d0\u00b0\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00bb\u00d0\u00b0\u00d0\u00b6\u00d0\u00be\u00d0\u00ba, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 userNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439
-# roleFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u043e\u043b\u0435\u0439
+# roleFilter=\u00d0\u00a4\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080 \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleFilter=\u0424\u0438\u043b\u044c\u0442\u0440 \u0440\u043e\u043b\u0435\u0439
-# roleFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
+# roleFilterWarning=\u00d0\u009d\u00d0\u00b5 \u00d0\u00b8\u00d1\u0081\u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d1\u0083\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00b8\u00d0\u00bb\u00d1\u008c\u00d1\u0082\u00d1\u0080, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleFilterWarning=\u041d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u0438\u043b\u044c\u0442\u0440, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
-# roleNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u043e\u043b\u0435\u0439
+# roleNotifications=\u00d0\u00a3\u00d0\u00b2\u00d0\u00b5\u00d0\u00b4\u00d0\u00be\u00d0\u00bc\u00d0\u00bb\u00d0\u00b5\u00d0\u00bd\u00d0\u00b8\u00d1\u008f \u00d0\u00bd\u00d0\u00b0 \u00d0\u00be\u00d1\u0081\u00d0\u00bd\u00d0\u00be\u00d0\u00b2\u00d0\u00b5 \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleNotifications=\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u043e\u043b\u0435\u0439
-# roleNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0436\u043e\u043a, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
+# roleNotificationsWarning=\u00d0\u009d\u00d0\u00b5 \u00d1\u0083\u00d1\u0081\u00d1\u0082\u00d0\u00b0\u00d0\u00bd\u00d0\u00b0\u00d0\u00b2\u00d0\u00bb\u00d0\u00b8\u00d0\u00b2\u00d0\u00b0\u00d0\u00b9\u00d1\u0082\u00d0\u00b5 \u00d1\u008d\u00d1\u0082\u00d0\u00be\u00d1\u0082 \u00d1\u0084\u00d0\u00bb\u00d0\u00b0\u00d0\u00b6\u00d0\u00be\u00d0\u00ba, \u00d0\u00b5\u00d1\u0081\u00d0\u00bb\u00d0\u00b8 \u00d1\u0081\u00d0\u00be\u00d0\u00b1\u00d1\u008b\u00d1\u0082\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bd\u00d0\u00b5 \u00d0\u00bf\u00d1\u0080\u00d0\u00b5\u00d0\u00b4\u00d0\u00bd\u00d0\u00b0\u00d0\u00b7\u00d0\u00bd\u00d0\u00b0\u00d1\u0087\u00d0\u00b5\u00d0\u00bd\u00d0\u00be \u00d0\u00b4\u00d0\u00bb\u00d1\u008f \u00d1\u0080\u00d0\u00be\u00d0\u00bb\u00d0\u00b5\u00d0\u00b9
 roleNotificationsWarning=\u041d\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e\u0442 \u0444\u043b\u0430\u0433, \u0435\u0441\u043b\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043d\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439
-# isActive=\u0410\u043a\u0442\u0438\u0432\u043d\u043e
+# isActive=\u00d0\u0090\u00d0\u00ba\u00d1\u0082\u00d0\u00b8\u00d0\u00b2\u00d0\u00bd\u00d0\u00be
 isActive=\u0410\u043a\u0442\u0438\u0432\u043d\u043e
-# checkUserAbout=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438
+# checkUserAbout=\u00d0\u009f\u00d0\u00be\u00d0\u00bb\u00d1\u008c\u00d0\u00b7\u00d0\u00be\u00d0\u00b2\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d0\u00b8
 checkUserAbout=\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438
-# checkRoleAbout=\u0420\u043e\u043b\u0438
+# checkRoleAbout=\u00d0\u00a0\u00d0\u00be\u00d0\u00bb\u00d0\u00b8
 checkRoleAbout=\u0420\u043e\u043b\u0438
 
-# active=\u0410\u043a\u0442\u0438\u0432\u043d\u043e
+# active=\u00d0\u0090\u00d0\u00ba\u00d1\u0082\u00d0\u00b8\u00d0\u00b2\u00d0\u00bd\u00d0\u00be
 active=\u0410\u043a\u0442\u0438\u0432\u043d\u043e

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.html b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.html
index 2aa106b..ea3ddc4 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.html
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceMappingPanel.html
@@ -27,15 +27,16 @@ under the License.
                wicket:id="mappingContainer">
           <tbody>
             <tr>
-              <th><wicket:message key="entity"/></th>
-              <th><wicket:message key="intMappingTypes"/></th>
-              <th><wicket:message key="intAttrNames"/></th>
-              <th><wicket:message key="extAttrNames"/></th>
+              <th>
+                <wicket:message key="intAttrName"/>
+                <span id="intAttrNameInfo" wicket:id="intAttrNameInfo" class="glyphicon glyphicon-info-sign"></span>
+              </th>
+              <th><wicket:message key="extAttrName"/></th>
               <th><i class="fa fa-repeat"></i></th>
               <th><i class="fa fa-magic"></i></th>
               <th>
                 <wicket:message key="mandatoryCondition"/>
-                <span id="popover" wicket:id="jexlInfo" class="glyphicon glyphicon-info-sign"></span>
+                <span id="jexlInfo" wicket:id="jexlInfo" class="glyphicon glyphicon-info-sign"></span>
               </th>
               <th><wicket:message key="connObjectKey"/></th>
               <th><label wicket:id="passwordLabel"/></th>
@@ -44,13 +45,7 @@ under the License.
             </tr>
             <tr wicket:id="mappings">
               <td>
-                <span wicket:id="entities">[entities]</span>
-              </td>
-              <td>
-                <span wicket:id="intMappingTypes">[intMappingTypes]</span>
-              </td>
-              <td>
-                <span wicket:id="intAttrNames">[intAttrNames]</span>
+                <span wicket:id="intAttrName">[intAttrNames]</span>
               </td>
               <td>
                 <span wicket:id="extAttrName">[extAttrName]</span>

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.properties
index 51201d4..d9e6f1f 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel.properties
@@ -20,8 +20,7 @@ __ACCOUNT__=ACCOUNT
 __GROUP__=GROUP
 auxClasses=Auxiliary Classes
 
-extAttrNames=External attributes
-intMappingTypes=Internal mapping types
+extAttrName=External attribute
 entity=Entity
 groupSchema=Role Schema
 connObjectKey=Remote Key
@@ -32,7 +31,7 @@ purpose=Purpose
 mappingUserSchema=Mapping User Schema
 mappingGroupSchema=Mapping Role Schema
 delete=Delete
-intAttrNames=Internal attributes
+intAttrName=Internal attribute
 enforceMandatoryCondition=Enforce mandatory condition
 fieldName=Field name
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_it.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_it.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_it.properties
index bf69414..abaf81f 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_it.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_it.properties
@@ -20,8 +20,7 @@ __ACCOUNT__=ACCOUNT
 __GROUP__=GROUP
 auxClasses=Classi Ausiliarie
 
-extAttrNames=Attributi esterni
-intMappingTypes=Tipo mapping interno
+extAttrName=Attributo esterno
 entity=Entit&agrave;
 groupSchema=Schema Ruolo
 connObjectKey=Chiave remota
@@ -32,7 +31,7 @@ purpose=Scopo
 mappingUserSchema=Mapping User Schema
 mappingGroupSchema=Mapping Role Schema
 delete=Rimuovi
-intAttrNames=Attributi interni
+intAttrName=Attributo interno
 enforceMandatoryCondition=Abilita mandatory condition
 fieldName=Nome campo
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_pt_BR.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_pt_BR.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_pt_BR.properties
index edf80c1..ec9a6b6 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_pt_BR.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_pt_BR.properties
@@ -20,8 +20,7 @@ __ACCOUNT__=ACCOUNT
 __GROUP__=GROUP
 auxClasses=Classes Auxiliares
 
-extAttrNames=Atributos Externos
-intMappingTypes=Tipos internos de mapeamentos
+extAttrName=Atributo Externo
 entity=Entidade
 groupSchema=Esquema de Fun\u00e7\u00e3o
 connObjectKey=Remote Key
@@ -32,7 +31,7 @@ purpose=Prop\u00f3sito
 mappingUserSchema=Esquema de mapeamento de usu\u00e1rio
 mappingGroupSchema=Esquema de mapeamento de fun\u00e7\u00e3o
 delete=Excluir
-intAttrNames=Atributos internos
+intAttrName=Atributo interno
 enforceMandatoryCondition=Aplicar condi\u00e7\u00e3o obrigat\u00f3ria
 fieldName=Nome do Campo
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_ru.properties
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_ru.properties b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_ru.properties
index ca685ce..6733ef9 100644
--- a/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_ru.properties
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/wizards/resources/ResourceProvisionPanel_ru.properties
@@ -27,9 +27,7 @@ __GROUP__=\u0413\u0420\u0423\u041f\u041f\u0410
 auxClasses=\u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b
 
 # extAttrNames=\u00d0\u0092\u00d0\u00bd\u00d0\u00b5\u00d1\u0088\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00b0\u00d1\u0082\u00d1\u0080\u00d0\u00b8\u00d0\u00b1\u00d1\u0083\u00d1\u0082\u00d1\u008b
-extAttrNames=\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
-# intMappingTypes=\u00d0\u00a2\u00d0\u00b8\u00d0\u00bf \u00d0\u00b2\u00d0\u00bd\u00d1\u0083\u00d1\u0082\u00d1\u0080\u00d0\u00b5\u00d0\u00bd\u00d0\u00bd\u00d0\u00b5\u00d0\u00b3\u00d0\u00be \u00d0\u00bc\u00d0\u00b0\u00d0\u00bf\u00d0\u00bf\u00d0\u00b8\u00d0\u00bd\u00d0\u00b3\u00d0\u00b0
-intMappingTypes=\u0422\u0438\u043f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0430
+extAttrName=\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
 # entity=\u00d0\u009e\u00d0\u00b1\u00d1\u008a\u00d0\u00b5\u00d0\u00ba\u00d1\u0082
 entity=\u041e\u0431\u044a\u0435\u043a\u0442
 # groupSchema=\u00d0\u0090\u00d1\u0082\u00d1\u0080\u00d0\u00b8\u00d0\u00b1\u00d1\u0083\u00d1\u0082 \u00d0\u00b3\u00d1\u0080\u00d1\u0083\u00d0\u00bf\u00d0\u00bf\u00d1\u008b
@@ -50,7 +48,7 @@ mappingGroupSchema=\u041c\u0430\u043f\u043f\u0438\u043d\u0433 \u0430\u0442\u0440
 # delete=\u00d0\u00a3\u00d0\u00b4\u00d0\u00b0\u00d0\u00bb\u00d0\u00b8\u00d1\u0082\u00d1\u008c
 delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c
 # intAttrNames=\u00d0\u0092\u00d0\u00bd\u00d1\u0083\u00d1\u0082\u00d1\u0080\u00d0\u00b5\u00d0\u00bd\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00b0\u00d1\u0082\u00d1\u0080\u00d0\u00b8\u00d0\u00b1\u00d1\u0083\u00d1\u0082\u00d1\u008b
-intAttrNames=\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
+intAttrName=\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b
 # enforceMandatoryCondition=\u00d0\u009e\u00d0\u00b1\u00d1\u008f\u00d0\u00b7\u00d0\u00b0\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c\u00d0\u00bd\u00d1\u008b\u00d0\u00b9 (\u00d0\u00bf\u00d1\u0080\u00d0\u00b8\u00d0\u00bd\u00d1\u0083\u00d0\u00b4\u00d0\u00b8\u00d1\u0082\u00d0\u00b5\u00d0\u00bb\u00d1\u008c\u00d0\u00bd\u00d0\u00be)
 enforceMandatoryCondition=\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 (\u043f\u0440\u0438\u043d\u0443\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e)
 # fieldName=\u00d0\u009d\u00d0\u00b0\u00d0\u00b7\u00d0\u00b2\u00d0\u00b0\u00d0\u00bd\u00d0\u00b8\u00d0\u00b5 \u00d0\u00bf\u00d0\u00be\u00d0\u00bb\u00d1\u008f

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 d0bf7d4..81a445a 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
@@ -33,7 +33,7 @@ import org.apache.commons.lang3.tuple.Pair;
 
 @XmlRootElement(name = "anyObject")
 @XmlType
-public class AnyObjectTO extends AnyTO implements RelatableTO, GroupableTO {
+public class AnyObjectTO extends AnyTO implements GroupableRelatableTO {
 
     private static final long serialVersionUID = 8841697496476959639L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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
new file mode 100644
index 0000000..09bc7e6
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableRelatableTO.java
@@ -0,0 +1,36 @@
+/*
+ * 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.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();
+
+    List<MembershipTO> getMemberships();
+
+    List<String> getDynGroups();
+
+    Map<Pair<String, String>, RelationshipTO> getRelationshipMap();
+
+    List<RelationshipTO> getRelationships();
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableTO.java
deleted file mode 100644
index 7b6a824..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupableTO.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.common.lib.to;
-
-import java.util.List;
-import java.util.Map;
-
-public interface GroupableTO {
-
-    Map<String, MembershipTO> getMembershipMap();
-
-    List<MembershipTO> getMemberships();
-
-    List<String> getDynGroups();
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelatableTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelatableTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelatableTO.java
deleted file mode 100644
index 1914c13..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelatableTO.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.common.lib.to;
-
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.lang3.tuple.Pair;
-
-public interface RelatableTO {
-
-    Map<Pair<String, String>, RelationshipTO> getRelationshipMap();
-
-    List<RelationshipTO> getRelationships();
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 77fd1c9..4ec8181 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
@@ -38,7 +38,7 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "user")
 @XmlType
-public class UserTO extends AnyTO implements RelatableTO, GroupableTO {
+public class UserTO extends AnyTO implements GroupableRelatableTO {
 
     private static final long serialVersionUID = 7791304495192615740L;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index 915d8ff..361c4e9 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -50,7 +50,6 @@ import org.apache.syncope.core.provisioning.api.Connector;
 import org.apache.syncope.core.provisioning.api.ConnectorFactory;
 import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ConnInstanceDAO;
@@ -62,6 +61,7 @@ import org.apache.syncope.core.persistence.api.entity.ConnInstance;
 import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.api.MappingManager;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
@@ -276,7 +276,7 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
         }
 
         // 2. build connObjectKeyItem
-        MappingItem connObjectKeyItem = MappingManagerImpl.getConnObjectKeyItem(init.getRight());
+        MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(init.getRight());
         if (connObjectKeyItem == null) {
             throw new NotFoundException(
                     "ConnObjectKey mapping for " + init.getMiddle() + " " + anyKey + " on resource '" + key + "'");
@@ -296,7 +296,7 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
         Connector connector = connFactory.getConnector(init.getLeft());
         ConnectorObject connectorObject = connector.getObject(init.getRight().getObjectClass(),
                 new Uid(connObjectKeyValue),
-                MappingManagerImpl.buildOperationOptions(mapItems));
+                MappingUtils.buildOperationOptions(mapItems));
         if (connectorObject == null) {
             throw new NotFoundException(
                     "Object " + connObjectKeyValue + " with class " + init.getRight().getObjectClass()

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReconciliationReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReconciliationReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReconciliationReportlet.java
index 2fb56da..9490c32 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReconciliationReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/ReconciliationReportlet.java
@@ -37,7 +37,6 @@ import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
 import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
@@ -59,6 +58,7 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.Connector;
 import org.apache.syncope.core.provisioning.api.ConnectorFactory;
 import org.apache.syncope.core.provisioning.api.MappingManager;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
@@ -271,7 +271,7 @@ public class ReconciliationReportlet extends AbstractReportlet {
             AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
             for (final ExternalResource resource : anyUtils.getAllResources(any)) {
                 Provision provision = resource.getProvision(any.getType());
-                MappingItem connObjectKeyItem = MappingManagerImpl.getConnObjectKeyItem(provision);
+                MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
                 final String connObjectKeyValue = connObjectKeyItem == null
                         ? StringUtils.EMPTY
                         : mappingManager.getConnObjectKeyValue(any, provision);
@@ -280,7 +280,7 @@ public class ReconciliationReportlet extends AbstractReportlet {
                     Connector connector = connFactory.getConnector(resource);
                     ConnectorObject connectorObject = connector.getObject(provision.getObjectClass(),
                             new Uid(connObjectKeyValue),
-                            MappingManagerImpl.buildOperationOptions(provision.getMapping().getItems().iterator()));
+                            MappingUtils.buildOperationOptions(provision.getMapping().getItems().iterator()));
 
                     if (connectorObject == null) {
                         // 2. not found on resource?

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
index 6a51d79..76ce8ed 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
@@ -25,7 +25,7 @@ import org.apache.syncope.core.persistence.api.entity.Schema;
 
 public interface SchemaDAO<S extends Schema> extends DAO<S> {
 
-    S find(String name);
+    S find(String key);
 
     List<S> findByAnyTypeClasses(Collection<AnyTypeClass> anyTypeClasses);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
index b13b19d..99b9d22 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAnyUtils.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity;
 
 import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
@@ -75,15 +76,15 @@ public class JPAAnyUtils implements AnyUtils {
 
     private static void initFieldNames(final Class<?> entityClass, final Set<String> keys) {
         List<Class<?>> classes = ClassUtils.getAllSuperclasses(entityClass);
-        if (!classes.contains(JPAUser.class)) {
-            classes.add(JPAUser.class);
-        }
+        classes.add(entityClass);
         for (Class<?> clazz : classes) {
             for (Field field : clazz.getDeclaredFields()) {
-                if (!Collection.class.isAssignableFrom(field.getType())
+                if (!Modifier.isStatic(field.getModifiers())
+                        && !field.getName().startsWith("pc")
+                        && !Collection.class.isAssignableFrom(field.getType())
                         && !Map.class.isAssignableFrom(field.getType())) {
 
-                    keys.add(field.getName());
+                    keys.add("id".equals(field.getName()) ? "key" : field.getName());
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 7c89dec..47dac59 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -52,13 +52,13 @@ public class JPAMappingItem extends AbstractGeneratedKeyEntity implements Mappin
     @ManyToOne
     private JPAMapping mapping;
 
-    @Column(nullable = true)
+    @NotNull
     private String intAttrName;
 
     /**
      * Target resource's field to be mapped.
      */
-    @Column(nullable = true)
+    @NotNull
     private String extAttrName;
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
index 99a8ec8..b8f2cab 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/ExternalResourceValidator.java
@@ -23,115 +23,19 @@ import java.util.Set;
 import javax.validation.ConstraintValidatorContext;
 import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.common.lib.types.SchemaType;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
-import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
-import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
 import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
 import org.identityconnectors.framework.common.objects.ObjectClass;
 
 public class ExternalResourceValidator extends AbstractValidator<ExternalResourceCheck, ExternalResource> {
 
-    private static final AnyUtilsFactory ANY_UTILS_FACTORY = new JPAAnyUtilsFactory();
-
-    private boolean isValid(final MappingItem item, final ConstraintValidatorContext context) {
-        if (StringUtils.isBlank(item.getExtAttrName())) {
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + " - extAttrName is null")).
-                    addPropertyNode("extAttrName").addConstraintViolation();
-
-            return false;
-        }
-
-        if (item.getPurpose() == null) {
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + " - purpose is null")).
-                    addPropertyNode("purpose").addConstraintViolation();
-
-            return false;
-        }
-
-        if (StringUtils.isBlank(item.getIntAttrName())) {
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + " - intAttrName is null")).
-                    addPropertyNode("intAttrName").addConstraintViolation();
-
-            return false;
-        }
-
-        IntAttrName intAttrName = null;
-        try {
-            intAttrName = IntAttrNameParser.parse(
-                    item.getIntAttrName(),
-                    ANY_UTILS_FACTORY,
-                    item.getMapping().getProvision().getAnyType().getKind());
-        } catch (IllegalArgumentException e) {
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping, item + " - " + e.getMessage())).
-                    addPropertyNode("intAttrName").addConstraintViolation();
-
-            return false;
-        }
-
-        if (intAttrName.getSchemaType() == SchemaType.DERIVED
-                && item.getPurpose() != MappingPurpose.PROPAGATION) {
-
-            context.buildConstraintViolationWithTemplate(
-                    getTemplate(EntityViolationType.InvalidMapping,
-                            " - only " + MappingPurpose.PROPAGATION.name() + " allowed for derived")).
-                    addPropertyNode("purpose").addConstraintViolation();
-
-            return false;
-        }
-
-        if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
-            if (item.getPurpose() != MappingPurpose.PROPAGATION) {
-                context.buildConstraintViolationWithTemplate(
-                        getTemplate(EntityViolationType.InvalidMapping,
-                                " - only " + MappingPurpose.PROPAGATION.name() + " allowed for virtual")).
-                        addPropertyNode("purpose").addConstraintViolation();
-
-                return false;
-            }
-
-            if (item.getMapping() == null) {
-                context.buildConstraintViolationWithTemplate(
-                        getTemplate(EntityViolationType.InvalidMapping,
-                                " - need to explicitly set mapping for further checks")).
-                        addPropertyNode("mapping").addConstraintViolation();
-
-                return false;
-            }
-
-            VirSchema schema = ApplicationContextProvider.getBeanFactory().getBean(VirSchemaDAO.class).
-                    find(item.getIntAttrName());
-            if (schema != null && schema.getProvision().equals(item.getMapping().getProvision())) {
-                context.buildConstraintViolationWithTemplate(
-                        getTemplate(EntityViolationType.InvalidMapping,
-                                " - no need to map virtual schema on linking resource")).
-                        addPropertyNode("intAttrName").addConstraintViolation();
-
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    private boolean isValid(final AnyType anyType, final Mapping mapping, final ConstraintValidatorContext context) {
+    private boolean isValid(final Mapping mapping, final ConstraintValidatorContext context) {
         if (mapping == null) {
             return true;
         }
@@ -154,8 +58,6 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
 
         int passwords = 0;
         for (MappingItem item : mapping.getItems()) {
-            isValid &= isValid(item, context);
-
             if (item.isPassword()) {
                 passwords++;
             }
@@ -232,7 +134,7 @@ public class ExternalResourceValidator extends AbstractValidator<ExternalResourc
                 if (provision.getObjectClass() != null) {
                     objectClasses.add(provision.getObjectClass().getObjectClassValue());
                 }
-                return isValid(provision.getAnyType(), provision.getMapping(), context);
+                return isValid(provision.getMapping(), context);
             }
         });
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
index e08833f..47636de 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ResourceTest.java
@@ -159,32 +159,6 @@ public class ResourceTest extends AbstractTest {
         resourceDAO.save(resource);
     }
 
-    @Test(expected = IllegalArgumentException.class)
-    public void saveInvalidConnObjectKeyMapping() {
-        ExternalResource resource = entityFactory.newEntity(ExternalResource.class);
-        resource.setKey("ws-target-resource-basic-save-invalid");
-
-        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
-        resource.setConnector(connector);
-
-        Provision provision = entityFactory.newEntity(Provision.class);
-        provision.setAnyType(anyTypeDAO.findUser());
-        provision.setObjectClass(ObjectClass.ACCOUNT);
-        provision.setResource(resource);
-        resource.add(provision);
-
-        Mapping mapping = entityFactory.newEntity(Mapping.class);
-        mapping.setProvision(provision);
-        provision.setMapping(mapping);
-
-        MappingItem connObjectKey = entityFactory.newEntity(MappingItem.class);
-        connObjectKey.setConnObjectKey(true);
-        mapping.setConnObjectKeyItem(connObjectKey);
-
-        // save the resource
-        resourceDAO.save(resource);
-    }
-
     @Test(expected = InvalidEntityException.class)
     public void saveInvalidMappingExtAttr() {
         ExternalResource resource = entityFactory.newEntity(ExternalResource.class);
@@ -274,21 +248,13 @@ public class ResourceTest extends AbstractTest {
         MappingItem virtualMapItem = entityFactory.newEntity(MappingItem.class);
         virtualMapItem.setIntAttrName("virtualReadOnly");
         virtualMapItem.setExtAttrName("TEST");
-        virtualMapItem.setPurpose(MappingPurpose.BOTH);
+        virtualMapItem.setPurpose(MappingPurpose.PROPAGATION);
         virtualMapItem.setMapping(mapping);
         mapping.add(virtualMapItem);
 
         ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
         resource.setConnector(connector);
 
-        try {
-            resourceDAO.save(resource);
-            fail();
-        } catch (InvalidEntityException e) {
-            assertNotNull(e);
-        }
-
-        virtualMapItem.setPurpose(MappingPurpose.PROPAGATION);
         resourceDAO.save(resource);
     }
 
@@ -358,33 +324,4 @@ public class ResourceTest extends AbstractTest {
             assertTrue(e.hasViolation(EntityViolationType.InvalidKey));
         }
     }
-
-    @Test(expected = InvalidEntityException.class)
-    public void issueSYNCOPE645() {
-        ExternalResource resource = entityFactory.newEntity(ExternalResource.class);
-        resource.setKey("ws-target-resource-basic-save-invalid");
-
-        ConnInstance connector = resourceDAO.find("ws-target-resource-1").getConnector();
-        resource.setConnector(connector);
-
-        Provision provision = entityFactory.newEntity(Provision.class);
-        provision.setAnyType(anyTypeDAO.findUser());
-        provision.setObjectClass(ObjectClass.ACCOUNT);
-        provision.setResource(resource);
-        resource.add(provision);
-
-        Mapping mapping = entityFactory.newEntity(Mapping.class);
-        mapping.setProvision(provision);
-        provision.setMapping(mapping);
-
-        final MappingItem item = entityFactory.newEntity(MappingItem.class);
-        item.setIntAttrName("icon");
-        item.setExtAttrName("icon");
-        item.setPurpose(MappingPurpose.BOTH);
-        mapping.setConnObjectKeyItem(item);
-
-        // save the resource
-        ExternalResource actual = resourceDAO.save(resource);
-        assertNotNull(actual);
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
index efe2349..614033c 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/ResourceTest.java
@@ -295,6 +295,7 @@ public class ResourceTest extends AbstractTest {
         int origMapItems = csv.getProvision(anyTypeDAO.findUser()).getMapping().getItems().size();
 
         MappingItem newMapItem = entityFactory.newEntity(MappingItem.class);
+        newMapItem.setIntAttrName("TEST");
         newMapItem.setExtAttrName("TEST");
         newMapItem.setPurpose(MappingPurpose.PROPAGATION);
         csv.getProvision(anyTypeDAO.findUser()).getMapping().add(newMapItem);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 2ff3310..621ed82 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -898,10 +898,7 @@ under the License.
                intAttrName="csvuserid" mandatoryCondition="true"
                connObjectKey="1" password="0" purpose="PROPAGATION"/>
   <MappingItem id="63151b89-2eb3-4980-a682-0215d54ab4a2" extAttrName="theirgroup" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="rderToBePropagated" mandatoryCondition="false"
-               connObjectKey="0" password="0" purpose="PROPAGATION"/>
-  <MappingItem id="b6079a7b-ac40-481d-81c9-2a292bab0092" extAttrName="membership" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
-               intAttrName="mderToBePropagated" mandatoryCondition="false"
+               intAttrName="groups[root].rderToBePropagated" mandatoryCondition="false"
                connObjectKey="0" password="0" purpose="PROPAGATION"/>
                          
   <Provision id="1b53c74e-6a63-49ef-b2f1-96eeb7f1bbb8" resource_id="ws-target-resource-update-resetsynctoken" anyType_id="USER" objectClass="__ACCOUNT__"
@@ -920,10 +917,10 @@ under the License.
   <Mapping id="ae1c77c3-2f1d-4258-ad06-710bb09041a9" provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8"
            connObjectLink="&apos;uid=&apos; + username + &apos;,ou=people,o=isp&apos;"/>
   <MappingItem id="9ff7d686-452c-4cec-a475-c1137c5d88c7" connObjectKey="1" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="cn" intAttrName="Username" intAttrName="username"
+               extAttrName="cn" intAttrName="username"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="73d97083-cfda-44e6-be62-3f9ac558b5eb" connObjectKey="0" password="1" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
-               extAttrName="__PASSWORD__" intAttrName="Password" intAttrName="password"
+               extAttrName="__PASSWORD__" intAttrName="password"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="cf0a222c-36ea-41e6-987c-7908614ccd23" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
                extAttrName="sn" intAttrName="surname"
@@ -961,7 +958,7 @@ under the License.
                extAttrName="cn" intAttrName="name"
                mandatoryCondition="true" purpose="BOTH"/>
   <MappingItem id="2" connObjectKey="0" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
-               extAttrName="owner" intAttrName="owner"
+               extAttrName="owner" intAttrName="userOwner"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="3" connObjectKey="0" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
                extAttrName="description" intAttrName="title"
@@ -985,7 +982,7 @@ under the License.
                extAttrName="SURNAME" intAttrName="surname" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="3ac0ecaf-d9a1-4fc1-9ae9-84dc34576810" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
-               extAttrName="USERNAME" intAttrName="Username" intAttrName="username" 
+               extAttrName="USERNAME" intAttrName="username" 
                mandatoryCondition="false" password="0" purpose="BOTH"/>
   <MappingItem id="e7215305-93c9-460b-b862-46f7b60de72d" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
                extAttrName="EMAIL" intAttrName="userId" 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
index 3d8d0a5..ba726c6 100644
--- a/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/TwoContent.xml
@@ -155,13 +155,13 @@ we are happy to inform you that the password request was execute successfully fo
 &lt;/body&gt;
 &lt;/html&gt;"/>
 
-  <Notification id="c74b4616-9c63-4350-b4bf-ae0077b1ae6a" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" 
+  <Notification id="c74b4616-9c63-4350-b4bf-ae0077b1ae6a" active="1" recipientAttrName="email" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset request" template_id="requestPasswordReset" 
                 traceLevel="FAILURES"/> 
   <AnyAbout id="0d4e37a1-a4f4-4865-afcb-4be01da3da53" anyType_id="USER" notification_id="c74b4616-9c63-4350-b4bf-ae0077b1ae6a" filter="token!=$null"/>
   <Notification_events notification_id="c74b4616-9c63-4350-b4bf-ae0077b1ae6a" event="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/>
   
-  <Notification id="71769807-7f74-4dc3-ba61-e4a7a00eb8ad" active="1" recipientAttrName="email" recipientAttrType="UserPlainSchema" selfAsRecipient="1" 
+  <Notification id="71769807-7f74-4dc3-ba61-e4a7a00eb8ad" active="1" recipientAttrName="email" selfAsRecipient="1" 
                 sender="admin@syncope.apache.org" subject="Password Reset successful" template_id="confirmPasswordReset" 
                 traceLevel="FAILURES"/> 
   <Notification_events notification_id="71769807-7f74-4dc3-ba61-e4a7a00eb8ad" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
new file mode 100644
index 0000000..1dfa654
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrName.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+
+public class IntAttrName {
+
+    private AnyTypeKind anyTypeKind;
+
+    private String field;
+
+    private SchemaType schemaType;
+
+    private String schemaName;
+
+    private String enclosingGroup;
+
+    private String relatedAnyObject;
+
+    private String membershipOfGroup;
+
+    public AnyTypeKind getAnyTypeKind() {
+        return anyTypeKind;
+    }
+
+    public void setAnyTypeKind(final AnyTypeKind anyTypeKind) {
+        this.anyTypeKind = anyTypeKind;
+    }
+
+    public String getField() {
+        return field;
+    }
+
+    public void setField(final String field) {
+        this.field = field;
+    }
+
+    public SchemaType getSchemaType() {
+        return schemaType;
+    }
+
+    public void setSchemaType(final SchemaType schemaType) {
+        this.schemaType = schemaType;
+    }
+
+    public String getSchemaName() {
+        return schemaName;
+    }
+
+    public void setSchemaName(final String schemaName) {
+        this.schemaName = schemaName;
+    }
+
+    public String getEnclosingGroup() {
+        return enclosingGroup;
+    }
+
+    public void setEnclosingGroup(final String enclosingGroup) {
+        this.enclosingGroup = enclosingGroup;
+    }
+
+    public String getRelatedAnyObject() {
+        return relatedAnyObject;
+    }
+
+    public void setRelatedAnyObject(final String relatedAnyObject) {
+        this.relatedAnyObject = relatedAnyObject;
+    }
+
+    public String getMembershipOfGroup() {
+        return membershipOfGroup;
+    }
+
+    public void setMembershipOfGroup(final String membershipOfGroup) {
+        this.membershipOfGroup = membershipOfGroup;
+    }
+
+    @Override
+    public String toString() {
+        return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
deleted file mode 100644
index 4beb5ce..0000000
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/IntAttrNameParser.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.api;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.SchemaType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-
-public final class IntAttrNameParser {
-
-    private static final Pattern ENCLOSING_GROUP_PATTERN = Pattern.compile("^groups\\[[\\w]+\\]\\.[\\w]+");
-
-    private static final Pattern RELATED_ANY_OBJECT_PATTERN = Pattern.compile("^anyObjects\\[[\\w]+\\]\\.[\\w]+");
-
-    private static final Pattern MEMBERSHIP_PATTERN = Pattern.compile("^\\[[\\w]+\\]\\.[\\w]+");
-
-    public static class IntAttrName {
-
-        private AnyTypeKind anyTypeKind;
-
-        private String field;
-
-        private SchemaType schemaType;
-
-        private String schemaName;
-
-        private String enclosingGroup;
-
-        private String relatedAnyObject;
-
-        private String membershipOfGroup;
-
-        public AnyTypeKind getAnyTypeKind() {
-            return anyTypeKind;
-        }
-
-        public String getField() {
-            return field;
-        }
-
-        public SchemaType getSchemaType() {
-            return schemaType;
-        }
-
-        public String getSchemaName() {
-            return schemaName;
-        }
-
-        public String getEnclosingGroup() {
-            return enclosingGroup;
-        }
-
-        public String getRelatedAnyObject() {
-            return relatedAnyObject;
-        }
-
-        public String getMembershipOfGroup() {
-            return membershipOfGroup;
-        }
-
-        @Override
-        public String toString() {
-            return ToStringBuilder.reflectionToString(field, ToStringStyle.MULTI_LINE_STYLE);
-        }
-
-    }
-
-    private static void setFieldOrSchemaName(
-            final String fieldOrSchemaName, final AnyUtils anyUtils, final IntAttrName result) {
-
-        if (anyUtils.isFieldName(fieldOrSchemaName)) {
-            result.field = fieldOrSchemaName;
-        } else {
-            result.schemaName = fieldOrSchemaName;
-        }
-    }
-
-    public static IntAttrName parse(
-            final String intAttrName,
-            final AnyUtilsFactory anyUtilsFactory,
-            final AnyTypeKind provisionAnyTypeKind) {
-
-        IntAttrName result = new IntAttrName();
-
-        if (intAttrName.indexOf('.') == -1) {
-            result.anyTypeKind = provisionAnyTypeKind;
-            setFieldOrSchemaName(intAttrName, anyUtilsFactory.getInstance(provisionAnyTypeKind), result);
-        } else {
-            Matcher matcher = ENCLOSING_GROUP_PATTERN.matcher(intAttrName);
-            if (matcher.matches()) {
-                result.anyTypeKind = AnyTypeKind.GROUP;
-                result.enclosingGroup = matcher.group(1);
-                setFieldOrSchemaName(matcher.group(2), anyUtilsFactory.getInstance(AnyTypeKind.GROUP), result);
-            } else {
-                matcher = RELATED_ANY_OBJECT_PATTERN.matcher(intAttrName);
-                if (matcher.matches()) {
-                    result.anyTypeKind = AnyTypeKind.ANY_OBJECT;
-                    result.relatedAnyObject = matcher.group(1);
-                    setFieldOrSchemaName(matcher.group(2), anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), result);
-                } else {
-                    matcher = MEMBERSHIP_PATTERN.matcher(intAttrName);
-                    if (matcher.matches()) {
-                        result.anyTypeKind = AnyTypeKind.USER;
-                        result.membershipOfGroup = matcher.group(1);
-                        setFieldOrSchemaName(matcher.group(2), anyUtilsFactory.getInstance(AnyTypeKind.USER), result);
-                    } else {
-                        throw new IllegalArgumentException("Unparsable expression: " + intAttrName);
-                    }
-                }
-            }
-        }
-
-        return result;
-    }
-
-    private IntAttrNameParser() {
-        // private constructor for static utility class
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
index 99c1ba8..8d0be03 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/MappingManager.java
@@ -41,14 +41,15 @@ public interface MappingManager {
     String getConnObjectKeyValue(Any<?> any, Provision provision);
 
     /**
-     * Get attribute values for the given {@link MappingItem} and any objects.
+     * Get attribute values for the given {@link MappingItem} and any object.
      *
      * @param provision provision information
      * @param mapItem mapping item
-     * @param anys any objects
+     * @param intAttrName int attr name
+     * @param any any object
      * @return attribute values.
      */
-    List<PlainAttrValue> getIntValues(Provision provision, MappingItem mapItem, List<Any<?>> anys);
+    List<PlainAttrValue> getIntValues(Provision provision, MappingItem mapItem, IntAttrName intAttrName, Any<?> any);
 
     /**
      * Prepare attributes for sending to a connector instance.

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
index db66766..d8cb012 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/MappingItemTransformer.java
@@ -36,13 +36,13 @@ public interface MappingItemTransformer {
      * Invoked while preparing attribute values to be sent out to external resource during propagation.
      *
      * @param mappingItem mapping item
-     * @param anys any objects
+     * @param any any object
      * @param values original values
      * @return transformed values
      */
     List<PlainAttrValue> beforePropagation(
             MappingItem mappingItem,
-            List<Any<?>> anys,
+            Any<?> any,
             List<PlainAttrValue> values);
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
index 1a2bcc4..83a97e6 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/ConnectorFacadeProxy.java
@@ -35,10 +35,11 @@ import org.apache.syncope.core.provisioning.api.ConnIdBundleManager;
 import org.apache.syncope.core.provisioning.api.utils.ConnPoolConfUtils;
 import org.apache.syncope.core.provisioning.api.Connector;
 import org.apache.syncope.core.provisioning.api.TimeoutException;
-import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.provisioning.api.pushpull.ReconciliationFilterBuilder;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.identityconnectors.common.security.GuardedByteArray;
 import org.identityconnectors.common.security.GuardedString;
 import org.identityconnectors.framework.api.APIConfiguration;
@@ -479,7 +480,7 @@ public class ConnectorFacadeProxy implements Connector {
             }
         }, new ArrayList<SortKey>(orderBy.size())));
 
-        builder.setAttributesToGet(MappingManagerImpl.buildOperationOptions(mapItems).getAttributesToGet());
+        builder.setAttributesToGet(MappingUtils.buildOperationOptions(mapItems).getAttributesToGet());
 
         search(objectClass, filter, handler, builder.build());
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
new file mode 100644
index 0000000..13af60a
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/IntAttrNameParser.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java;
+
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.Schema;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+public class IntAttrNameParser {
+
+    private static final Pattern ENCLOSING_GROUP_PATTERN = Pattern.compile("^groups\\[([\\w]+)\\]\\.([\\w]+)");
+
+    private static final Pattern RELATED_ANY_OBJECT_PATTERN = Pattern.compile("^anyObjects\\[([\\w]+)\\]\\.([\\w]+)");
+
+    private static final Pattern MEMBERSHIP_PATTERN = Pattern.compile("^memberships\\[([\\w]+)\\]\\.([\\w]+)");
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
+    private AnyUtilsFactory anyUtilsFactory;
+
+    private SchemaType find(final String key) {
+        Schema schema = plainSchemaDAO.find(key);
+        if (schema == null) {
+            schema = derSchemaDAO.find(key);
+            if (schema == null) {
+                schema = virSchemaDAO.find(key);
+                if (schema == null) {
+                    return null;
+                } else {
+                    return SchemaType.VIRTUAL;
+                }
+            } else {
+                return SchemaType.DERIVED;
+            }
+        } else {
+            return SchemaType.PLAIN;
+        }
+    }
+
+    private void setFieldOrSchemaName(
+            final String fieldOrSchemaName,
+            final AnyTypeKind anyTypeKind,
+            final IntAttrName result) {
+
+        if (anyUtilsFactory.getInstance(anyTypeKind).isFieldName(fieldOrSchemaName)) {
+            result.setField(fieldOrSchemaName);
+        } else {
+            result.setSchemaType(find(fieldOrSchemaName));
+            result.setSchemaName(fieldOrSchemaName);
+        }
+    }
+
+    @Transactional(readOnly = true)
+    public IntAttrName parse(final String intAttrName, final AnyTypeKind provisionAnyTypeKind) {
+        IntAttrName result = new IntAttrName();
+
+        if (intAttrName.indexOf('.') == -1) {
+            result.setAnyTypeKind(provisionAnyTypeKind);
+            setFieldOrSchemaName(intAttrName, result.getAnyTypeKind(), result);
+        } else {
+            Matcher matcher = ENCLOSING_GROUP_PATTERN.matcher(intAttrName);
+            if (matcher.matches()) {
+                result.setAnyTypeKind(AnyTypeKind.GROUP);
+                result.setEnclosingGroup(matcher.group(1));
+                setFieldOrSchemaName(matcher.group(2), result.getAnyTypeKind(), result);
+            } else {
+                matcher = RELATED_ANY_OBJECT_PATTERN.matcher(intAttrName);
+                if (matcher.matches()) {
+                    result.setAnyTypeKind(AnyTypeKind.ANY_OBJECT);
+                    result.setRelatedAnyObject(matcher.group(1));
+                    setFieldOrSchemaName(matcher.group(2), result.getAnyTypeKind(), result);
+                } else {
+                    matcher = MEMBERSHIP_PATTERN.matcher(intAttrName);
+                    if (matcher.matches()) {
+                        result.setAnyTypeKind(AnyTypeKind.USER);
+                        result.setMembershipOfGroup(matcher.group(1));
+                        setFieldOrSchemaName(matcher.group(2), result.getAnyTypeKind(), result);
+                    } else {
+                        throw new IllegalArgumentException("Unparsable expression: " + intAttrName);
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+}


[09/15] syncope git commit: [SYNCOPE-862] Features complete

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 a2c9271..4c44b7f 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
@@ -24,7 +24,6 @@ import java.util.List;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.policy.PullPolicySpec;
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
@@ -47,8 +46,8 @@ import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.Connector;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
-import org.apache.syncope.core.provisioning.api.IntAttrNameParser.IntAttrName;
+import org.apache.syncope.core.provisioning.java.IntAttrNameParser;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -63,6 +62,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 
 @Transactional(readOnly = true)
 @Component
@@ -103,6 +103,9 @@ public class PullUtils {
     @Autowired
     private AnyUtilsFactory anyUtilsFactory;
 
+    @Autowired
+    private IntAttrNameParser intAttrNameParser;
+
     public String findMatchingAnyKey(
             final AnyType anyType,
             final String name,
@@ -127,7 +130,7 @@ public class PullUtils {
             public boolean handle(final ConnectorObject obj) {
                 return found.add(obj);
             }
-        }, MappingManagerImpl.buildOperationOptions(MappingManagerImpl.getPullMappingItems(provision).iterator()));
+        }, MappingUtils.buildOperationOptions(MappingUtils.getPullMappingItems(provision).iterator()));
 
         if (found.isEmpty()) {
             LOG.debug("No {} found on {} with __NAME__ {}", provision.getObjectClass(), resource, name);
@@ -170,10 +173,10 @@ public class PullUtils {
 
         List<String> result = new ArrayList<>();
 
-        MappingItem connObjectKeyItem = MappingManagerImpl.getConnObjectKeyItem(provision);
+        MappingItem connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
 
         String transfUid = uid;
-        for (MappingItemTransformer transformer : MappingManagerImpl.getMappingItemTransformers(connObjectKeyItem)) {
+        for (MappingItemTransformer transformer : MappingUtils.getMappingItemTransformers(connObjectKeyItem)) {
             List<Object> output = transformer.beforePull(
                     connObjectKeyItem,
                     null,
@@ -183,9 +186,8 @@ public class PullUtils {
             }
         }
 
-        IntAttrName intAttrName = IntAttrNameParser.parse(
+        IntAttrName intAttrName = intAttrNameParser.parse(
                 connObjectKeyItem.getIntAttrName(),
-                anyUtilsFactory,
                 provision.getAnyType().getKind());
 
         if (intAttrName.getField() != null) {
@@ -214,6 +216,8 @@ public class PullUtils {
                         result.add(anyObject.getKey());
                     }
                     break;
+
+                default:
             }
         } else if (intAttrName.getSchemaType() != null) {
             switch (intAttrName.getSchemaType()) {
@@ -246,6 +250,8 @@ public class PullUtils {
                         result.add(any.getKey());
                     }
                     break;
+
+                default:
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 af2631c..c0ed5fc 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
@@ -18,7 +18,6 @@
  */
 package org.apache.syncope.core.provisioning.java.utils;
 
-import org.apache.syncope.core.provisioning.java.MappingManagerImpl;
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.commons.lang3.StringUtils;
@@ -222,7 +221,7 @@ public class ConnObjectUtils {
 
         // 1. fill with data from connector object
         anyTO.setRealm(pullTask.getDestinatioRealm().getFullPath());
-        for (MappingItem item : MappingManagerImpl.getPullMappingItems(provision)) {
+        for (MappingItem item : MappingUtils.getPullMappingItems(provision)) {
             mappingManager.setIntValues(item, obj.getAttributeByName(item.getExtAttrName()), anyTO, anyUtils);
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
new file mode 100644
index 0000000..63ceb98
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.jexl3.JexlContext;
+import org.apache.commons.jexl3.MapContext;
+import org.apache.commons.lang3.ClassUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.data.MappingItemTransformer;
+import org.apache.syncope.core.provisioning.java.data.JEXLMappingItemTransformer;
+import org.apache.syncope.core.provisioning.java.jexl.JexlUtils;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.identityconnectors.framework.common.objects.Name;
+import org.identityconnectors.framework.common.objects.OperationOptions;
+import org.identityconnectors.framework.common.objects.OperationOptionsBuilder;
+import org.identityconnectors.framework.common.objects.OperationalAttributes;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+
+public final class MappingUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(MappingUtils.class);
+
+    public static MappingItem getConnObjectKeyItem(final Provision provision) {
+        Mapping mapping = null;
+        if (provision != null) {
+            mapping = provision.getMapping();
+        }
+
+        return mapping == null
+                ? null
+                : mapping.getConnObjectKeyItem();
+    }
+
+    private static List<MappingItem> getMappingItems(final Provision provision, final MappingPurpose purpose) {
+        List<? extends MappingItem> items = Collections.<MappingItem>emptyList();
+        if (provision != null) {
+            items = provision.getMapping().getItems();
+        }
+
+        List<MappingItem> result = new ArrayList<>();
+
+        switch (purpose) {
+            case PULL:
+                for (MappingItem item : items) {
+                    if (MappingPurpose.PROPAGATION != item.getPurpose()
+                            && MappingPurpose.NONE != item.getPurpose()) {
+
+                        result.add(item);
+                    }
+                }
+                break;
+
+            case PROPAGATION:
+                for (MappingItem item : items) {
+                    if (MappingPurpose.PULL != item.getPurpose()
+                            && MappingPurpose.NONE != item.getPurpose()) {
+
+                        result.add(item);
+                    }
+                }
+                break;
+
+            case BOTH:
+                for (MappingItem item : items) {
+                    if (MappingPurpose.NONE != item.getPurpose()) {
+                        result.add(item);
+                    }
+                }
+                break;
+
+            case NONE:
+                for (MappingItem item : items) {
+                    if (MappingPurpose.NONE == item.getPurpose()) {
+                        result.add(item);
+                    }
+                }
+                break;
+
+            default:
+        }
+
+        return result;
+    }
+
+    public static List<MappingItem> getPropagationMappingItems(final Provision provision) {
+        return getMappingItems(provision, MappingPurpose.PROPAGATION);
+    }
+
+    public static List<MappingItem> getPullMappingItems(final Provision provision) {
+        return getMappingItems(provision, MappingPurpose.PULL);
+    }
+
+    /**
+     * Build __NAME__ for propagation. First look if there ia a defined connObjectLink for the given resource (and in
+     * this case evaluate as JEXL); otherwise, take given connObjectKey.
+     *
+     * @param any given any object
+     * @param provision external resource
+     * @param connObjectKey connector object key
+     * @return the value to be propagated as __NAME__
+     */
+    public static Name evaluateNAME(final Any<?> any, final Provision provision, final String connObjectKey) {
+        if (StringUtils.isBlank(connObjectKey)) {
+            // LOG error but avoid to throw exception: leave it to the external resource
+            LOG.error("Missing ConnObjectKey for '{}': ", provision.getResource());
+        }
+
+        // Evaluate connObjectKey expression
+        String connObjectLink = provision == null || provision.getMapping() == null
+                ? null
+                : provision.getMapping().getConnObjectLink();
+        String evalConnObjectLink = null;
+        if (StringUtils.isNotBlank(connObjectLink)) {
+            JexlContext jexlContext = new MapContext();
+            JexlUtils.addFieldsToContext(any, jexlContext);
+            JexlUtils.addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
+            JexlUtils.addDerAttrsToContext(any, jexlContext);
+            evalConnObjectLink = JexlUtils.evaluate(connObjectLink, jexlContext);
+        }
+
+        // If connObjectLink evaluates to an empty string, just use the provided connObjectKey as Name(),
+        // otherwise evaluated connObjectLink expression is taken as Name().
+        Name name;
+        if (StringUtils.isBlank(evalConnObjectLink)) {
+            // add connObjectKey as __NAME__ attribute ...
+            LOG.debug("Add connObjectKey [{}] as __NAME__", connObjectKey);
+            name = new Name(connObjectKey);
+        } else {
+            LOG.debug("Add connObjectLink [{}] as __NAME__", evalConnObjectLink);
+            name = new Name(evalConnObjectLink);
+
+            // connObjectKey not propagated: it will be used to set the value for __UID__ attribute
+            LOG.debug("connObjectKey will be used just as __UID__ attribute");
+        }
+
+        return name;
+    }
+
+    public static List<MappingItemTransformer> getMappingItemTransformers(final MappingItem mappingItem) {
+        List<MappingItemTransformer> result = new ArrayList<>();
+
+        // First consider the JEXL transformation expressions
+        JEXLMappingItemTransformer jexlTransformer = null;
+        if (StringUtils.isNotBlank(mappingItem.getPropagationJEXLTransformer())
+                || StringUtils.isNotBlank(mappingItem.getPullJEXLTransformer())) {
+
+            try {
+                jexlTransformer = (JEXLMappingItemTransformer) ApplicationContextProvider.getBeanFactory().
+                        createBean(JEXLMappingItemTransformer.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+
+                jexlTransformer.setPropagationJEXL(mappingItem.getPropagationJEXLTransformer());
+                jexlTransformer.setPullJEXL(mappingItem.getPullJEXLTransformer());
+            } catch (Exception e) {
+                LOG.error("Could not instantiate {}, ignoring...", JEXLMappingItemTransformer.class.getName(), e);
+            }
+        }
+        if (jexlTransformer != null) {
+            result.add(jexlTransformer);
+        }
+
+        // Then other custom tranaformers
+        for (String className : mappingItem.getMappingItemTransformerClassNames()) {
+            try {
+                Class<?> transformerClass = ClassUtils.getClass(className);
+
+                result.add((MappingItemTransformer) ApplicationContextProvider.getBeanFactory().
+                        createBean(transformerClass, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false));
+            } catch (Exception e) {
+                LOG.error("Could not instantiate {}, ignoring...", className, e);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Build options for requesting all mapped connector attributes.
+     *
+     * @param mapItems mapping items
+     * @return options for requesting all mapped connector attributes
+     * @see OperationOptions
+     */
+    public static OperationOptions buildOperationOptions(final Iterator<? extends MappingItem> mapItems) {
+        OperationOptionsBuilder builder = new OperationOptionsBuilder();
+
+        Set<String> attrsToGet = new HashSet<>();
+        attrsToGet.add(Name.NAME);
+        attrsToGet.add(Uid.NAME);
+        attrsToGet.add(OperationalAttributes.ENABLE_NAME);
+
+        while (mapItems.hasNext()) {
+            MappingItem mapItem = mapItems.next();
+            if (mapItem.getPurpose() != MappingPurpose.NONE) {
+                attrsToGet.add(mapItem.getExtAttrName());
+            }
+        }
+
+        builder.setAttributesToGet(attrsToGet);
+        // -------------------------------------
+
+        return builder.build();
+    }
+
+    /**
+     * Private default constructor, for static-only classes.
+     */
+    private MappingUtils() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/main/resources/provisioningContext.xml
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/resources/provisioningContext.xml b/core/provisioning-java/src/main/resources/provisioningContext.xml
index 068d1e7..37c8181 100644
--- a/core/provisioning-java/src/main/resources/provisioningContext.xml
+++ b/core/provisioning-java/src/main/resources/provisioningContext.xml
@@ -122,4 +122,5 @@ under the License.
     <property name="stringLocations" value="${connid.locations}"/>
   </bean>
 
+  <bean class="org.apache.syncope.core.provisioning.java.IntAttrNameParser"/>
 </beans>

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
new file mode 100644
index 0000000..c603f8a
--- /dev/null
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/IntAttrNameParserTest.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.core.provisioning.api.IntAttrName;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional("Master")
+public class IntAttrNameParserTest extends AbstractTest {
+
+    @Autowired
+    private IntAttrNameParser intAttrNameParser;
+
+    @Test
+    public void ownFields() {
+        IntAttrName intAttrName = intAttrNameParser.parse("key", AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+        assertNotNull(intAttrName.getField());
+        assertEquals("key", intAttrName.getField());
+        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+
+        intAttrName = intAttrNameParser.parse("name", AnyTypeKind.GROUP);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
+        assertNotNull(intAttrName.getField());
+        assertEquals("name", intAttrName.getField());
+        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+
+        intAttrName = intAttrNameParser.parse("userOwner", AnyTypeKind.GROUP);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
+        assertNotNull(intAttrName.getField());
+        assertEquals("userOwner", intAttrName.getField());
+        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+
+        intAttrName = intAttrNameParser.parse("name", AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+    }
+
+    @Test
+    public void ownSchema() {
+        IntAttrName intAttrName = intAttrNameParser.parse("email", AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+        assertEquals("email", intAttrName.getSchemaName());
+        assertEquals(SchemaType.PLAIN, intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+
+        intAttrName = intAttrNameParser.parse("cn", AnyTypeKind.ANY_OBJECT);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+        assertEquals("cn", intAttrName.getSchemaName());
+        assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+
+        intAttrName = intAttrNameParser.parse("rvirtualdata", AnyTypeKind.ANY_OBJECT);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+        assertEquals("rvirtualdata", intAttrName.getSchemaName());
+        assertEquals(SchemaType.VIRTUAL, intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+    }
+
+    @Test
+    public void enclosingGroup() {
+        IntAttrName intAttrName = intAttrNameParser.parse("groups[readers].cn", AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.GROUP, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+        assertEquals("cn", intAttrName.getSchemaName());
+        assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+        assertEquals("readers", intAttrName.getEnclosingGroup());
+        assertNull(intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+    }
+
+    @Test
+    public void relatedAnyObject() {
+        IntAttrName intAttrName = intAttrNameParser.parse("anyObjects[hp].name", AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.ANY_OBJECT, intAttrName.getAnyTypeKind());
+        assertEquals("name", intAttrName.getField());
+        assertNull(intAttrName.getSchemaName());
+        assertNull(intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertEquals("hp", intAttrName.getRelatedAnyObject());
+        assertNull(intAttrName.getMembershipOfGroup());
+    }
+
+    @Test
+    public void membership() {
+        IntAttrName intAttrName = intAttrNameParser.parse("memberships[top].cn", AnyTypeKind.USER);
+        assertNotNull(intAttrName);
+        assertEquals(AnyTypeKind.USER, intAttrName.getAnyTypeKind());
+        assertNull(intAttrName.getField());
+        assertEquals("cn", intAttrName.getSchemaName());
+        assertEquals(SchemaType.DERIVED, intAttrName.getSchemaType());
+        assertNull(intAttrName.getEnclosingGroup());
+        assertEquals("top", intAttrName.getMembershipOfGroup());
+        assertNull(intAttrName.getRelatedAnyObject());
+    }
+
+    @Test
+    public void invalid() {
+        try {
+            intAttrNameParser.parse("memberships.cn", AnyTypeKind.USER);
+            fail();
+        } catch (IllegalArgumentException e) {
+            assertNotNull(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
index dd6792b..0e84b68 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/MappingTest.java
@@ -27,6 +27,7 @@ import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.identityconnectors.framework.common.objects.Name;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,12 +58,12 @@ public class MappingTest extends AbstractTest {
         User user = userDAO.findByUsername("rossini");
         assertNotNull(user);
 
-        Name name = MappingManagerImpl.evaluateNAME(user, provision, user.getUsername());
+        Name name = MappingUtils.evaluateNAME(user, provision, user.getUsername());
         assertEquals("uid=rossini,ou=people,o=isp", name.getNameValue());
 
         provision.getMapping().setConnObjectLink("'uid=' + username + ',o=' + realm + ',ou=people,o=isp'");
 
-        name = MappingManagerImpl.evaluateNAME(user, provision, user.getUsername());
+        name = MappingUtils.evaluateNAME(user, provision, user.getUsername());
         assertEquals("uid=rossini,o=even,ou=people,o=isp", name.getNameValue());
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
index 7fc60df..822860f 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/PrefixMappingItemTransformer.java
@@ -34,11 +34,11 @@ public class PrefixMappingItemTransformer extends DefaultMappingItemTransformer
     @Override
     public List<PlainAttrValue> beforePropagation(
             final MappingItem mappingItem,
-            final List<Any<?>> anys,
+            final Any<?> any,
             final List<PlainAttrValue> values) {
 
         if (values == null || values.isEmpty() || values.get(0).getStringValue() == null) {
-            return super.beforePropagation(mappingItem, anys, values);
+            return super.beforePropagation(mappingItem, any, values);
         } else {
             String value = values.get(0).getStringValue();
             values.get(0).setStringValue(PREFIX + value);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
index 1036fdc..849db31 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/NotificationsITCase.java
@@ -43,17 +43,7 @@ public class NotificationsITCase extends AbstractConsoleITCase {
         FormTester formTester = wicketTester.newFormTester(
                 "body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form");
 
-        // -------------------------------
-        // generate event to populate recipientAttrName
-        // -------------------------------
-        formTester.setValue("content:form:view:recipientAttrType:dropDownChoiceField", "3");
-        wicketTester.executeAjaxEvent("body:content:tabbedPanel:panel:outerObjectsRepeater:0:outer:form:content:"
-                + "form:view:recipientAttrType:dropDownChoiceField", Constants.ON_CHANGE);
-        // -------------------------------
-
-        formTester.select("content:form:view:recipientAttrType:dropDownChoiceField", 3);
-        formTester.setValue("content:form:view:recipientAttrType:dropDownChoiceField", "3");
-        formTester.setValue("content:form:view:recipientAttrName:dropDownChoiceField", "0");
+        formTester.setValue("content:form:view:recipientAttrName:textField", "email");
         formTester.select("content:form:view:template:dropDownChoiceField", 2);
         formTester.select("content:form:view:traceLevel:dropDownChoiceField", 0);
         formTester.setValue("content:form:view:sender:textField", sender);

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
index bd62785..f2b8f56 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/TopologyITCase.java
@@ -168,23 +168,12 @@ public class TopologyITCase extends AbstractConsoleITCase {
         formTester = wicketTester.newFormTester(
                 "body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form");
 
-        formTester.setValue("view:mapping:mappingContainer:mappings:0:entities:dropDownChoiceField", "0");
-        wicketTester.executeAjaxEvent(
-                "body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form"
-                + ":view:mapping:mappingContainer:mappings:0:entities:dropDownChoiceField", Constants.ON_CHANGE);
-
-        formTester.setValue("view:mapping:mappingContainer:mappings:0:intMappingTypes:dropDownChoiceField", "4");
-        wicketTester.executeAjaxEvent(
-                "body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form"
-                + ":view:mapping:mappingContainer:mappings:0:intMappingTypes:dropDownChoiceField", Constants.ON_CHANGE);
-
         formTester.setValue("view:mapping:mappingContainer:mappings:0:connObjectKey:checkboxField", "true");
         wicketTester.executeAjaxEvent(
                 "body:toggle:outerObjectsRepeater:3:outer:form:content:provision:container:content:wizard:form"
                 + ":view:mapping:mappingContainer:mappings:0:connObjectKey:checkboxField", Constants.ON_CHANGE);
 
-        formTester.setValue("view:mapping:mappingContainer:mappings:0:entities:dropDownChoiceField", "0");
-        formTester.setValue("view:mapping:mappingContainer:mappings:0:intMappingTypes:dropDownChoiceField", "4");
+        formTester.setValue("view:mapping:mappingContainer:mappings:0:intAttrName:textField", "key");
         formTester.setValue("view:mapping:mappingContainer:mappings:0:extAttrName:textField", "ID");
         formTester.setValue("view:mapping:mappingContainer:mappings:0:connObjectKey:checkboxField", "true");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 a09b9bb..326cf96 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
@@ -867,8 +867,17 @@ public class GroupITCase extends AbstractITCase {
 
     @Test
     public void issueSYNCOPE632() {
-        GroupTO groupTO = null;
+        GroupTO groupTO = getSampleTO("lastGroup");
         try {
+            // 0. create group
+            groupTO.getPlainAttrs().add(attrTO("icon", "anIcon"));
+            groupTO.getPlainAttrs().add(attrTO("show", "true"));
+            groupTO.getDerAttrs().add(attrTO("displayProperty", null));
+            groupTO.getResources().clear();
+
+            groupTO = createGroup(groupTO).getAny();
+            assertNotNull(groupTO);
+
             // 1. create new LDAP resource having ConnObjectKey mapped to a derived attribute
             ResourceTO newLDAP = resourceService.read(RESOURCE_NAME_LDAP);
             newLDAP.setKey("new-ldap");
@@ -887,22 +896,22 @@ public class GroupITCase extends AbstractITCase {
             mapping.setConnObjectLink("'cn=' + displayProperty + ',ou=groups,o=isp'");
 
             MappingItemTO description = new MappingItemTO();
+            description.setIntAttrName("key");
             description.setExtAttrName("description");
-            description.setPurpose(MappingPurpose.BOTH);
+            description.setPurpose(MappingPurpose.PROPAGATION);
             mapping.add(description);
 
             newLDAP = createResource(newLDAP);
             assertNotNull(newLDAP);
 
-            // 2. create a group and give the resource created above
-            groupTO = getSampleTO("lastGroup" + getUUIDString());
-            groupTO.getPlainAttrs().add(attrTO("icon", "anIcon"));
-            groupTO.getPlainAttrs().add(attrTO("show", "true"));
-            groupTO.getDerAttrs().add(attrTO("displayProperty", null));
-            groupTO.getResources().clear();
-            groupTO.getResources().add("new-ldap");
+            // 2. update group and give the resource created above
+            GroupPatch patch = new GroupPatch();
+            patch.setKey(groupTO.getKey());
+            patch.getResources().add(new StringPatchItem.Builder().
+                    operation(PatchOperation.ADD_REPLACE).
+                    value("new-ldap").build());
 
-            groupTO = createGroup(groupTO).getAny();
+            groupTO = updateGroup(patch).getAny();
             assertNotNull(groupTO);
 
             // 3. update the group
@@ -943,7 +952,7 @@ public class GroupITCase extends AbstractITCase {
 
             assertEquals(1, entries);
         } finally {
-            if (groupTO != null) {
+            if (groupTO.getKey() != null) {
                 groupService.delete(groupTO.getKey());
             }
             resourceService.delete("new-ldap");

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/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 38b3631..3d98f28 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
@@ -18,30 +18,47 @@
  */
 package org.apache.syncope.fit.core;
 
+import static org.apache.syncope.fit.core.AbstractTaskITCase.execProvisioningTask;
 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 javax.ws.rs.core.Response;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.patch.AttrPatch;
+import org.apache.syncope.common.lib.patch.DeassociationPatch;
 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.BulkActionResult;
+import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MappingItemTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.TypeExtensionTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
+import org.apache.syncope.common.lib.types.PropagationTaskExecStatus;
+import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
+import org.apache.syncope.common.rest.api.beans.AnySearchQuery;
+import org.apache.syncope.common.rest.api.service.TaskService;
 import org.apache.syncope.fit.AbstractITCase;
 import org.junit.FixMethodOrder;
 import org.junit.Test;
 import org.junit.runners.MethodSorters;
+import org.springframework.jdbc.core.JdbcTemplate;
 
 @FixMethodOrder(MethodSorters.JVM)
 public class MembershipITCase extends AbstractITCase {
@@ -203,4 +220,99 @@ public class MembershipITCase extends AbstractITCase {
         user = userService.read(user.getKey());
         assertTrue(user.getMemberships().isEmpty());
     }
+
+    @Test
+    public void syncWithMembershipAttr() {
+        // 0. create ad-hoc resource, with adequate mapping
+        ResourceTO newResource = resourceService.read(RESOURCE_NAME_DBPULL);
+        newResource.setKey(getUUIDString());
+
+        MappingItemTO item = IterableUtils.find(newResource.getProvision("USER").getMapping().getItems(),
+                new Predicate<MappingItemTO>() {
+
+            @Override
+            public boolean evaluate(final MappingItemTO object) {
+                return "firstname".equals(object.getIntAttrName());
+            }
+        });
+        assertNotNull(item);
+        assertEquals("ID", item.getExtAttrName());
+        item.setIntAttrName("memberships[additional].aLong");
+        item.setPurpose(MappingPurpose.BOTH);
+
+        item = IterableUtils.find(newResource.getProvision("USER").getMapping().getItems(),
+                new Predicate<MappingItemTO>() {
+
+            @Override
+            public boolean evaluate(final MappingItemTO object) {
+                return "fullname".equals(object.getIntAttrName());
+            }
+        });
+        item.setPurpose(MappingPurpose.PULL);
+
+        PullTaskTO newTask = null;
+        try {
+            newResource = createResource(newResource);
+            assertNotNull(newResource);
+
+            // 1. create user with new resource assigned
+            UserTO user = UserITCase.getUniqueSampleTO("memb@apache.org");
+            user.setRealm("/even/two");
+            user.getPlainAttrs().remove(user.getPlainAttrMap().get("ctype"));
+            user.getResources().clear();
+            user.getResources().add(newResource.getKey());
+
+            MembershipTO membership = new MembershipTO.Builder().group("034740a9-fa10-453b-af37-dc7897e98fb1").build();
+            membership.getPlainAttrs().add(new AttrTO.Builder().schema("aLong").value("5432").build());
+            user.getMemberships().add(membership);
+
+            user = createUser(user).getAny();
+            assertNotNull(user);
+
+            // 2. verify that user was found on resource
+            JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+            String idOnResource = jdbcTemplate.queryForObject(
+                    "SELECT id FROM testpull WHERE id=?", String.class, "5432");
+            assertEquals("5432", idOnResource);
+
+            // 3. unlink user from resource, then remove it
+            DeassociationPatch patch = new DeassociationPatch();
+            patch.setKey(user.getKey());
+            patch.setAction(ResourceDeassociationAction.UNLINK);
+            patch.getResources().add(newResource.getKey());
+            assertNotNull(userService.deassociate(patch).readEntity(BulkActionResult.class));
+
+            userService.delete(user.getKey());
+
+            // 4. create pull task and execute
+            newTask = taskService.read("7c2242f4-14af-4ab5-af31-cdae23783655", true);
+            newTask.setResource(newResource.getKey());
+            newTask.setDestinationRealm("/even/two");
+
+            Response response = taskService.create(newTask);
+            newTask = getObject(response.getLocation(), TaskService.class, PullTaskTO.class);
+            assertNotNull(newTask);
+
+            ExecTO execution = execProvisioningTask(taskService, newTask.getKey(), 50, false);
+            assertEquals(PropagationTaskExecStatus.SUCCESS, PropagationTaskExecStatus.valueOf(execution.getStatus()));
+
+            // 5. verify that pulled user has
+            PagedResult<UserTO> users = userService.search(new AnySearchQuery.Builder().
+                    realm("/").
+                    fiql(SyncopeClient.getUserSearchConditionBuilder().
+                            is("username").equalTo(user.getUsername()).query()).build());
+            assertEquals(1, users.getTotalCount());
+            assertEquals(1, users.getResult().get(0).getMemberships().size());
+            assertEquals("5432", users.getResult().get(0).getMemberships().get(0).
+                    getPlainAttrMap().get("aLong").getValues().get(0));
+        } catch (Exception e) {
+            LOG.error("Unexpected error", e);
+            fail(e.getMessage());
+        } finally {
+            if (newTask != null && !"83f7e85d-9774-43fe-adba-ccd856312994".equals(newTask.getKey())) {
+                taskService.delete(newTask.getKey());
+            }
+            resourceService.delete(newResource.getKey());
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
index a89fae3..59de26b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/MigrationITCase.java
@@ -339,7 +339,7 @@ public class MigrationITCase extends AbstractTaskITCase {
         provisionTO.setMapping(mapping);
 
         item = new MappingItemTO();
-        item.setIntAttrName("groupName");
+        item.setIntAttrName("name");
         item.setExtAttrName("name");
         item.setMandatoryCondition("true");
         item.setPurpose(MappingPurpose.PULL);
@@ -417,7 +417,7 @@ public class MigrationITCase extends AbstractTaskITCase {
     public void migrateFromSyncope12() throws InterruptedException {
         // 1. cleanup
         try {
-            realmService.delete(MIGRATION_REALM);
+            realmService.delete("/" + MIGRATION_REALM);
         } catch (Exception e) {
             // ignore
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8e162494/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
index f509611..6d7dd0d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
@@ -255,10 +255,8 @@ public class ResourceITCase extends AbstractITCase {
             createResource(resourceTO);
             fail("Create should not have worked");
         } catch (SyncopeClientException e) {
-            assertEquals(ClientExceptionType.Composite, e.getType());
-            SyncopeClientException rvm = e.asComposite().getException(ClientExceptionType.RequiredValuesMissing);
-            assertNotNull(rvm);
-            assertEquals("intAttrName", rvm.getElements().iterator().next());
+            assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
+            assertEquals("intAttrName", e.getElements().iterator().next());
         }
     }
 
@@ -701,4 +699,34 @@ public class ResourceITCase extends AbstractITCase {
             }
         }
     }
+
+    public void issueSYNCOPE645() {
+        ResourceTO resource = new ResourceTO();
+        resource.setKey("ws-target-resource-basic-save-invalid");
+
+        String connector = resourceService.read("ws-target-resource-1").getConnector();
+        resource.setConnector(connector);
+
+        ProvisionTO provision = new ProvisionTO();
+        provision.setAnyType(AnyTypeKind.USER.name());
+        provision.setObjectClass("__ACCOUNT__");
+        resource.getProvisions().add(provision);
+
+        MappingTO mapping = new MappingTO();
+        provision.setMapping(mapping);
+
+        MappingItemTO item = new MappingItemTO();
+        item.setIntAttrName("icon");
+        item.setExtAttrName("icon");
+        item.setPurpose(MappingPurpose.BOTH);
+        mapping.setConnObjectKeyItem(item);
+
+        // save the resource
+        try {
+            resourceService.create(resource);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.InvalidMapping, e.getType());
+        }
+    }
 }