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/06/11 16:17:09 UTC

[19/70] syncope git commit: [SYNCOPE-666] Initial commit, Travis CI builds disabled

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/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 4e6b985..22ce79e 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
@@ -18,101 +18,72 @@
  */
 package org.apache.syncope.core.persistence.jpa.dao;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 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;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.AttributableType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.Entitlement;
 import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.core.persistence.api.dao.DerAttrDAO;
-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.GroupDAO;
 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.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.AttrTemplate;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.DerAttr;
-import org.apache.syncope.core.persistence.api.entity.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.PlainAttr;
-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.membership.MDerAttr;
-import org.apache.syncope.core.persistence.api.entity.membership.MDerAttrTemplate;
-import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttrTemplate;
-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.group.GDerAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GDerAttrTemplate;
-import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrTemplate;
-import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GVirAttrTemplate;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMembership;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
 import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.common.lib.types.SubjectType;
 import org.apache.syncope.core.misc.RealmUtils;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.misc.security.AuthContextUtils;
 import org.apache.syncope.core.misc.security.UnauthorizedException;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+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.AMembership;
+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.persistence.jpa.entity.JPAAnyUtilsFactory;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAMembership;
+import org.apache.syncope.core.persistence.jpa.entity.user.JPAUMembership;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
 
 @Repository
