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

[4/4] syncope git commit: [SYNCOPE-647] Merge from 1_2_X

[SYNCOPE-647] Merge from 1_2_X


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

Branch: refs/heads/master
Commit: 9f6dc6c28eb79839d62948055074789c925cc03a
Parents: 6d5713d c1e6b58
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Feb 24 14:06:46 2015 +0100
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Feb 24 14:06:46 2015 +0100

----------------------------------------------------------------------
 .../api/entity/AttributableUtil.java            |  2 +-
 .../persistence/jpa/dao/JPAPlainSchemaDAO.java  |  4 +-
 .../jpa/entity/JPAAttributableUtil.java         |  2 +-
 .../core/provisioning/java/VirAttrHandler.java  | 61 +++++++++++---------
 .../data/AbstractAttributableDataBinder.java    | 57 ++++++++----------
 .../syncope/fit/core/reference/UserITCase.java  | 51 ++++++++++++++--
 6 files changed, 108 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/9f6dc6c2/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AttributableUtil.java
----------------------------------------------------------------------
diff --cc core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AttributableUtil.java
index 0b7107d,0000000..eb46fd0
mode 100644,000000..100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AttributableUtil.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/AttributableUtil.java
@@@ -1,91 -1,0 +1,91 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.core.persistence.api.entity;
 +
 +import java.util.List;
 +import org.apache.syncope.common.lib.to.AbstractAttributableTO;
 +import org.apache.syncope.common.lib.to.AbstractSubjectTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.common.lib.types.IntMappingType;
 +import org.apache.syncope.common.lib.types.MappingPurpose;
 +
 +public interface AttributableUtil {
 +
 +    AttributableType getType();
 +
 +    <T extends Attributable<?, ?, ?>> Class<T> attributableClass();
 +
 +    <T extends PlainSchema> Class<T> plainSchemaClass();
 +
 +    <T extends PlainSchema> T newPlainSchema();
 +
 +    <T extends PlainAttr> Class<T> plainAttrClass();
 +
 +    <T extends PlainAttr> T newPlainAttr();
 +
 +    <T extends PlainAttrValue> Class<T> plainAttrValueClass();
 +
 +    <T extends PlainAttrValue> T newPlainAttrValue();
 +
 +    <T extends AttrTemplate<PlainSchema>> Class<T> plainAttrTemplateClass();
 +
 +    <T extends PlainAttrValue> Class<T> plainAttrUniqueValueClass();
 +
 +    <T extends PlainAttrValue> T newPlainAttrUniqueValue();
 +
 +    <T extends DerSchema> Class<T> derSchemaClass();
 +
 +    <T extends DerSchema> T newDerSchema();
 +
 +    <T extends DerAttr> Class<T> derAttrClass();
 +
 +    <T extends DerAttr> T newDerAttr();
 +
 +    <T extends AttrTemplate<DerSchema>> Class<T> derAttrTemplateClass();
 +
 +    <T extends VirSchema> Class<T> virSchemaClass();
 +
 +    <T extends VirSchema> T newVirSchema();
 +
 +    <T extends VirAttr> Class<T> virAttrClass();
 +
 +    <T extends VirAttr> T newVirAttr();
 +
 +    <T extends AttrTemplate<VirSchema>> Class<T> virAttrTemplateClass();
 +
 +    <T extends MappingItem> T getAccountIdItem(ExternalResource resource);
 +
 +    String getAccountLink(ExternalResource resource);
 +
 +    <T extends MappingItem> List<T> getMappingItems(ExternalResource resource, MappingPurpose purpose);
 +
 +    <T extends MappingItem> List<T> getUidToMappingItems(ExternalResource resource, MappingPurpose purpose);
 +
-     IntMappingType intMappingType();
++    IntMappingType plainIntMappingType();
 +
 +    IntMappingType derIntMappingType();
 +
 +    IntMappingType virIntMappingType();
 +
 +    <T extends MappingItem> Class<T> mappingItemClass();
 +
 +    <T extends AbstractAttributableTO> T newAttributableTO();
 +
 +    <T extends AbstractSubjectTO> T newSubjectTO();
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f6dc6c2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
index 9546557,0000000..2a354a5
mode 100644,000000..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
@@@ -1,141 -1,0 +1,141 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.core.persistence.jpa.dao;
 +
 +import java.util.HashSet;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Set;
 +import javax.persistence.TypedQuery;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.core.persistence.api.dao.AttrTemplateDAO;
 +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;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtil;
 +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.CPlainSchema;
 +import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttr;
 +import org.apache.syncope.core.persistence.api.entity.membership.MPlainSchema;
 +import org.apache.syncope.core.persistence.api.entity.role.RMappingItem;
 +import org.apache.syncope.core.persistence.api.entity.role.RPlainAttr;
 +import org.apache.syncope.core.persistence.api.entity.role.RPlainSchema;
 +import org.apache.syncope.core.persistence.api.entity.user.UMappingItem;
 +import org.apache.syncope.core.persistence.api.entity.user.UPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainSchema;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.stereotype.Repository;
 +
 +@Repository
 +public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema, String> implements PlainSchemaDAO {
 +
 +    @Autowired
 +    private PlainAttrDAO attrDAO;
 +
 +    @Autowired
 +    private AttrTemplateDAO<PlainSchema> attrTemplateDAO;
 +
 +    @Autowired
 +    private ExternalResourceDAO resourceDAO;
 +
 +    private <T extends PlainSchema> Class<? extends AbstractPlainSchema> getJPAEntityReference(
 +            final Class<T> reference) {
 +
 +        return CPlainSchema.class.isAssignableFrom(reference)
 +                ? JPACPlainSchema.class
 +                : RPlainSchema.class.isAssignableFrom(reference)
 +                        ? JPARPlainSchema.class
 +                        : MPlainSchema.class.isAssignableFrom(reference)
 +                                ? JPAMPlainSchema.class
 +                                : UPlainSchema.class.isAssignableFrom(reference)
 +                                        ? JPAUPlainSchema.class
 +                                        : null;
 +    }
 +
 +    @Override
 +    public <T extends PlainSchema> T find(final String key, final Class<T> reference) {
 +        return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
 +    }
 +
 +    @Override
 +    public <T extends PlainSchema> List<T> findAll(final Class<T> reference) {
 +        TypedQuery<T> query = entityManager.createQuery(
 +                "SELECT e FROM " + getJPAEntityReference(reference).getSimpleName() + " e", reference);
 +        return query.getResultList();
 +    }
 +
 +    @Override
 +    public <T extends PlainAttr> List<T> findAttrs(final PlainSchema schema, final Class<T> reference) {
 +        final StringBuilder queryString = new StringBuilder("SELECT e FROM ").
 +                append(((JPAPlainAttrDAO) attrDAO).getJPAEntityReference(reference).getSimpleName()).
 +                append(" e WHERE e.");
 +        if (RPlainAttr.class.isAssignableFrom(reference) || MPlainAttr.class.isAssignableFrom(reference)) {
 +            queryString.append("template.");
 +        }
 +        queryString.append("schema=:schema");
 +
 +        TypedQuery<T> query = entityManager.createQuery(queryString.toString(), reference);
 +        query.setParameter("schema", schema);
 +
 +        return query.getResultList();
 +    }
 +
 +    @Override
 +    public <T extends PlainSchema> T save(final T schema) {
 +        return entityManager.merge(schema);
 +    }
 +
 +    @Override
 +    @SuppressWarnings("unchecked")
 +    public void delete(final String key, final AttributableUtil attributableUtil) {
 +        PlainSchema schema = find(key, attributableUtil.plainSchemaClass());
 +        if (schema == null) {
 +            return;
 +        }
 +
 +        final Set<Long> attrIds = new HashSet<>();
 +        for (PlainAttr attr : findAttrs(schema, attributableUtil.plainAttrClass())) {
 +            attrIds.add(attr.getKey());
 +        }
 +        for (Long attrId : attrIds) {
 +            attrDAO.delete(attrId, attributableUtil.plainAttrClass());
 +        }
 +
 +        if (attributableUtil.getType() == AttributableType.ROLE
 +                || attributableUtil.getType() == AttributableType.MEMBERSHIP) {
 +
 +            for (Iterator<Number> it = attrTemplateDAO.
 +                    findBySchemaName(schema.getKey(), attributableUtil.plainAttrTemplateClass()).iterator();
 +                    it.hasNext();) {
 +
 +                attrTemplateDAO.delete(it.next().longValue(), attributableUtil.plainAttrTemplateClass());
 +            }
 +        }
 +
-         resourceDAO.deleteMapping(key, attributableUtil.intMappingType(), UMappingItem.class);
-         resourceDAO.deleteMapping(key, attributableUtil.intMappingType(), RMappingItem.class);
++        resourceDAO.deleteMapping(key, attributableUtil.plainIntMappingType(), UMappingItem.class);
++        resourceDAO.deleteMapping(key, attributableUtil.plainIntMappingType(), RMappingItem.class);
 +
 +        entityManager.remove(schema);
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f6dc6c2/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAttributableUtil.java
----------------------------------------------------------------------
diff --cc core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAttributableUtil.java
index 4ca357d,0000000..3b744c6
mode 100644,000000..100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAttributableUtil.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAAttributableUtil.java
@@@ -1,879 -1,0 +1,879 @@@
 +/*
 + * 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.Collections;
 +import java.util.List;
 +import org.apache.syncope.common.lib.to.AbstractAttributableTO;
 +import org.apache.syncope.common.lib.to.AbstractSubjectTO;
 +import org.apache.syncope.common.lib.to.ConfTO;
 +import org.apache.syncope.common.lib.to.MembershipTO;
 +import org.apache.syncope.common.lib.to.RoleTO;
 +import org.apache.syncope.common.lib.to.UserTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.common.lib.types.IntMappingType;
 +import org.apache.syncope.common.lib.types.MappingPurpose;
 +import org.apache.syncope.core.persistence.api.entity.AttrTemplate;
 +import org.apache.syncope.core.persistence.api.entity.Attributable;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtil;
 +import org.apache.syncope.core.persistence.api.entity.DerAttr;
 +import org.apache.syncope.core.persistence.api.entity.DerSchema;
 +import org.apache.syncope.core.persistence.api.entity.ExternalResource;
 +import org.apache.syncope.core.persistence.api.entity.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.PlainSchema;
 +import org.apache.syncope.core.persistence.api.entity.VirAttr;
 +import org.apache.syncope.core.persistence.api.entity.VirSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainAttrUniqueValue;
 +import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainAttrValue;
 +import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.conf.JPAConf;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMDerAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMDerAttrTemplate;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMDerSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainAttrTemplate;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainAttrUniqueValue;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainAttrValue;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMVirAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMVirAttrTemplate;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMVirSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMembership;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARDerAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARDerAttrTemplate;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARDerSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARMappingItem;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARPlainAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARPlainAttrTemplate;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARPlainAttrUniqueValue;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARPlainAttrValue;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARVirAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARVirAttrTemplate;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARVirSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.role.JPARole;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUMappingItem;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrValue;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirSchema;
 +import org.apache.syncope.core.persistence.jpa.entity.user.JPAUser;
 +import org.apache.syncope.core.misc.spring.BeanUtils;
 +import org.identityconnectors.framework.common.objects.Uid;
 +import org.slf4j.LoggerFactory;
 +
 +@SuppressWarnings({ "unchecked", "rawtypes" })
 +public class JPAAttributableUtil implements AttributableUtil {
 +
 +    /**
 +     * Logger.
 +     */
 +    private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(AttributableUtil.class);
 +
 +    private final AttributableType type;
 +
 +    protected JPAAttributableUtil(final AttributableType type) {
 +        this.type = type;
 +    }
 +
 +    @Override
 +    public AttributableType getType() {
 +        return type;
 +    }
 +
 +    @Override
 +    public <T extends Attributable<?, ?, ?>> Class<T> attributableClass() {
 +        Class result;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = JPARole.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMembership.class;
 +                break;
 +
 +            case CONFIGURATION:
 +                result = JPAConf.class;
 +                break;
 +
 +            case USER:
 +            default:
 +                result = JPAUser.class;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainSchema> Class<T> plainSchemaClass() {
 +        Class result;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = JPARPlainSchema.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMPlainSchema.class;
 +                break;
 +
 +            case CONFIGURATION:
 +                result = JPACPlainSchema.class;
 +                break;
 +
 +            case USER:
 +            default:
 +                result = JPAUPlainSchema.class;
 +                break;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainSchema> T newPlainSchema() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUPlainSchema();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARPlainSchema();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMPlainSchema();
 +                break;
 +
 +            case CONFIGURATION:
 +                result = (T) new JPACPlainSchema();
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainAttr> Class<T> plainAttrClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = JPARPlainAttr.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMPlainAttr.class;
 +                break;
 +
 +            case CONFIGURATION:
 +                result = JPACPlainAttr.class;
 +                break;
 +
 +            case USER:
 +            default:
 +                result = JPAUPlainAttr.class;
 +                break;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainAttr> T newPlainAttr() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUPlainAttr();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARPlainAttr();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMPlainAttr();
 +                break;
 +
 +            case CONFIGURATION:
 +                result = (T) new JPACPlainAttr();
 +
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainAttrValue> Class<T> plainAttrValueClass() {
 +        Class result;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = JPARPlainAttrValue.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMPlainAttrValue.class;
 +                break;
 +
 +            case CONFIGURATION:
 +                result = JPACPlainAttrValue.class;
 +                break;
 +
 +            case USER:
 +            default:
 +                result = JPAUPlainAttrValue.class;
 +                break;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainAttrValue> T newPlainAttrValue() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUPlainAttrValue();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARPlainAttrValue();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMPlainAttrValue();
 +                break;
 +
 +            case CONFIGURATION:
 +                result = (T) new JPACPlainAttrValue();
 +                break;
 +
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainAttrValue> Class<T> plainAttrUniqueValueClass() {
 +        Class result;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = JPARPlainAttrUniqueValue.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMPlainAttrUniqueValue.class;
 +                break;
 +
 +            case CONFIGURATION:
 +                result = JPACPlainAttrUniqueValue.class;
 +                break;
 +
 +            case USER:
 +            default:
 +                result = JPAUPlainAttrUniqueValue.class;
 +                break;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends PlainAttrValue> T newPlainAttrUniqueValue() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUPlainAttrUniqueValue();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARPlainAttrUniqueValue();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMPlainAttrUniqueValue();
 +                break;
 +
 +            case CONFIGURATION:
 +                result = (T) new JPACPlainAttrUniqueValue();
 +                break;
 +
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends AttrTemplate<PlainSchema>> Class<T> plainAttrTemplateClass() {
 +        Class result;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = JPARPlainAttrTemplate.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMPlainAttrTemplate.class;
 +                break;
 +
 +            case USER:
 +            case CONFIGURATION:
 +            default:
 +                result = null;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends DerSchema> Class<T> derSchemaClass() {
 +        Class result;
 +
 +        switch (type) {
 +            case USER:
 +                result = JPAUDerSchema.class;
 +                break;
 +
 +            case ROLE:
 +                result = JPARDerSchema.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMDerSchema.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +                result = null;
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends DerSchema> T newDerSchema() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUDerSchema();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARDerSchema();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMDerSchema();
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends DerAttr> Class<T> derAttrClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = JPAUDerAttr.class;
 +                break;
 +
 +            case ROLE:
 +                result = JPARDerAttr.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMDerAttr.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends DerAttr> T newDerAttr() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUDerAttr();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARDerAttr();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMDerAttr();
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends AttrTemplate<DerSchema>> Class<T> derAttrTemplateClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case USER:
 +                break;
 +
 +            case ROLE:
 +                result = JPARDerAttrTemplate.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMDerAttrTemplate.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends VirSchema> Class<T> virSchemaClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = JPAUVirSchema.class;
 +                break;
 +
 +            case ROLE:
 +                result = JPARVirSchema.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMVirSchema.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends VirSchema> T newVirSchema() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUVirSchema();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARVirSchema();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMVirSchema();
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends VirAttr> Class<T> virAttrClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = JPAUVirAttr.class;
 +                break;
 +
 +            case ROLE:
 +                result = JPARVirAttr.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMVirAttr.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends VirAttr> T newVirAttr() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new JPAUVirAttr();
 +                break;
 +
 +            case ROLE:
 +                result = (T) new JPARVirAttr();
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = (T) new JPAMVirAttr();
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends AttrTemplate<VirSchema>> Class<T> virAttrTemplateClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case USER:
 +                break;
 +
 +            case ROLE:
 +                result = JPARVirAttrTemplate.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = JPAMVirAttrTemplate.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends MappingItem> T getAccountIdItem(final ExternalResource resource) {
 +        T result = null;
 +
 +        if (resource != null) {
 +            switch (type) {
 +                case ROLE:
 +                    if (resource.getRmapping() != null) {
 +                        result = (T) resource.getRmapping().getAccountIdItem();
 +                    }
 +                    break;
 +
 +                case MEMBERSHIP:
 +                case USER:
 +                    if (resource.getUmapping() != null) {
 +                        result = (T) resource.getUmapping().getAccountIdItem();
 +                    }
 +                    break;
 +
 +                default:
 +            }
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public String getAccountLink(final ExternalResource resource) {
 +        String result = null;
 +
 +        if (resource != null) {
 +            switch (type) {
 +                case USER:
 +                    if (resource.getUmapping() != null) {
 +                        result = resource.getUmapping().getAccountLink();
 +                    }
 +                    break;
 +
 +                case ROLE:
 +                    if (resource.getRmapping() != null) {
 +                        result = resource.getRmapping().getAccountLink();
 +                    }
 +                    break;
 +
 +                case MEMBERSHIP:
 +                case CONFIGURATION:
 +                default:
 +            }
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends MappingItem> List<T> getMappingItems(
 +            final ExternalResource resource, final MappingPurpose purpose) {
 +
 +        List<T> items = Collections.<T>emptyList();
 +
 +        if (resource != null) {
 +            switch (type) {
 +                case ROLE:
 +                    if (resource.getRmapping() != null) {
 +                        items = (List<T>) resource.getRmapping().getItems();
 +                    }
 +                    break;
 +
 +                case MEMBERSHIP:
 +                case USER:
 +                    if (resource.getUmapping() != null) {
 +                        items = (List<T>) resource.getUmapping().getItems();
 +                    }
 +                    break;
 +
 +                default:
 +            }
 +        }
 +
 +        final List<T> result = new ArrayList<>();
 +
 +        switch (purpose) {
 +            case SYNCHRONIZATION:
 +                for (T item : items) {
 +                    if (MappingPurpose.PROPAGATION != item.getPurpose()
 +                            && MappingPurpose.NONE != item.getPurpose()) {
 +
 +                        result.add(item);
 +                    }
 +                }
 +                break;
 +
 +            case PROPAGATION:
 +                for (T item : items) {
 +                    if (MappingPurpose.SYNCHRONIZATION != item.getPurpose()
 +                            && MappingPurpose.NONE != item.getPurpose()) {
 +
 +                        result.add(item);
 +                    }
 +                }
 +                break;
 +
 +            case BOTH:
 +                for (T item : items) {
 +                    if (MappingPurpose.NONE != item.getPurpose()) {
 +                        result.add(item);
 +                    }
 +                }
 +                break;
 +
 +            case NONE:
 +                for (T item : items) {
 +                    if (MappingPurpose.NONE == item.getPurpose()) {
 +                        result.add(item);
 +                    }
 +                }
 +                break;
 +            default:
 +                LOG.error("You requested not existing purpose {}", purpose);
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends MappingItem> List<T> getUidToMappingItems(
 +            final ExternalResource resource, final MappingPurpose purpose) {
 +
 +        List<T> items = getMappingItems(resource, purpose);
 +
 +        MappingItem uidItem = type == AttributableType.USER ? new JPAUMappingItem() : new JPARMappingItem();
 +        BeanUtils.copyProperties(getAccountIdItem(resource), uidItem);
 +        uidItem.setExtAttrName(Uid.NAME);
 +        uidItem.setAccountid(false);
 +        items.add((T) uidItem);
 +
 +        return items;
 +    }
 +
 +    @Override
-     public IntMappingType intMappingType() {
++    public IntMappingType plainIntMappingType() {
 +        IntMappingType result = null;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = IntMappingType.RolePlainSchema;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = IntMappingType.MembershipPlainSchema;
 +                break;
 +
 +            case USER:
 +                result = IntMappingType.UserPlainSchema;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public IntMappingType derIntMappingType() {
 +        IntMappingType result = null;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = IntMappingType.RoleDerivedSchema;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = IntMappingType.MembershipDerivedSchema;
 +                break;
 +
 +            case USER:
 +                result = IntMappingType.UserDerivedSchema;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public IntMappingType virIntMappingType() {
 +        IntMappingType result = null;
 +
 +        switch (type) {
 +            case ROLE:
 +                result = IntMappingType.RoleVirtualSchema;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = IntMappingType.MembershipVirtualSchema;
 +                break;
 +
 +            case USER:
 +                result = IntMappingType.UserVirtualSchema;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends MappingItem> Class<T> mappingItemClass() {
 +        Class result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = JPAUMappingItem.class;
 +                break;
 +
 +            case ROLE:
 +                result = JPARMappingItem.class;
 +                break;
 +
 +            case MEMBERSHIP:
 +                result = AbstractMappingItem.class;
 +                break;
 +
 +            case CONFIGURATION:
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends AbstractAttributableTO> T newAttributableTO() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new UserTO();
 +                break;
 +            case ROLE:
 +                result = (T) new RoleTO();
 +                break;
 +            case MEMBERSHIP:
 +                result = (T) new MembershipTO();
 +                break;
 +            case CONFIGURATION:
 +                result = (T) new ConfTO();
 +                break;
 +            default:
 +        }
 +
 +        return result;
 +    }
 +
 +    @Override
 +    public <T extends AbstractSubjectTO> T newSubjectTO() {
 +        T result = null;
 +
 +        switch (type) {
 +            case USER:
 +                result = (T) new UserTO();
 +                break;
 +            case ROLE:
 +                result = (T) new RoleTO();
 +                break;
 +            case MEMBERSHIP:
 +            case CONFIGURATION:
 +            default:
 +                break;
 +        }
 +
 +        return result;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/9f6dc6c2/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
----------------------------------------------------------------------
diff --cc core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
index 6f0e38e,0000000..449f949
mode 100644,000000..100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
@@@ -1,308 -1,0 +1,313 @@@
 +/*
 + * 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 java.util.ArrayList;
 +import java.util.Collection;
- import java.util.Collections;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Set;
 +import org.apache.commons.lang3.StringUtils;
 +import org.apache.syncope.common.lib.mod.AttrMod;
 +import org.apache.syncope.common.lib.to.AttrTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
++import org.apache.syncope.common.lib.types.IntMappingType;
 +import org.apache.syncope.common.lib.types.MappingPurpose;
 +import org.apache.syncope.common.lib.types.PropagationByResource;
 +import org.apache.syncope.common.lib.types.ResourceOperation;
 +import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 +import org.apache.syncope.core.persistence.api.dao.MembershipDAO;
 +import org.apache.syncope.core.persistence.api.dao.UserDAO;
 +import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
 +import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 +import org.apache.syncope.core.persistence.api.entity.Attributable;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtil;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtilFactory;
 +import org.apache.syncope.core.persistence.api.entity.ExternalResource;
 +import org.apache.syncope.core.persistence.api.entity.MappingItem;
 +import org.apache.syncope.core.persistence.api.entity.Subject;
 +import org.apache.syncope.core.persistence.api.entity.VirAttr;
 +import org.apache.syncope.core.persistence.api.entity.VirSchema;
 +import org.apache.syncope.core.persistence.api.entity.membership.MVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.membership.MVirAttrTemplate;
 +import org.apache.syncope.core.persistence.api.entity.membership.Membership;
 +import org.apache.syncope.core.persistence.api.entity.role.RVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.role.RVirAttrTemplate;
 +import org.apache.syncope.core.persistence.api.entity.role.Role;
 +import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.user.UVirSchema;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.stereotype.Component;
 +import org.springframework.transaction.annotation.Transactional;
 +
 +@Component
 +@Transactional(rollbackFor = { Throwable.class })
 +public class VirAttrHandler {
 +
 +    private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
 +
 +    @Autowired
 +    private ExternalResourceDAO resourceDAO;
 +
 +    @Autowired
 +    private VirSchemaDAO virSchemaDAO;
 +
 +    @Autowired
 +    private VirAttrDAO virAttrDAO;
 +
 +    @Autowired
 +    private UserDAO userDAO;
 +
 +    @Autowired
 +    private MembershipDAO membershipDAO;
 +
 +    @Autowired
 +    private AttributableUtilFactory attrUtilFactory;
 +
 +    public <T extends VirSchema> T getVirSchema(final String virSchemaName, final Class<T> reference) {
 +        T virtualSchema = null;
 +        if (StringUtils.isNotBlank(virSchemaName)) {
 +            virtualSchema = virSchemaDAO.find(virSchemaName, reference);
 +
 +            if (virtualSchema == null) {
 +                LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
 +            }
 +        }
 +
 +        return virtualSchema;
 +    }
 +
 +    public void setVirAttrSchema(final Attributable<?, ?, ?> attributable,
 +            final VirAttr virAttr, final VirSchema virSchema) {
 +
 +        if (virAttr instanceof UVirAttr) {
 +            ((UVirAttr) virAttr).setSchema((UVirSchema) virSchema);
 +        } else if (virAttr instanceof RVirAttr) {
 +            RVirAttrTemplate template = ((Role) attributable).
 +                    getAttrTemplate(RVirAttrTemplate.class, virSchema.getKey());
 +            if (template != null) {
 +                ((RVirAttr) virAttr).setTemplate(template);
 +            }
 +        } else if (virAttr instanceof MVirAttr) {
 +            MVirAttrTemplate template =
 +                    ((Membership) attributable).getRole().
 +                    getAttrTemplate(MVirAttrTemplate.class, virSchema.getKey());
 +            if (template != null) {
 +                ((MVirAttr) virAttr).setTemplate(template);
 +            }
 +        }
 +    }
 +
++    public void updateOnResourcesIfMappingMatches(final AttributableUtil attrUtil, final String schemaKey,
++            final Set<ExternalResource> resources, final IntMappingType mappingType,
++            final PropagationByResource propByRes) {
++
++        for (ExternalResource resource : resources) {
++            for (MappingItem mapItem : attrUtil.getMappingItems(resource, MappingPurpose.PROPAGATION)) {
++                if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
++                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
++                }
++            }
++        }
++    }
++
 +    @SuppressWarnings({ "unchecked", "rawtypes" })
 +    public PropagationByResource fillVirtual(final Attributable attributable,
 +            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated,
 +            final AttributableUtil attrUtil) {
 +
 +        PropagationByResource propByRes = new PropagationByResource();
 +
 +        final Set<ExternalResource> externalResources = new HashSet<>();
 +        if (attributable instanceof Subject) {
 +            externalResources.addAll(((Subject<?, ?, ?>) attributable).getResources());
-         }
- 
-         if (attributable instanceof Membership) {
-             externalResources.clear();
++        } else if (attributable instanceof Membership) {
 +            externalResources.addAll(((Membership) attributable).getUser().getResources());
++            externalResources.addAll(((Membership) attributable).getRole().getResources());
 +        }
 +
 +        // 1. virtual attributes to be removed
 +        for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
 +            VirSchema virSchema = getVirSchema(vAttrToBeRemoved, attrUtil.virSchemaClass());
 +            if (virSchema != null) {
 +                VirAttr virAttr = attributable.getVirAttr(virSchema.getKey());
 +                if (virAttr == null) {
 +                    LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
 +                } else {
 +                    attributable.removeVirAttr(virAttr);
 +                    virAttrDAO.delete(virAttr);
 +                }
 +
-                 for (ExternalResource resource : resourceDAO.findAll()) {
++                for (ExternalResource resource : externalResources) {
 +                    for (MappingItem mapItem : attrUtil.getMappingItems(resource, MappingPurpose.PROPAGATION)) {
 +                        if (virSchema.getKey().equals(mapItem.getIntAttrName())
-                                 && mapItem.getIntMappingType() == attrUtil.virIntMappingType()
-                                 && externalResources.contains(resource)) {
++                                && mapItem.getIntMappingType() == attrUtil.virIntMappingType()) {
 +
 +                            propByRes.add(ResourceOperation.UPDATE, resource.getKey());
 +
 +                            // Using virtual attribute as AccountId must be avoided
 +                            if (mapItem.isAccountid() && virAttr != null && !virAttr.getValues().isEmpty()) {
 +                                propByRes.addOldAccountId(resource.getKey(), virAttr.getValues().get(0));
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +
 +        LOG.debug("Virtual attributes to be removed:\n{}", propByRes);
 +
 +        // 2. virtual attributes to be updated
 +        for (AttrMod vAttrToBeUpdated : vAttrsToBeUpdated) {
 +            VirSchema virSchema = getVirSchema(vAttrToBeUpdated.getSchema(), attrUtil.virSchemaClass());
 +            VirAttr virAttr = null;
 +            if (virSchema != null) {
 +                virAttr = attributable.getVirAttr(virSchema.getKey());
 +                if (virAttr == null) {
 +                    virAttr = attrUtil.newVirAttr();
 +                    setVirAttrSchema(attributable, virAttr, virSchema);
 +                    if (virAttr.getSchema() == null) {
 +                        LOG.debug("Ignoring {} because no valid schema or template was found", vAttrToBeUpdated);
 +                    } else {
 +                        attributable.addVirAttr(virAttr);
 +                    }
 +                }
 +            }
 +
 +            if (virSchema != null && virAttr != null && virAttr.getSchema() != null) {
-                 for (ExternalResource resource : resourceDAO.findAll()) {
-                     for (MappingItem mapItem : attrUtil.getMappingItems(resource, MappingPurpose.PROPAGATION)) {
-                         if (virSchema.getKey().equals(mapItem.getIntAttrName())
-                                 && mapItem.getIntMappingType() == attrUtil.virIntMappingType()
-                                 && externalResources.contains(resource)) {
- 
-                             propByRes.add(ResourceOperation.UPDATE, resource.getKey());
-                         }
-                     }
++                if (attributable instanceof Subject) {
++                    updateOnResourcesIfMappingMatches(attrUtil, virSchema.getKey(),
++                            externalResources, attrUtil.derIntMappingType(), propByRes);
++                } else if (attributable instanceof Membership) {
++                    updateOnResourcesIfMappingMatches(attrUtil, virSchema.getKey(),
++                            externalResources, IntMappingType.MembershipVirtualSchema, propByRes);
 +                }
 +
 +                final List<String> values = new ArrayList<>(virAttr.getValues());
 +                values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
 +                values.addAll(vAttrToBeUpdated.getValuesToBeAdded());
 +
 +                virAttr.getValues().clear();
 +                virAttr.getValues().addAll(values);
 +
 +                // Owner cannot be specified before otherwise a virtual attribute remove will be invalidated.
 +                virAttr.setOwner(attributable);
 +            }
 +        }
 +
 +        LOG.debug("Virtual attributes to be added:\n{}", propByRes);
 +
 +        return propByRes;
 +    }
 +
 +    /**
 +     * Add virtual attributes and specify values to be propagated.
 +     *
 +     * @param attributable attributable.
 +     * @param vAttrs virtual attributes to be added.
 +     * @param attrUtil attributable util.
 +     */
 +    @SuppressWarnings({ "unchecked", "rawtypes" })
 +    public void fillVirtual(final Attributable attributable, final Collection<AttrTO> vAttrs,
 +            final AttributableUtil attrUtil) {
 +
 +        for (AttrTO attributeTO : vAttrs) {
 +            VirAttr virAttr = attributable.getVirAttr(attributeTO.getSchema());
 +            if (virAttr == null) {
 +                VirSchema virSchema = getVirSchema(attributeTO.getSchema(), attrUtil.virSchemaClass());
 +                if (virSchema != null) {
 +                    virAttr = attrUtil.newVirAttr();
 +                    setVirAttrSchema(attributable, virAttr, virSchema);
 +                    if (virAttr.getSchema() == null) {
 +                        LOG.debug("Ignoring {} because no valid schema or template was found", attributeTO);
 +                    } else {
 +                        virAttr.setOwner(attributable);
 +                        attributable.addVirAttr(virAttr);
 +                        virAttr.getValues().clear();
 +                        virAttr.getValues().addAll(attributeTO.getValues());
 +                    }
 +                }
 +            } else {
 +                virAttr.getValues().clear();
 +                virAttr.getValues().addAll(attributeTO.getValues());
 +            }
 +        }
 +    }
 +
 +    /**
 +     * SYNCOPE-459: build virtual attribute changes in case no other changes were made.
 +     *
 +     * @param key user id
 +     * @param vAttrsToBeRemoved virtual attributes to be removed.
 +     * @param vAttrsToBeUpdated virtual attributes to be updated.
 +     * @return operations to be performed on external resources for virtual attributes changes
 +     */
 +    public PropagationByResource fillVirtual(
 +            final Long key, final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
 +
 +        return fillVirtual(
 +                userDAO.authFetch(key),
 +                vAttrsToBeRemoved,
 +                vAttrsToBeUpdated,
 +                attrUtilFactory.getInstance(AttributableType.USER));
 +    }
 +
++    private Set<String> getAttrNames(final List<? extends VirAttr> virAttrs) {
++        final Set<String> virAttrNames = new HashSet<>();
++        for (VirAttr attr : virAttrs) {
++            virAttrNames.add(attr.getSchema().getKey());
++        }
++        return virAttrNames;
++    }
++
 +    /**
 +     * SYNCOPE-501: build membership virtual attribute changes in case no other changes were made.
 +     *
 +     * @param key user key
 +     * @param roleKey role key
 +     * @param membershipKey membership key
 +     * @param vAttrsToBeRemoved virtual attributes to be removed.
 +     * @param vAttrsToBeUpdated virtual attributes to be updated.
 +     * @param isRemoval flag to check if fill is on removed or added membership
 +     * @return operations to be performed on external resources for membership virtual attributes changes
 +     */
 +    public PropagationByResource fillMembershipVirtual(
 +            final Long key, final Long roleKey, final Long membershipKey, final Set<String> vAttrsToBeRemoved,
 +            final Set<AttrMod> vAttrsToBeUpdated, final boolean isRemoval) {
 +
 +        final Membership membership = membershipKey == null
 +                ? userDAO.authFetch(key).getMembership(roleKey)
 +                : membershipDAO.authFetch(membershipKey);
 +
 +        return membership == null ? new PropagationByResource() : isRemoval
 +                ? fillVirtual(
 +                        membership,
-                         membership.getVirAttrs() == null
-                                 ? Collections.<String>emptySet()
-                                 : getAttrNames(membership.getVirAttrs()),
++                        getAttrNames(membership.getVirAttrs()),
 +                        vAttrsToBeUpdated,
 +                        attrUtilFactory.getInstance(AttributableType.MEMBERSHIP))
 +                : fillVirtual(
 +                        membership,
 +                        vAttrsToBeRemoved,
 +                        vAttrsToBeUpdated,
 +                        attrUtilFactory.getInstance(AttributableType.MEMBERSHIP));
 +    }
 +
-     private Set<String> getAttrNames(final List<? extends VirAttr> virAttrs) {
-         final Set<String> virAttrNames = new HashSet<>();
-         for (VirAttr attr : virAttrs) {
-             virAttrNames.add(attr.getSchema().getKey());
-         }
-         return virAttrNames;
-     }
- 
 +}