-public class JPAGroupDAO extends AbstractSubjectDAO<GPlainAttr, GDerAttr, GVirAttr> implements GroupDAO {
+public class JPAGroupDAO extends AbstractAnyDAO<Group> implements GroupDAO {
 
     @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private PlainAttrDAO plainAttrDAO;
-
-    @Autowired
-    private DerAttrDAO derAttrDAO;
-
-    @Autowired
-    private VirAttrDAO virAttrDAO;
+    private AnyObjectDAO anyObjectDAO;
 
     @Autowired
-    private AttributableUtilsFactory attrUtilsFactory;
+    private UserDAO userDAO;
 
     @Override
-    protected Subject<GPlainAttr, GDerAttr, GVirAttr> findInternal(final Long key) {
-        return find(key);
+    protected AnyUtils init() {
+        return new JPAAnyUtilsFactory().getInstance(AnyTypeKind.GROUP);
     }
 
     @Override
-    public Group find(final Long key) {
-        TypedQuery<Group> query = entityManager.createQuery(
-                "SELECT e FROM " + JPAGroup.class.getSimpleName() + " e WHERE e.id = :id", Group.class);
-        query.setParameter("id", key);
+    protected void securityChecks(final Group group) {
+        Set<String> authRealms = AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_READ);
+        boolean authorized = CollectionUtils.exists(authRealms, new Predicate<String>() {
 
-        Group result = null;
-        try {
-            result = query.getSingleResult();
-        } catch (NoResultException e) {
-            LOG.debug("No group found with id {}", key, e);
+            @Override
+            public boolean evaluate(final String realm) {
+                return group.getRealm().getFullPath().startsWith(realm)
+                        || realm.equals(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey()));
+            }
+        });
+        if (authRealms == null || authRealms.isEmpty() || !authorized) {
+            throw new UnauthorizedException(AnyTypeKind.GROUP, group.getKey());
         }
-
-        return result;
     }
 
     @Override
@@ -168,74 +139,22 @@ public class JPAGroupDAO extends AbstractSubjectDAO<GPlainAttr, GDerAttr, GVirAt
         return query.getResultList();
     }
 
-    @SuppressWarnings("unchecked")
     @Override
-    public List<Group> findByAttrValue(final String schemaName, final GPlainAttrValue attrValue) {
-        return (List<Group>) findByAttrValue(
-                schemaName, attrValue, attrUtilsFactory.getInstance(AttributableType.GROUP));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Group findByAttrUniqueValue(final String schemaName, final GPlainAttrValue attrUniqueValue) {
-        return (Group) findByAttrUniqueValue(
-                schemaName, attrUniqueValue, attrUtilsFactory.getInstance(AttributableType.GROUP));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<Group> findByDerAttrValue(final String schemaName, final String value) {
-        return (List<Group>) findByDerAttrValue(
-                schemaName, value, attrUtilsFactory.getInstance(AttributableType.GROUP));
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public List<Group> findByResource(final ExternalResource resource) {
-        return (List<Group>) findByResource(resource, attrUtilsFactory.getInstance(AttributableType.GROUP));
-    }
-
-    @Override
-    public final List<Group> findAll(final Set<String> adminRealms, final int page, final int itemsPerPage) {
-        return findAll(adminRealms, page, itemsPerPage, Collections.<OrderByClause>emptyList());
-    }
-
-    @Override
-    public List<Group> findAll(final Set<String> adminRealms,
-            final int page, final int itemsPerPage, final List<OrderByClause> orderBy) {
-
-        return searchDAO.search(adminRealms, getAllMatchingCond(), page, itemsPerPage, orderBy, SubjectType.GROUP);
-    }
-
-    @Override
-    public final int count(final Set<String> adminRealms) {
-        return searchDAO.count(adminRealms, getAllMatchingCond(), SubjectType.GROUP);
-    }
-
-    @Override
-    public List<Membership> findMemberships(final Group group) {
-        TypedQuery<Membership> query = entityManager.createQuery(
-                "SELECT e FROM " + JPAMembership.class.getSimpleName() + " e WHERE e.group=:group", Membership.class);
+    public List<AMembership> findAMemberships(final Group group) {
+        TypedQuery<AMembership> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAAMembership.class.getSimpleName()
+                + " e WHERE e.rightEnd=:group", AMembership.class);
         query.setParameter("group", group);
 
         return query.getResultList();
     }
 
-    @SuppressWarnings("unchecked")
-    private List<Long> unmatched(final Long groupId,
-            final Class<?> attrClass, final Class<? extends AttrTemplate<?>> attrTemplateClass) {
-
-        final Query query = entityManager.createNativeQuery(new StringBuilder().
-                append("SELECT ma.id ").
-                append("FROM ").append(JPAMembership.TABLE).append(" m, ").
-                append(attrClass.getSimpleName()).append(" ma ").
-                append("WHERE m.group_id = ?1 ").
-                append("AND ma.owner_id = m.id ").
-                append("AND ma.template_id NOT IN (").
-                append("SELECT id ").
-                append("FROM ").append(attrTemplateClass.getSimpleName()).append(' ').
-                append("WHERE owner_id = ?1)").toString());
-        query.setParameter(1, groupId);
+    @Override
+    public List<UMembership> findUMemberships(final Group group) {
+        TypedQuery<UMembership> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAUMembership.class.getSimpleName()
+                + " e WHERE e.rightEnd=:group", UMembership.class);
+        query.setParameter("group", group);
 
         return query.getResultList();
     }
@@ -243,108 +162,39 @@ public class JPAGroupDAO extends AbstractSubjectDAO<GPlainAttr, GDerAttr, GVirAt
     @Override
     public Group save(final Group group) {
         // refresh dynaminc memberships
-        if (group.getDynMembership() != null) {
-            List<User> matchingUsers = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                    SearchCondConverter.convert(group.getDynMembership().getFIQLCond()), SubjectType.USER);
-
-            group.getDynMembership().getUsers().clear();
-            for (User user : matchingUsers) {
-                group.getDynMembership().addUser(user);
-            }
-        }
+        if (group.getADynMembership() != null) {
+            List<AnyObject> matching = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
+                    SearchCondConverter.convert(group.getADynMembership().getFIQLCond()), AnyTypeKind.ANY_OBJECT);
 
-        // remove plain attributes without a valid template
-        List<GPlainAttr> rToBeDeleted = new ArrayList<>();
-        for (final PlainAttr attr : group.getPlainAttrs()) {
-            boolean found = CollectionUtils.exists(group.getAttrTemplates(GPlainAttrTemplate.class),
-                    new Predicate<GPlainAttrTemplate>() {
-
-                        @Override
-                        public boolean evaluate(final GPlainAttrTemplate template) {
-                            return template.getSchema().equals(attr.getSchema());
-                        }
-                    });
-            if (!found) {
-                rToBeDeleted.add((GPlainAttr) attr);
+            group.getADynMembership().getMembers().clear();
+            for (AnyObject anyObject : matching) {
+                group.getADynMembership().add(anyObject);
             }
         }
-        for (GPlainAttr attr : rToBeDeleted) {
-            LOG.debug("Removing {} from {} because no template is available for it", attr, group);
-            group.removePlainAttr(attr);
-        }
+        if (group.getUDynMembership() != null) {
+            List<User> matching = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
+                    SearchCondConverter.convert(group.getUDynMembership().getFIQLCond()), AnyTypeKind.USER);
 
-        // remove derived attributes without a valid template
-        List<GDerAttr> rDerToBeDeleted = new ArrayList<>();
-        for (final DerAttr attr : group.getDerAttrs()) {
-            boolean found = CollectionUtils.exists(group.getAttrTemplates(GDerAttrTemplate.class),
-                    new Predicate<GDerAttrTemplate>() {
-
-                        @Override
-                        public boolean evaluate(final GDerAttrTemplate template) {
-                            return template.getSchema().equals(attr.getSchema());
-                        }
-                    });
-            if (!found) {
-                rDerToBeDeleted.add((GDerAttr) attr);
+            group.getUDynMembership().getMembers().clear();
+            for (User user : matching) {
+                group.getUDynMembership().add(user);
             }
         }
-        for (GDerAttr attr : rDerToBeDeleted) {
-            LOG.debug("Removing {} from {} because no template is available for it", attr, group);
-            group.removeDerAttr(attr);
-        }
 
-        // remove virtual attributes without a valid template
-        List<GVirAttr> rVirToBeDeleted = new ArrayList<>();
-        for (final VirAttr attr : group.getVirAttrs()) {
-            boolean found = CollectionUtils.exists(group.getAttrTemplates(GVirAttrTemplate.class),
-                    new Predicate<GVirAttrTemplate>() {
-
-                        @Override
-                        public boolean evaluate(final GVirAttrTemplate template) {
-                            return template.getSchema().equals(attr.getSchema());
-                        }
-                    });
-            if (!found) {
-                LOG.debug("Removing {} from {} because no template is available for it", attr, group);
-                rVirToBeDeleted.add((GVirAttr) attr);
-            }
-        }
-        for (GVirAttr attr : rVirToBeDeleted) {
-            group.removeVirAttr(attr);
-        }
-
-        Group merged = entityManager.merge(group);
-
-        // Now the same process for any exising membership of the group being saved
-        if (group.getKey() != null) {
-            for (Long key : unmatched(group.getKey(), MPlainAttr.class, MPlainAttrTemplate.class)) {
-                LOG.debug("Removing MAttr[{}] because no template is available for it in {}", key, group);
-                plainAttrDAO.delete(key, MPlainAttr.class);
-            }
-            for (Long id : unmatched(group.getKey(), MDerAttr.class, MDerAttrTemplate.class)) {
-                LOG.debug("Removing MDerAttr[{}] because no template is available for it in {}", id, group);
-                derAttrDAO.delete(id, MDerAttr.class);
-            }
-            for (Long id : unmatched(group.getKey(), MVirAttr.class, MVirAttrTemplate.class)) {
-                LOG.debug("Removing MVirAttr[{}] because no template is available for it in {}", id, group);
-                virAttrDAO.delete(id, MVirAttr.class);
-            }
-        }
-
-        merged = entityManager.merge(merged);
-        for (VirAttr attr : merged.getVirAttrs()) {
-            attr.getValues().clear();
-            attr.getValues().addAll(group.getVirAttr(attr.getSchema().getKey()).getValues());
-        }
-
-        return merged;
+        return super.save(group);
     }
 
     @Override
     public void delete(final Group group) {
-        for (Membership membership : findMemberships(group)) {
-            membership.getUser().removeMembership(membership);
-            userDAO.save(membership.getUser());
+        for (AMembership membership : findAMemberships(group)) {
+            membership.getLeftEnd().remove(membership);
+            anyObjectDAO.save(membership.getLeftEnd());
+
+            entityManager.remove(membership);
+        }
+        for (UMembership membership : findUMemberships(group)) {
+            membership.getLeftEnd().remove(membership);
+            userDAO.save(membership.getLeftEnd());
 
             entityManager.remove(membership);
         }
@@ -352,76 +202,69 @@ public class JPAGroupDAO extends AbstractSubjectDAO<GPlainAttr, GDerAttr, GVirAt
         entityManager.remove(group);
     }
 
-    @Override
-    public void delete(final Long key) {
-        Group group = (Group) findInternal(key);
-        if (group == null) {
-            return;
-        }
+    private void populateTransitiveResources(
+            final Group group, final Any<?, ?, ?> any, final Map<Long, PropagationByResource> result) {
 
-        delete(group);
-    }
+        PropagationByResource propByRes = new PropagationByResource();
+        for (ExternalResource resource : group.getResources()) {
+            if (!any.getResources().contains(resource)) {
+                propByRes.add(ResourceOperation.DELETE, resource.getKey());
+            }
 
-    @Override
-    public Group authFetch(final Long key) {
-        if (key == null) {
-            throw new NotFoundException("Null group id");
+            if (!propByRes.isEmpty()) {
+                result.put(any.getKey(), propByRes);
+            }
         }
+    }
 
-        final Group group = find(key);
-        if (group == null) {
-            throw new NotFoundException("Group " + key);
-        }
+    @Transactional(readOnly = true)
+    @Override
+    public Map<Long, PropagationByResource> findAnyObjectsWithTransitiveResources(final Long groupKey) {
+        Group group = authFind(groupKey);
 
-        Set<String> authRealms = AuthContextUtils.getAuthorizations().get(Entitlement.GROUP_READ);
-        boolean authorized = CollectionUtils.exists(authRealms, new Predicate<String>() {
+        Map<Long, PropagationByResource> result = new HashMap<>();
 
-            @Override
-            public boolean evaluate(final String realm) {
-                return group.getRealm().getFullPath().startsWith(realm)
-                        || realm.equals(RealmUtils.getGroupOwnerRealm(group.getRealm().getFullPath(), group.getKey()));
-            }
-        });
-        if (authRealms == null || authRealms.isEmpty() || !authorized) {
-            throw new UnauthorizedException(SubjectType.GROUP, group.getKey());
+        for (AMembership membership : findAMemberships(group)) {
+            populateTransitiveResources(group, membership.getLeftEnd(), result);
         }
 
-        return group;
+        return result;
     }
 
     @Transactional(readOnly = true)
     @Override
-    public Map<Long, PropagationByResource> findUsersWithIndirectResources(final Long groupKey) {
-        Group group = authFetch(groupKey);
+    public Map<Long, PropagationByResource> findUsersWithTransitiveResources(final Long groupKey) {
+        Group group = authFind(groupKey);
 
         Map<Long, PropagationByResource> result = new HashMap<>();
 
-        for (Membership membership : findMemberships(group)) {
-            User user = membership.getUser();
+        for (UMembership membership : findUMemberships(group)) {
+            populateTransitiveResources(group, membership.getLeftEnd(), result);
+        }
+
+        return result;
+    }
 
-            PropagationByResource propByRes = new PropagationByResource();
-            for (ExternalResource resource : group.getResources()) {
-                if (!user.getResources().contains(resource)) {
-                    propByRes.add(ResourceOperation.DELETE, resource.getKey());
-                }
+    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
+    @Override
+    public void refreshDynMemberships(final AnyObject anyObject) {
+        for (Group role : findAll(SyncopeConstants.FULL_ADMIN_REALMS, -1, -1)) {
+            if (role.getADynMembership() != null && !searchDAO.matches(anyObject,
+                    SearchCondConverter.convert(role.getADynMembership().getFIQLCond()), AnyTypeKind.ANY_OBJECT)) {
 
-                if (!propByRes.isEmpty()) {
-                    result.put(user.getKey(), propByRes);
-                }
+                role.getADynMembership().remove(anyObject);
             }
         }
-
-        return result;
     }
 
     @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
     @Override
     public void refreshDynMemberships(final User user) {
         for (Group role : findAll(SyncopeConstants.FULL_ADMIN_REALMS, -1, -1)) {
-            if (role.getDynMembership() != null && !searchDAO.matches(user,
-                    SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), SubjectType.USER)) {
+            if (role.getUDynMembership() != null && !searchDAO.matches(user,
+                    SearchCondConverter.convert(role.getUDynMembership().getFIQLCond()), AnyTypeKind.USER)) {
 
-                role.getDynMembership().removeUser(user);
+                role.getUDynMembership().remove(user);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAMembershipDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAMembershipDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAMembershipDAO.java
deleted file mode 100644
index 998f680..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAMembershipDAO.java
+++ /dev/null
@@ -1,104 +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.persistence.jpa.dao;
-
-import java.util.List;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import org.apache.syncope.core.persistence.api.dao.MembershipDAO;
-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.membership.Membership;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMembership;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public class JPAMembershipDAO extends AbstractDAO<Membership, Long> implements MembershipDAO {
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Override
-    public Membership find(final Long key) {
-        return entityManager.find(JPAMembership.class, key);
-    }
-
-    @Override
-    public Membership find(final User user, final Group group) {
-        Query query = entityManager.createQuery(
-                "SELECT e FROM " + JPAMembership.class.getSimpleName()
-                + " e WHERE e.user = :user AND e.group = :group");
-        query.setParameter("user", user);
-        query.setParameter("group", group);
-
-        Membership result = null;
-
-        try {
-            result = (Membership) query.getSingleResult();
-        } catch (NoResultException e) {
-            LOG.debug("No membership was found for user {} and group {}", user, group, e);
-        }
-
-        return result;
-    }
-
-    @Override
-    public List<Membership> findAll() {
-        TypedQuery<Membership> query = entityManager.createQuery(
-                "SELECT e FROM " + JPAMembership.class.getSimpleName() + " e", Membership.class);
-        return query.getResultList();
-    }
-
-    @Override
-    public Membership save(final Membership membership) {
-        return entityManager.merge(membership);
-    }
-
-    @Override
-    public void delete(final Long key) {
-        Membership membership = find(key);
-        if (membership == null) {
-            return;
-        }
-
-        membership.getUser().removeMembership(membership);
-        userDAO.save(membership.getUser());
-
-        entityManager.remove(membership);
-    }
-
-    @Override
-    public Membership authFetch(final Long key) {
-        if (key == null) {
-            throw new NotFoundException("Null membership key");
-        }
-
-        Membership membership = find(key);
-        if (membership == null) {
-            throw new NotFoundException("Membership " + key);
-        }
-
-        return membership;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/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 b41066c..5e232fd 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
@@ -19,43 +19,43 @@
 package org.apache.syncope.core.persistence.jpa.dao;
 
 import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
-import org.apache.syncope.core.persistence.api.entity.Attributable;
+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.anyobject.APlainAttr;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.conf.JPACPlainAttr;
-import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttr;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttr;
 import org.springframework.stereotype.Repository;
 
 @Repository
-public class JPAPlainAttrDAO extends AbstractDAO<PlainAttr, Long> implements PlainAttrDAO {
+public class JPAPlainAttrDAO extends AbstractDAO<PlainAttr<?>, Long> implements PlainAttrDAO {
 
-    public <T extends PlainAttr> Class<? extends AbstractPlainAttr> getJPAEntityReference(
+    public <T extends PlainAttr<?>> Class<? extends AbstractPlainAttr<?>> getJPAEntityReference(
             final Class<T> reference) {
 
         return CPlainAttr.class.isAssignableFrom(reference)
                 ? JPACPlainAttr.class
                 : GPlainAttr.class.isAssignableFrom(reference)
                         ? JPAGPlainAttr.class
-                        : MPlainAttr.class.isAssignableFrom(reference)
-                                ? JPAMPlainAttr.class
+                        : APlainAttr.class.isAssignableFrom(reference)
+                                ? JPAAPlainAttr.class
                                 : UPlainAttr.class.isAssignableFrom(reference)
                                         ? JPAUPlainAttr.class
                                         : null;
     }
 
     @Override
-    public <T extends PlainAttr> T find(final Long key, final Class<T> reference) {
+    public <T extends PlainAttr<?>> T find(final Long key, final Class<T> reference) {
         return reference.cast(entityManager.find(getJPAEntityReference(reference), key));
     }
 
     @Override
-    public <T extends PlainAttr> void delete(final Long key, final Class<T> reference) {
+    public <T extends PlainAttr<?>> void delete(final Long key, final Class<T> reference) {
         T attribute = find(key, reference);
         if (attribute == null) {
             return;
@@ -66,9 +66,9 @@ public class JPAPlainAttrDAO extends AbstractDAO<PlainAttr, Long> implements Pla
 
     @Override
     @SuppressWarnings("unchecked")
-    public <T extends PlainAttr> void delete(final T plainAttr) {
+    public <T extends PlainAttr<?>> void delete(final T plainAttr) {
         if (plainAttr.getOwner() != null) {
-            ((Attributable<T, ?, ?>) plainAttr.getOwner()).removePlainAttr(plainAttr);
+            ((Any<T, ?, ?>) plainAttr.getOwner()).remove(plainAttr);
         }
 
         entityManager.remove(plainAttr);

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
index 4b99051..655decd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainAttrValueDAO.java
@@ -22,19 +22,19 @@ import java.util.List;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.core.persistence.api.dao.PlainAttrValueDAO;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttrUniqueValue;
-import org.apache.syncope.core.persistence.api.entity.membership.MPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAPlainAttrValue;
 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.membership.JPAMPlainAttrUniqueValue;
-import org.apache.syncope.core.persistence.jpa.entity.membership.JPAMPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.jpa.entity.group.JPAGPlainAttrValue;
 import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainAttrUniqueValue;
@@ -55,10 +55,10 @@ public class JPAPlainAttrValueDAO extends AbstractDAO<PlainAttrValue, Long> impl
                                 ? JPAGPlainAttrValue.class
                                 : reference.equals(GPlainAttrUniqueValue.class)
                                         ? JPAGPlainAttrUniqueValue.class
-                                        : reference.equals(MPlainAttrValue.class)
-                                                ? JPAMPlainAttrValue.class
-                                                : reference.equals(MPlainAttrUniqueValue.class)
-                                                        ? JPAMPlainAttrUniqueValue.class
+                                        : reference.equals(APlainAttrValue.class)
+                                                ? JPAAPlainAttrValue.class
+                                                : reference.equals(APlainAttrUniqueValue.class)
+                                                        ? JPAAPlainAttrUniqueValue.class
                                                         : reference.equals(UPlainAttrValue.class)
                                                                 ? JPAUPlainAttrValue.class
                                                                 : reference.equals(UPlainAttrUniqueValue.class)
@@ -96,7 +96,7 @@ public class JPAPlainAttrValueDAO extends AbstractDAO<PlainAttrValue, Long> impl
     @Override
     public <T extends PlainAttrValue> void delete(final T attrValue) {
         if (attrValue.getAttr() != null) {
-            attrValue.getAttr().removeValue(attrValue);
+            attrValue.getAttr().remove(attrValue);
         }
 
         entityManager.remove(attrValue);

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/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 cc7df33..a922946 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
@@ -20,29 +20,16 @@ package org.apache.syncope.core.persistence.jpa.dao;
 
 import java.util.List;
 import javax.persistence.TypedQuery;
-import org.apache.commons.collections4.Closure;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.syncope.common.lib.types.AttributableType;
-import org.apache.syncope.core.persistence.api.dao.AttrTemplateDAO;
+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.PlainAttrDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtils;
+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.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.group.GMappingItem;
-import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GPlainSchema;
-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.group.JPAGPlainSchema;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUPlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
 
@@ -53,46 +40,25 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema, String> implemen
     private PlainAttrDAO plainAttrDAO;
 
     @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
-                : GPlainSchema.class.isAssignableFrom(reference)
-                        ? JPAGPlainSchema.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));
+    public PlainSchema find(final String key) {
+        return entityManager.find(JPAPlainSchema.class, 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);
+    public List<PlainSchema> findAll() {
+        TypedQuery<PlainSchema> query = entityManager.createQuery(
+                "SELECT e FROM " + JPAPlainSchema.class.getSimpleName() + " e", PlainSchema.class);
         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 ").
+    public <T extends PlainAttr<?>> List<T> findAttrs(final PlainSchema schema, final Class<T> reference) {
+        StringBuilder queryString = new StringBuilder("SELECT e FROM ").
                 append(((JPAPlainAttrDAO) plainAttrDAO).getJPAEntityReference(reference).getSimpleName()).
-                append(" e WHERE e.");
-        if (GPlainAttr.class.isAssignableFrom(reference) || MPlainAttr.class.isAssignableFrom(reference)) {
-            queryString.append("template.");
-        }
-        queryString.append("schema=:schema");
+                append(" e WHERE e.schema=:schema");
 
         TypedQuery<T> query = entityManager.createQuery(queryString.toString(), reference);
         query.setParameter("schema", schema);
@@ -101,45 +67,28 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema, String> implemen
     }
 
     @Override
-    public <T extends PlainSchema> T save(final T schema) {
+    public PlainSchema save(final PlainSchema schema) {
         return entityManager.merge(schema);
     }
 
     @Override
-    @SuppressWarnings("unchecked")
-    public void delete(final String key, final AttributableUtils attributableUtil) {
-        PlainSchema schema = find(key, attributableUtil.plainSchemaClass());
+    public void delete(final String key) {
+        PlainSchema schema = find(key);
         if (schema == null) {
             return;
         }
 
-        CollectionUtils.forAllDo(findAttrs(schema, attributableUtil.plainAttrClass()), new Closure<PlainAttr>() {
+        AnyUtilsFactory anyUtilsFactory = new JPAAnyUtilsFactory();
+        for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
+            AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
 
-            @Override
-            public void execute(final PlainAttr input) {
-                plainAttrDAO.delete(input.getKey(), attributableUtil.plainAttrClass());
+            for (PlainAttr<?> attr : findAttrs(schema, anyUtils.plainAttrClass())) {
+                plainAttrDAO.delete(attr.getKey(), anyUtils.plainAttrClass());
             }
 
-        });
-
-        if (attributableUtil.getType() == AttributableType.GROUP
-                || attributableUtil.getType() == AttributableType.MEMBERSHIP) {
-
-            CollectionUtils.forAllDo(attrTemplateDAO.
-                    findBySchemaName(schema.getKey(), attributableUtil.plainAttrTemplateClass()).iterator(),
-                    new Closure<Number>() {
-
-                        @Override
-                        public void execute(final Number input) {
-                            attrTemplateDAO.delete(input.longValue(), attributableUtil.plainAttrTemplateClass());
-                        }
-
-                    });
+            resourceDAO.deleteMapping(key, anyUtils.plainIntMappingType());
         }
 
-        resourceDAO.deleteMapping(key, attributableUtil.plainIntMappingType(), UMappingItem.class);
-        resourceDAO.deleteMapping(key, attributableUtil.plainIntMappingType(), GMappingItem.class);
-
         entityManager.remove(schema);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
index 1007ac4..176cfbd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
@@ -25,7 +25,7 @@ import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
-import org.apache.syncope.core.persistence.api.entity.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.Realm;

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
index c195bd9..5f600b6 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARoleDAO.java
@@ -22,10 +22,10 @@ import java.util.List;
 import javax.persistence.NoResultException;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.SubjectType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
-import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
+import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Role;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -39,7 +39,7 @@ import org.springframework.transaction.annotation.Transactional;
 public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO {
 
     @Autowired
-    private SubjectSearchDAO searchDAO;
+    private AnySearchDAO searchDAO;
 
     @Override
     public Role find(final Long key) {
@@ -82,11 +82,11 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO {
         // refresh dynaminc memberships
         if (role.getDynMembership() != null) {
             List<User> matchingUsers = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                    SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), SubjectType.USER);
+                    SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), AnyTypeKind.USER);
 
-            role.getDynMembership().getUsers().clear();
+            role.getDynMembership().getMembers().clear();
             for (User user : matchingUsers) {
-                role.getDynMembership().addUser(user);
+                role.getDynMembership().add(user);
             }
         }
 
@@ -113,9 +113,9 @@ public class JPARoleDAO extends AbstractDAO<Role, Long> implements RoleDAO {
     public void refreshDynMemberships(final User user) {
         for (Role role : findAll()) {
             if (role.getDynMembership() != null && !searchDAO.matches(user,
-                    SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), SubjectType.USER)) {
+                    SearchCondConverter.convert(role.getDynMembership().getFIQLCond()), AnyTypeKind.USER)) {
 
-                role.getDynMembership().removeUser(user);
+                role.getDynMembership().remove(user);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASubjectSearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASubjectSearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASubjectSearchDAO.java
deleted file mode 100644
index b4cbad8..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPASubjectSearchDAO.java
+++ /dev/null
@@ -1,778 +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.persistence.jpa.dao;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.persistence.Entity;
-import javax.persistence.Query;
-import javax.persistence.TemporalType;
-import javax.validation.ValidationException;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Transformer;
-import org.apache.commons.lang3.ClassUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.SubjectType;
-import org.apache.syncope.core.misc.RealmUtils;
-import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
-import org.apache.syncope.core.persistence.api.dao.search.GroupCond;
-import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.dao.search.ResourceCond;
-import org.apache.syncope.core.persistence.api.dao.search.RoleCond;
-import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
-import org.apache.syncope.core.persistence.api.dao.search.SubjectCond;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtils;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtilsFactory;
-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.Realm;
-import org.apache.syncope.core.persistence.api.entity.Subject;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Repository;
-import org.springframework.util.ReflectionUtils;
-
-@Repository
-public class JPASubjectSearchDAO extends AbstractDAO<Subject<?, ?, ?>, Long> implements SubjectSearchDAO {
-
-    private static final String EMPTY_ATTR_QUERY = "SELECT subject_id FROM user_search_attr WHERE 1=2";
-
-    @Autowired
-    private RealmDAO realmDAO;
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private GroupDAO groupDAO;
-
-    @Autowired
-    private PlainSchemaDAO schemaDAO;
-
-    @Autowired
-    private AttributableUtilsFactory attrUtilsFactory;
-
-    private String getAdminRealmsFilter(final Set<String> adminRealms, final SearchSupport svs) {
-        Set<Long> realmKeys = new HashSet<>();
-        for (String realmPath : RealmUtils.normalize(adminRealms)) {
-            Realm realm = realmDAO.find(realmPath);
-            if (realm == null) {
-                LOG.warn("Ignoring invalid realm {}", realmPath);
-            } else {
-                CollectionUtils.collect(realmDAO.findDescendants(realm), new Transformer<Realm, Long>() {
-
-                    @Override
-                    public Long transform(final Realm descendant) {
-                        return descendant.getKey();
-                    }
-                }, realmKeys);
-            }
-        }
-
-        StringBuilder adminRealmFilter = new StringBuilder().
-                append("SELECT subject_id FROM ").append(svs.field().name).
-                append(" WHERE realm_id IN (SELECT id AS realm_id FROM Realm");
-
-        boolean firstRealm = true;
-        for (Long realmKey : realmKeys) {
-            if (firstRealm) {
-                adminRealmFilter.append(" WHERE");
-                firstRealm = false;
-            } else {
-                adminRealmFilter.append(" OR");
-            }
-            adminRealmFilter.append(" id = ").append(realmKey);
-        }
-
-        adminRealmFilter.append(')');
-
-        return adminRealmFilter.toString();
-    }
-
-    @Override
-    public int count(final Set<String> adminRealms, final SearchCond searchCondition, final SubjectType type) {
-        List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
-
-        // 1. get the query string from the search condition
-        SearchSupport svs = new SearchSupport(type);
-        StringBuilder queryString = getQuery(searchCondition, parameters, type, svs);
-
-        // 2. take into account administrative realms
-        queryString.insert(0, "SELECT u.subject_id FROM (");
-        queryString.append(") u WHERE subject_id IN (");
-        queryString.append(getAdminRealmsFilter(adminRealms, svs)).append(')');
-
-        // 3. prepare the COUNT query
-        queryString.insert(0, "SELECT COUNT(subject_id) FROM (");
-        queryString.append(") count_subject_id");
-
-        Query countQuery = entityManager.createNativeQuery(queryString.toString());
-        fillWithParameters(countQuery, parameters);
-
-        LOG.debug("Native count query\n{}\nwith parameters\n{}", queryString.toString(), parameters);
-
-        int result = ((Number) countQuery.getSingleResult()).intValue();
-        LOG.debug("Native count query result: {}", result);
-
-        return result;
-    }
-
-    @Override
-    public <T extends Subject<?, ?, ?>> List<T> search(
-            final Set<String> adminRealms, final SearchCond searchCondition, final SubjectType type) {
-
-        return search(adminRealms, searchCondition, Collections.<OrderByClause>emptyList(), type);
-    }
-
-    @Override
-    public <T extends Subject<?, ?, ?>> List<T> search(
-            final Set<String> adminRealms, final SearchCond searchCondition, final List<OrderByClause> orderBy,
-            final SubjectType type) {
-
-        return search(adminRealms, searchCondition, -1, -1, orderBy, type);
-    }
-
-    @Override
-    public <T extends Subject<?, ?, ?>> List<T> search(
-            final Set<String> adminRealms, final SearchCond searchCondition, final int page, final int itemsPerPage,
-            final List<OrderByClause> orderBy, final SubjectType type) {
-
-        List<T> result = Collections.<T>emptyList();
-
-        if (adminRealms != null && !adminRealms.isEmpty()) {
-            LOG.debug("Search condition:\n{}", searchCondition);
-
-            if (searchCondition != null && searchCondition.isValid()) {
-                try {
-                    result = doSearch(adminRealms, searchCondition, page, itemsPerPage, orderBy, type);
-                } catch (Exception e) {
-                    LOG.error("While searching for {}", type, e);
-                }
-            } else {
-                LOG.error("Invalid search condition:\n{}", searchCondition);
-            }
-        }
-
-        return result;
-    }
-
-    @Override
-    public <T extends Subject<?, ?, ?>> boolean matches(
-            final T subject, final SearchCond searchCondition, final SubjectType type) {
-
-        List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
-
-        // 1. get the query string from the search condition
-        SearchSupport svs = new SearchSupport(type);
-        StringBuilder queryString = getQuery(searchCondition, parameters, type, svs);
-
-        boolean matches;
-        if (queryString.length() == 0) {
-            // Could be empty: got into a group search with a single membership condition ...
-            matches = false;
-        } else {
-            // 2. take into account the passed user
-            queryString.insert(0, "SELECT u.subject_id FROM (");
-            queryString.append(") u WHERE subject_id=?").append(setParameter(parameters, subject.getKey()));
-
-            // 3. prepare the search query
-            Query query = entityManager.createNativeQuery(queryString.toString());
-
-            // 4. populate the search query with parameter values
-            fillWithParameters(query, parameters);
-
-            // 5. executes query
-            matches = !query.getResultList().isEmpty();
-        }
-
-        return matches;
-    }
-
-    private int setParameter(final List<Object> parameters, final Object parameter) {
-        int key;
-        synchronized (parameters) {
-            parameters.add(parameter);
-            key = parameters.size();
-        }
-
-        return key;
-    }
-
-    private void fillWithParameters(final Query query, final List<Object> parameters) {
-        for (int i = 0; i < parameters.size(); i++) {
-            if (parameters.get(i) instanceof Date) {
-                query.setParameter(i + 1, (Date) parameters.get(i), TemporalType.TIMESTAMP);
-            } else if (parameters.get(i) instanceof Boolean) {
-                query.setParameter(i + 1, ((Boolean) parameters.get(i))
-                        ? 1
-                        : 0);
-            } else {
-                query.setParameter(i + 1, parameters.get(i));
-            }
-        }
-    }
-
-    private StringBuilder buildSelect(final OrderBySupport orderBySupport) {
-        final StringBuilder select = new StringBuilder("SELECT u.subject_id");
-
-        for (OrderBySupport.Item obs : orderBySupport.items) {
-            select.append(',').append(obs.select);
-        }
-        select.append(" FROM ");
-
-        return select;
-    }
-
-    private StringBuilder buildWhere(final OrderBySupport orderBySupport) {
-        final StringBuilder where = new StringBuilder(" u");
-        for (SearchSupport.SearchView searchView : orderBySupport.views) {
-            where.append(',').append(searchView.name).append(' ').append(searchView.alias);
-        }
-        where.append(" WHERE ");
-        for (SearchSupport.SearchView searchView : orderBySupport.views) {
-            where.append("u.subject_id=").append(searchView.alias).append(".subject_id AND ");
-        }
-
-        for (OrderBySupport.Item obs : orderBySupport.items) {
-            if (StringUtils.isNotBlank(obs.where)) {
-                where.append(obs.where).append(" AND ");
-            }
-        }
-        where.append("u.subject_id IN (");
-
-        return where;
-    }
-
-    private StringBuilder buildOrderBy(final OrderBySupport orderBySupport) {
-        final StringBuilder orderBy = new StringBuilder();
-
-        for (OrderBySupport.Item obs : orderBySupport.items) {
-            orderBy.append(obs.orderBy).append(',');
-        }
-        if (!orderBySupport.items.isEmpty()) {
-            orderBy.insert(0, " ORDER BY ");
-            orderBy.deleteCharAt(orderBy.length() - 1);
-        }
-
-        return orderBy;
-    }
-
-    private OrderBySupport parseOrderBy(final SubjectType type, final SearchSupport svs,
-            final List<OrderByClause> orderByClauses) {
-
-        final AttributableUtils attrUtils = attrUtilsFactory.getInstance(type.asAttributableType());
-
-        OrderBySupport orderBySupport = new OrderBySupport();
-
-        for (OrderByClause clause : orderByClauses) {
-            OrderBySupport.Item obs = new OrderBySupport.Item();
-
-            // Manage difference among external key attribute and internal JPA @Id
-            String fieldName = "key".equals(clause.getField()) ? "id" : clause.getField();
-
-            Field subjectField = ReflectionUtils.findField(attrUtils.attributableClass(), fieldName);
-            if (subjectField == null) {
-                PlainSchema schema = schemaDAO.find(fieldName, attrUtils.plainSchemaClass());
-                if (schema != null) {
-                    if (schema.isUniqueConstraint()) {
-                        orderBySupport.views.add(svs.uniqueAttr());
-
-                        obs.select = new StringBuilder().
-                                append(svs.uniqueAttr().alias).append('.').append(svs.fieldName(schema.getType())).
-                                append(" AS ").append(fieldName).toString();
-                        obs.where = new StringBuilder().
-                                append(svs.uniqueAttr().alias).
-                                append(".schema_name='").append(fieldName).append("'").toString();
-                        obs.orderBy = fieldName + " " + clause.getDirection().name();
-                    } else {
-                        orderBySupport.views.add(svs.attr());
-
-                        obs.select = new StringBuilder().
-                                append(svs.attr().alias).append('.').append(svs.fieldName(schema.getType())).
-                                append(" AS ").append(fieldName).toString();
-                        obs.where = new StringBuilder().
-                                append(svs.attr().alias).
-                                append(".schema_name='").append(fieldName).append("'").toString();
-                        obs.orderBy = fieldName + " " + clause.getDirection().name();
-                    }
-                }
-            } else {
-                orderBySupport.views.add(svs.field());
-
-                obs.select = svs.field().alias + "." + fieldName;
-                obs.where = StringUtils.EMPTY;
-                obs.orderBy = svs.field().alias + "." + fieldName + " " + clause.getDirection().name();
-            }
-
-            if (obs.isEmpty()) {
-                LOG.warn("Cannot build any valid clause from {}", clause);
-            } else {
-                orderBySupport.items.add(obs);
-            }
-        }
-
-        return orderBySupport;
-    }
-
-    @SuppressWarnings("unchecked")
-    private <T extends Subject<?, ?, ?>> List<T> doSearch(final Set<String> adminRealms,
-            final SearchCond nodeCond, final int page, final int itemsPerPage, final List<OrderByClause> orderBy,
-            final SubjectType type) {
-
-        List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
-
-        // 1. get the query string from the search condition
-        SearchSupport svs = new SearchSupport(type);
-        StringBuilder queryString = getQuery(nodeCond, parameters, type, svs);
-
-        // 2. take into account administrative groups and ordering
-        OrderBySupport orderBySupport = parseOrderBy(type, svs, orderBy);
-        if (queryString.charAt(0) == '(') {
-            queryString.insert(0, buildSelect(orderBySupport));
-            queryString.append(buildWhere(orderBySupport));
-        } else {
-            queryString.insert(0, buildSelect(orderBySupport).append('('));
-            queryString.append(')').append(buildWhere(orderBySupport));
-        }
-        queryString.
-                append(getAdminRealmsFilter(adminRealms, svs)).append(')').
-                append(buildOrderBy(orderBySupport));
-
-        // 3. prepare the search query
-        Query query = entityManager.createNativeQuery(queryString.toString());
-
-        // 4. page starts from 1, while setFirtResult() starts from 0
-        query.setFirstResult(itemsPerPage * (page <= 0 ? 0 : page - 1));
-
-        if (itemsPerPage >= 0) {
-            query.setMaxResults(itemsPerPage);
-        }
-
-        // 5. populate the search query with parameter values
-        fillWithParameters(query, parameters);
-
-        LOG.debug("Native query\n{}\nwith parameters\n{}", queryString.toString(), parameters);
-
-        // 6. Prepare the result (avoiding duplicates)
-        List<T> result = new ArrayList<>();
-
-        for (Object subjectId : query.getResultList()) {
-            long actualId;
-            if (subjectId instanceof Object[]) {
-                actualId = ((Number) ((Object[]) subjectId)[0]).longValue();
-            } else {
-                actualId = ((Number) subjectId).longValue();
-            }
-
-            T subject = type == SubjectType.USER
-                    ? (T) userDAO.find(actualId)
-                    : (T) groupDAO.find(actualId);
-            if (subject == null) {
-                LOG.error("Could not find {} with id {}, even though returned by the native query",
-                        type, actualId);
-            } else {
-                if (!result.contains(subject)) {
-                    result.add(subject);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    private StringBuilder getQuery(final SearchCond nodeCond, final List<Object> parameters,
-            final SubjectType type, final SearchSupport svs) {
-
-        StringBuilder query = new StringBuilder();
-
-        switch (nodeCond.getType()) {
-
-            case LEAF:
-            case NOT_LEAF:
-                if (nodeCond.getGroupCond() != null && SubjectType.USER == type) {
-                    query.append(getQuery(nodeCond.getGroupCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                }
-                if (nodeCond.getRoleCond() != null && SubjectType.USER == type) {
-                    query.append(getQuery(nodeCond.getRoleCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                }
-                if (nodeCond.getResourceCond() != null) {
-                    query.append(getQuery(nodeCond.getResourceCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
-                }
-                if (nodeCond.getAttributeCond() != null) {
-                    query.append(getQuery(nodeCond.getAttributeCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
-                }
-                if (nodeCond.getSubjectCond() != null) {
-                    query.append(getQuery(nodeCond.getSubjectCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, type, svs));
-                }
-                break;
-
-            case AND:
-                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, type, svs)).
-                        append(" AND subject_id IN ( ").
-                        append(getQuery(nodeCond.getRightNodeCond(), parameters, type, svs)).
-                        append(")");
-                break;
-
-            case OR:
-                query.append(getQuery(nodeCond.getLeftNodeCond(), parameters, type, svs)).
-                        append(" OR subject_id IN ( ").
-                        append(getQuery(nodeCond.getRightNodeCond(), parameters, type, svs)).
-                        append(")");
-                break;
-
-            default:
-        }
-
-        return query;
-    }
-
-    private String getQuery(final GroupCond cond, final boolean not, final List<Object> parameters,
-            final SearchSupport svs) {
-
-        StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
-                append(svs.field().name).append(" WHERE ");
-
-        if (not) {
-            query.append("subject_id NOT IN (");
-        } else {
-            query.append("subject_id IN (");
-        }
-
-        query.append("SELECT DISTINCT subject_id ").append("FROM ").
-                append(svs.membership().name).append(" WHERE ").
-                append("group_id=?").append(setParameter(parameters, cond.getGroupKey())).
-                append(')');
-
-        if (not) {
-            query.append("AND subject_id NOT IN (");
-        } else {
-            query.append("OR subject_id IN (");
-        }
-
-        query.append("SELECT DISTINCT subject_id ").append("FROM ").
-                append(svs.dyngroupmembership().name).append(" WHERE ").
-                append("group_id=?").append(setParameter(parameters, cond.getGroupKey())).
-                append(')');
-
-        return query.toString();
-    }
-
-    private String getQuery(final RoleCond cond, final boolean not, final List<Object> parameters,
-            final SearchSupport svs) {
-
-        StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
-                append(svs.field().name).append(" WHERE ");
-
-        if (not) {
-            query.append("subject_id NOT IN (");
-        } else {
-            query.append("subject_id IN (");
-        }
-
-        query.append("SELECT DISTINCT subject_id ").append("FROM ").
-                append(svs.role().name).append(" WHERE ").
-                append("role_id=?").append(setParameter(parameters, cond.getRoleKey())).
-                append(')');
-
-        if (not) {
-            query.append("AND subject_id NOT IN (");
-        } else {
-            query.append("OR subject_id IN (");
-        }
-
-        query.append("SELECT DISTINCT subject_id ").append("FROM ").
-                append(svs.dynrolemembership().name).append(" WHERE ").
-                append("role_id=?").append(setParameter(parameters, cond.getRoleKey())).
-                append(')');
-
-        return query.toString();
-    }
-
-    private String getQuery(final ResourceCond cond, final boolean not, final List<Object> parameters,
-            final SubjectType type, final SearchSupport svs) {
-
-        final StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
-                append(svs.field().name).append(" WHERE ");
-
-        if (not) {
-            query.append("subject_id NOT IN (");
-        } else {
-            query.append("subject_id IN (");
-        }
-
-        query.append("SELECT DISTINCT subject_id FROM ").
-                append(svs.resource().name).
-                append(" WHERE resource_name=?").
-                append(setParameter(parameters, cond.getResourceName()));
-
-        if (type == SubjectType.USER) {
-            query.append(" UNION SELECT DISTINCT subject_id FROM ").
-                    append(svs.groupResource().name).
-                    append(" WHERE resource_name=?").
-                    append(setParameter(parameters, cond.getResourceName()));
-        }
-
-        query.append(')');
-
-        return query.toString();
-    }
-
-    private void fillAttributeQuery(final StringBuilder query, final PlainAttrValue attrValue,
-            final PlainSchema schema, final AttributeCond cond, final boolean not,
-            final List<Object> parameters, final SearchSupport svs) {
-
-        String column = (cond instanceof SubjectCond)
-                ? cond.getSchema()
-                : "' AND " + svs.fieldName(schema.getType());
-
-        switch (cond.getType()) {
-
-            case ISNULL:
-                query.append(column).append(not
-                        ? " IS NOT NULL"
-                        : " IS NULL");
-                break;
-
-            case ISNOTNULL:
-                query.append(column).append(not
-                        ? " IS NULL"
-                        : " IS NOT NULL");
-                break;
-
-            case LIKE:
-                if (schema.getType() == AttrSchemaType.String || schema.getType() == AttrSchemaType.Enum) {
-                    query.append(column);
-                    if (not) {
-                        query.append(" NOT ");
-                    }
-                    query.append(" LIKE ?").append(setParameter(parameters, cond.getExpression()));
-                } else {
-                    if (!(cond instanceof SubjectCond)) {
-                        query.append("' AND");
-                    }
-                    query.append(" 1=2");
-                    LOG.error("LIKE is only compatible with string or enum schemas");
-                }
-                break;
-
-            case EQ:
-                query.append(column);
-                if (not) {
-                    query.append("<>");
-                } else {
-                    query.append('=');
-                }
-                query.append('?').append(setParameter(parameters, attrValue.getValue()));
-                break;
-
-            case GE:
-                query.append(column);
-                if (not) {
-                    query.append('<');
-                } else {
-                    query.append(">=");
-                }
-                query.append('?').append(setParameter(parameters, attrValue.getValue()));
-                break;
-
-            case GT:
-                query.append(column);
-                if (not) {
-                    query.append("<=");
-                } else {
-                    query.append('>');
-                }
-                query.append('?').append(setParameter(parameters, attrValue.getValue()));
-                break;
-
-            case LE:
-                query.append(column);
-                if (not) {
-                    query.append('>');
-                } else {
-                    query.append("<=");
-                }
-                query.append('?').append(setParameter(parameters, attrValue.getValue()));
-                break;
-
-            case LT:
-                query.append(column);
-                if (not) {
-                    query.append(">=");
-                } else {
-                    query.append('<');
-                }
-                query.append('?').append(setParameter(parameters, attrValue.getValue()));
-                break;
-
-            default:
-        }
-    }
-
-    private String getQuery(final AttributeCond cond, final boolean not, final List<Object> parameters,
-            final SubjectType type, final SearchSupport svs) {
-
-        final AttributableUtils attrUtils = attrUtilsFactory.getInstance(type.asAttributableType());
-
-        PlainSchema schema = schemaDAO.find(cond.getSchema(), attrUtils.plainSchemaClass());
-        if (schema == null) {
-            LOG.warn("Ignoring invalid schema '{}'", cond.getSchema());
-            return EMPTY_ATTR_QUERY;
-        }
-
-        PlainAttrValue attrValue = attrUtils.newPlainAttrValue();
-        try {
-            if (cond.getType() != AttributeCond.Type.LIKE && cond.getType() != AttributeCond.Type.ISNULL
-                    && cond.getType() != AttributeCond.Type.ISNOTNULL) {
-
-                schema.getValidator().validate(cond.getExpression(), attrValue);
-            }
-        } catch (ValidationException e) {
-            LOG.error("Could not validate expression '" + cond.getExpression() + "'", e);
-            return EMPTY_ATTR_QUERY;
-        }
-
-        StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ");
-        if (cond.getType() == AttributeCond.Type.ISNOTNULL) {
-            query.append(svs.field().name).
-                    append(" WHERE subject_id NOT IN (SELECT subject_id FROM ").
-                    append(svs.nullAttr().name).
-                    append(" WHERE schema_name='").append(schema.getKey()).append("')");
-        } else {
-            if (cond.getType() == AttributeCond.Type.ISNULL) {
-                query.append(svs.nullAttr().name).
-                        append(" WHERE schema_name='").append(schema.getKey()).append("'");
-            } else {
-                if (schema.isUniqueConstraint()) {
-                    query.append(svs.uniqueAttr().name);
-                } else {
-                    query.append(svs.attr().name);
-                }
-                query.append(" WHERE schema_name='").append(schema.getKey());
-
-                fillAttributeQuery(query, attrValue, schema, cond, not, parameters, svs);
-            }
-        }
-
-        return query.toString();
-    }
-
-    @SuppressWarnings("rawtypes")
-    private String getQuery(final SubjectCond cond, final boolean not, final List<Object> parameters,
-            final SubjectType type, final SearchSupport svs) {
-
-        final AttributableUtils attrUtils = attrUtilsFactory.getInstance(type.asAttributableType());
-
-        // Keeps track of difference between entity's getKey() and JPA @Id fields
-        if ("key".equals(cond.getSchema())) {
-            cond.setSchema("id");
-        }
-
-        Field subjectField = ReflectionUtils.findField(attrUtils.attributableClass(), cond.getSchema());
-        if (subjectField == null) {
-            LOG.warn("Ignoring invalid schema '{}'", cond.getSchema());
-            return EMPTY_ATTR_QUERY;
-        }
-
-        PlainSchema schema = attrUtils.newPlainSchema();
-        schema.setKey(subjectField.getName());
-        for (AttrSchemaType attrSchemaType : AttrSchemaType.values()) {
-            if (subjectField.getType().isAssignableFrom(attrSchemaType.getType())) {
-                schema.setType(attrSchemaType);
-            }
-        }
-
-        // Deal with subject Integer fields logically mapping to boolean values
-        // (JPAGroup.inheritPlainAttrs, for example)
-        boolean foundBooleanMin = false;
-        boolean foundBooleanMax = false;
-        if (Integer.class.equals(subjectField.getType())) {
-            for (Annotation annotation : subjectField.getAnnotations()) {
-                if (Min.class.equals(annotation.annotationType())) {
-                    foundBooleanMin = ((Min) annotation).value() == 0;
-                } else if (Max.class.equals(annotation.annotationType())) {
-                    foundBooleanMax = ((Max) annotation).value() == 1;
-                }
-            }
-        }
-        if (foundBooleanMin && foundBooleanMax) {
-            schema.setType(AttrSchemaType.Boolean);
-        }
-
-        // Deal with subject fields representing relationships to other entities
-        if (subjectField.getType().getAnnotation(Entity.class) != null) {
-            Method relMethod = null;
-            try {
-                relMethod = ClassUtils.getPublicMethod(subjectField.getType(), "getKey", new Class[0]);
-            } catch (Exception e) {
-                LOG.error("Could not find {}#getKey", subjectField.getType(), e);
-            }
-
-            if (relMethod != null) {
-                if (Long.class.isAssignableFrom(relMethod.getReturnType())) {
-                    cond.setSchema(cond.getSchema() + "_id");
-                    schema.setType(AttrSchemaType.Long);
-                }
-                if (String.class.isAssignableFrom(relMethod.getReturnType())) {
-                    cond.setSchema(cond.getSchema() + "_name");
-                    schema.setType(AttrSchemaType.String);
-                }
-            }
-        }
-
-        PlainAttrValue attrValue = attrUtils.newPlainAttrValue();
-        if (cond.getType() != AttributeCond.Type.LIKE
-                && cond.getType() != AttributeCond.Type.ISNULL
-                && cond.getType() != AttributeCond.Type.ISNOTNULL) {
-
-            try {
-                schema.getValidator().validate(cond.getExpression(), attrValue);
-            } catch (ValidationException e) {
-                LOG.error("Could not validate expression '" + cond.getExpression() + "'", e);
-                return EMPTY_ATTR_QUERY;
-            }
-        }
-
-        final StringBuilder query = new StringBuilder("SELECT DISTINCT subject_id FROM ").
-                append(svs.field().name).append(" WHERE ");
-
-        fillAttributeQuery(query, attrValue, schema, cond, not, parameters, svs);
-
-        return query.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index d90ddbd..ff93071 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -26,7 +26,7 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
-import org.apache.syncope.core.persistence.api.entity.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.task.Task;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPANotificationTask;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPAPropagationTask;