You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2016/12/07 12:27:47 UTC

[3/3] syncope git commit: [SYNCOPE-980] Fix parenthesis for some subqueries, including memberships

[SYNCOPE-980] Fix parenthesis for some subqueries, including memberships


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

Branch: refs/heads/master
Commit: f1d294d6fe23b03ade5f59f9d1b94959c518cb86
Parents: 5cab8af
Author: Francesco Chicchiricc� <il...@apache.org>
Authored: Wed Dec 7 13:26:55 2016 +0100
Committer: Francesco Chicchiricc� <il...@apache.org>
Committed: Wed Dec 7 13:27:36 2016 +0100

----------------------------------------------------------------------
 .../persistence/api/dao/search/SearchCond.java  |  91 +++++++-------
 .../persistence/jpa/dao/JPAAnySearchDAO.java    | 123 +++++++++----------
 .../persistence/jpa/inner/AnySearchTest.java    |  69 ++++++++++-
 .../apache/syncope/fit/core/SearchITCase.java   |  43 +++++++
 4 files changed, 216 insertions(+), 110 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/f1d294d6/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
index 61cc664..e87df92 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/search/SearchCond.java
@@ -55,9 +55,9 @@ public class SearchCond extends AbstractSearchCond {
 
     private MemberCond memberCond;
 
-    private SearchCond leftNodeCond;
+    private SearchCond leftSearchCond;
 
-    private SearchCond rightNodeCond;
+    private SearchCond rightSearchCond;
 
     public static SearchCond getLeafCond(final AnyTypeCond anyTypeCond) {
         SearchCond nodeCond = new SearchCond();
@@ -189,8 +189,8 @@ public class SearchCond extends AbstractSearchCond {
         SearchCond nodeCond = new SearchCond();
 
         nodeCond.type = Type.AND;
-        nodeCond.leftNodeCond = leftCond;
-        nodeCond.rightNodeCond = rightCond;
+        nodeCond.leftSearchCond = leftCond;
+        nodeCond.rightSearchCond = rightCond;
 
         return nodeCond;
     }
@@ -208,8 +208,8 @@ public class SearchCond extends AbstractSearchCond {
         SearchCond nodeCond = new SearchCond();
 
         nodeCond.type = Type.OR;
-        nodeCond.leftNodeCond = leftCond;
-        nodeCond.rightNodeCond = rightCond;
+        nodeCond.leftSearchCond = leftCond;
+        nodeCond.rightSearchCond = rightCond;
 
         return nodeCond;
     }
@@ -231,6 +231,42 @@ public class SearchCond extends AbstractSearchCond {
         this.anyTypeCond = anyTypeCond;
     }
 
+    /**
+     * Not a simple getter: recursively scans the search condition tree.
+     *
+     * @return the AnyType key or {@code NULL} if no type condition was found
+     */
+    public String hasAnyTypeCond() {
+        String anyTypeName = null;
+
+        if (type == null) {
+            return anyTypeName;
+        }
+
+        switch (type) {
+            case LEAF:
+            case NOT_LEAF:
+                if (anyTypeCond != null) {
+                    anyTypeName = anyTypeCond.getAnyTypeKey();
+                }
+                break;
+
+            case AND:
+            case OR:
+                if (leftSearchCond != null) {
+                    anyTypeName = leftSearchCond.hasAnyTypeCond();
+                }
+                if (anyTypeName == null && rightSearchCond != null) {
+                    anyTypeName = rightSearchCond.hasAnyTypeCond();
+                }
+                break;
+
+            default:
+        }
+
+        return anyTypeName;
+    }
+
     public AnyCond getAnyCond() {
         return anyCond;
     }
@@ -267,49 +303,18 @@ public class SearchCond extends AbstractSearchCond {
         return memberCond;
     }
 
-    public SearchCond getLeftNodeCond() {
-        return leftNodeCond;
+    public SearchCond getLeftSearchCond() {
+        return leftSearchCond;
     }
 
-    public SearchCond getRightNodeCond() {
-        return rightNodeCond;
+    public SearchCond getRightSearchCond() {
+        return rightSearchCond;
     }
 
     public Type getType() {
         return type;
     }
 
-    public String hasAnyTypeCond() {
-        String anyTypeName = null;
-
-        if (type == null) {
-            return anyTypeName;
-        }
-
-        switch (type) {
-            case LEAF:
-            case NOT_LEAF:
-                if (anyTypeCond != null) {
-                    anyTypeName = anyTypeCond.getAnyTypeKey();
-                }
-                break;
-
-            case AND:
-            case OR:
-                if (leftNodeCond != null) {
-                    anyTypeName = leftNodeCond.hasAnyTypeCond();
-                }
-                if (anyTypeName == null && rightNodeCond != null) {
-                    anyTypeName = rightNodeCond.hasAnyTypeCond();
-                }
-                break;
-
-            default:
-        }
-
-        return anyTypeName;
-    }
-
     @Override
     public boolean isValid() {
         boolean isValid = false;
@@ -335,9 +340,9 @@ public class SearchCond extends AbstractSearchCond {
 
             case AND:
             case OR:
-                isValid = (leftNodeCond == null || rightNodeCond == null)
+                isValid = (leftSearchCond == null || rightSearchCond == null)
                         ? false
-                        : leftNodeCond.isValid() && rightNodeCond.isValid();
+                        : leftSearchCond.isValid() && rightSearchCond.isValid();
                 break;
 
             default:

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1d294d6/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
index 3f8e5bd..9554f9a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAAnySearchDAO.java
@@ -135,12 +135,12 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
     }
 
     @Override
-    public int count(final Set<String> adminRealms, final SearchCond searchCondition, final AnyTypeKind typeKind) {
+    public int count(final Set<String> adminRealms, final SearchCond cond, final AnyTypeKind typeKind) {
         List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
 
         // 1. get the query string from the search condition
         SearchSupport svs = new SearchSupport(typeKind);
-        StringBuilder queryString = getQuery(searchCondition, parameters, svs);
+        StringBuilder queryString = getQuery(cond, parameters, svs);
 
         // 2. take into account administrative realms
         queryString.insert(0, "SELECT u.any_id FROM (");
@@ -166,35 +166,35 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
     }
 
     @Override
-    public <T extends Any<?>> List<T> search(final SearchCond searchCondition, final AnyTypeKind typeKind) {
-        return search(searchCondition, Collections.<OrderByClause>emptyList(), typeKind);
+    public <T extends Any<?>> List<T> search(final SearchCond cond, final AnyTypeKind typeKind) {
+        return search(cond, Collections.<OrderByClause>emptyList(), typeKind);
     }
 
     @Override
     public <T extends Any<?>> List<T> search(
-            final SearchCond searchCondition, final List<OrderByClause> orderBy, final AnyTypeKind typeKind) {
+            final SearchCond cond, final List<OrderByClause> orderBy, final AnyTypeKind typeKind) {
 
-        return search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, -1, -1, orderBy, typeKind);
+        return search(SyncopeConstants.FULL_ADMIN_REALMS, cond, -1, -1, orderBy, typeKind);
     }
 
     @Override
     public <T extends Any<?>> List<T> search(
-            final Set<String> adminRealms, final SearchCond searchCondition, final int page, final int itemsPerPage,
+            final Set<String> adminRealms, final SearchCond cond, final int page, final int itemsPerPage,
             final List<OrderByClause> orderBy, final AnyTypeKind typeKind) {
 
         List<T> result = Collections.<T>emptyList();
 
         if (adminRealms != null && !adminRealms.isEmpty()) {
-            LOG.debug("Search condition:\n{}", searchCondition);
+            LOG.debug("Search condition:\n{}", cond);
 
-            if (searchCondition != null && searchCondition.isValid()) {
+            if (cond != null && cond.isValid()) {
                 try {
-                    result = doSearch(adminRealms, searchCondition, page, itemsPerPage, orderBy, typeKind);
+                    result = doSearch(adminRealms, cond, page, itemsPerPage, orderBy, typeKind);
                 } catch (Exception e) {
                     LOG.error("While searching for {}", typeKind, e);
                 }
             } else {
-                LOG.error("Invalid search condition:\n{}", searchCondition);
+                LOG.error("Invalid search condition:\n{}", cond);
             }
         }
 
@@ -203,13 +203,13 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
 
     @Override
     public <T extends Any<?>> boolean matches(
-            final T any, final SearchCond searchCondition, final AnyTypeKind typeKind) {
+            final T any, final SearchCond cond, final AnyTypeKind typeKind) {
 
         List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
 
         // 1. get the query string from the search condition
         SearchSupport svs = new SearchSupport(typeKind);
-        StringBuilder queryString = getQuery(searchCondition, parameters, svs);
+        StringBuilder queryString = getQuery(cond, parameters, svs);
 
         boolean matches;
         if (queryString.length() == 0) {
@@ -369,14 +369,14 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
 
     @SuppressWarnings("unchecked")
     private <T extends Any<?>> List<T> doSearch(final Set<String> adminRealms,
-            final SearchCond nodeCond, final int page, final int itemsPerPage, final List<OrderByClause> orderBy,
+            final SearchCond cond, final int page, final int itemsPerPage, final List<OrderByClause> orderBy,
             final AnyTypeKind typeKind) {
 
         List<Object> parameters = Collections.synchronizedList(new ArrayList<>());
 
         // 1. get the query string from the search condition
         SearchSupport svs = new SearchSupport(typeKind);
-        StringBuilder queryString = getQuery(nodeCond, parameters, svs);
+        StringBuilder queryString = getQuery(cond, parameters, svs);
 
         // 2. take into account administrative groups and ordering
         OrderBySupport orderBySupport = parseOrderBy(typeKind, svs, orderBy);
@@ -428,68 +428,67 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         return result;
     }
 
-    private StringBuilder getQuery(final SearchCond nodeCond, final List<Object> parameters, final SearchSupport svs) {
+    private StringBuilder getQuery(final SearchCond cond, final List<Object> parameters, final SearchSupport svs) {
         StringBuilder query = new StringBuilder();
 
-        switch (nodeCond.getType()) {
-
+        switch (cond.getType()) {
             case LEAF:
             case NOT_LEAF:
-                if (nodeCond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind()) {
-                    query.append(getQuery(nodeCond.getAnyTypeCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getRelationshipTypeCond() != null
+                if (cond.getAnyTypeCond() != null && AnyTypeKind.ANY_OBJECT == svs.anyTypeKind()) {
+                    query.append(getQuery(cond.getAnyTypeCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getRelationshipTypeCond() != null
                         && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
 
-                    query.append(getQuery(nodeCond.getRelationshipTypeCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getRelationshipCond() != null
+                    query.append(getQuery(cond.getRelationshipTypeCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getRelationshipCond() != null
                         && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
 
-                    query.append(getQuery(nodeCond.getRelationshipCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getMembershipCond() != null
+                    query.append(getQuery(cond.getRelationshipCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getMembershipCond() != null
                         && (AnyTypeKind.USER == svs.anyTypeKind() || AnyTypeKind.ANY_OBJECT == svs.anyTypeKind())) {
 
-                    query.append(getQuery(nodeCond.getMembershipCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getAssignableCond() != null) {
-                    query.append(getQuery(nodeCond.getAssignableCond(), parameters, svs));
-                } else if (nodeCond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind()) {
-                    query.append(getQuery(nodeCond.getRoleCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getMemberCond() != null && AnyTypeKind.GROUP == svs.anyTypeKind()) {
-                    query.append(getQuery(nodeCond.getMemberCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getResourceCond() != null) {
-                    query.append(getQuery(nodeCond.getResourceCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getAttributeCond() != null) {
-                    query.append(getQuery(nodeCond.getAttributeCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
-                } else if (nodeCond.getAnyCond() != null) {
-                    query.append(getQuery(nodeCond.getAnyCond(),
-                            nodeCond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                    query.append(getQuery(cond.getMembershipCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getAssignableCond() != null) {
+                    query.append(getQuery(cond.getAssignableCond(), parameters, svs));
+                } else if (cond.getRoleCond() != null && AnyTypeKind.USER == svs.anyTypeKind()) {
+                    query.append(getQuery(cond.getRoleCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getMemberCond() != null && AnyTypeKind.GROUP == svs.anyTypeKind()) {
+                    query.append(getQuery(cond.getMemberCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getResourceCond() != null) {
+                    query.append(getQuery(cond.getResourceCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getAttributeCond() != null) {
+                    query.append(getQuery(cond.getAttributeCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
+                } else if (cond.getAnyCond() != null) {
+                    query.append(getQuery(cond.getAnyCond(),
+                            cond.getType() == SearchCond.Type.NOT_LEAF, parameters, svs));
                 }
                 break;
 
             case AND:
-                String andSubQuery = getQuery(nodeCond.getLeftNodeCond(), parameters, svs).toString();
+                String andSubQuery = getQuery(cond.getLeftSearchCond(), parameters, svs).toString();
                 // Add extra parentheses
                 andSubQuery = andSubQuery.replaceFirst("WHERE ", "WHERE (");
                 query.append(andSubQuery).
                         append(" AND any_id IN ( ").
-                        append(getQuery(nodeCond.getRightNodeCond(), parameters, svs)).
+                        append(getQuery(cond.getRightSearchCond(), parameters, svs)).
                         append("))");
                 break;
 
             case OR:
-                String orSubQuery = getQuery(nodeCond.getLeftNodeCond(), parameters, svs).toString();
+                String orSubQuery = getQuery(cond.getLeftSearchCond(), parameters, svs).toString();
                 // Add extra parentheses
                 orSubQuery = orSubQuery.replaceFirst("WHERE ", "WHERE (");
                 query.append(orSubQuery).
                         append(" OR any_id IN ( ").
-                        append(getQuery(nodeCond.getRightNodeCond(), parameters, svs)).
+                        append(getQuery(cond.getRightSearchCond(), parameters, svs)).
                         append("))");
                 break;
 
@@ -585,7 +584,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         }
 
         StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
-                append(svs.field().name).append(" WHERE ");
+                append(svs.field().name).append(" WHERE (");
 
         if (not) {
             query.append("any_id NOT IN (");
@@ -596,7 +595,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         query.append("SELECT DISTINCT any_id FROM ").
                 append(svs.membership().name).append(" WHERE ").
                 append("group_id=?").append(setParameter(parameters, groupKey)).
-                append(')');
+                append(") ");
 
         if (not) {
             query.append("AND any_id NOT IN (");
@@ -607,7 +606,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         query.append("SELECT DISTINCT any_id FROM ").
                 append(svs.dyngroupmembership().name).append(" WHERE ").
                 append("group_id=?").append(setParameter(parameters, groupKey)).
-                append(')');
+                append("))");
 
         return query.toString();
     }
@@ -616,7 +615,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
             final SearchSupport svs) {
 
         StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
-                append(svs.field().name).append(" WHERE ");
+                append(svs.field().name).append(" WHERE (");
 
         if (not) {
             query.append("any_id NOT IN (");
@@ -627,7 +626,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         query.append("SELECT DISTINCT any_id FROM ").
                 append(svs.role().name).append(" WHERE ").
                 append("role_id=?").append(setParameter(parameters, cond.getRoleKey())).
-                append(')');
+                append(") ");
 
         if (not) {
             query.append("AND any_id NOT IN (");
@@ -638,7 +637,7 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         query.append("SELECT DISTINCT any_id FROM ").
                 append(svs.dynrolemembership().name).append(" WHERE ").
                 append("role_id=?").append(setParameter(parameters, cond.getRoleKey())).
-                append(')');
+                append("))");
 
         return query.toString();
     }
@@ -723,20 +722,20 @@ public class JPAAnySearchDAO extends AbstractDAO<Any<?>> implements AnySearchDAO
         }
 
         query.append("SELECT DISTINCT group_id AS any_id FROM ").
-                append(new SearchSupport(AnyTypeKind.USER).membership().name).append(" WHERE ").
+                append(new SearchSupport(AnyTypeKind.USER).membership().name).append(" WHERE (").
                 append("any_id=?").append(setParameter(parameters, memberKey)).
-                append(')');
+                append(") ");
 
         if (not) {
-            query.append(" AND any_id NOT IN (");
+            query.append("AND any_id NOT IN (");
         } else {
-            query.append(" OR any_id IN (");
+            query.append("OR any_id IN (");
         }
 
         query.append("SELECT DISTINCT group_id AS any_id FROM ").
                 append(new SearchSupport(AnyTypeKind.ANY_OBJECT).membership().name).append(" WHERE ").
                 append("any_id=?").append(setParameter(parameters, memberKey)).
-                append(')');
+                append("))");
 
         return query.toString();
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1d294d6/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
index 1e59280..429dfb5 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/AnySearchTest.java
@@ -35,6 +35,8 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 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.MembershipCond;
@@ -49,6 +51,8 @@ import org.apache.syncope.core.persistence.api.dao.search.MemberCond;
 import org.apache.syncope.core.persistence.api.dao.search.RelationshipCond;
 import org.apache.syncope.core.persistence.api.dao.search.RelationshipTypeCond;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -72,6 +76,12 @@ public class AnySearchTest extends AbstractTest {
     @Autowired
     private AnySearchDAO searchDAO;
 
+    @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @Autowired
+    private RealmDAO realmDAO;
+
     @Test
     public void anyObjectMatch() {
         AnyObject anyObject = anyObjectDAO.find("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
@@ -474,20 +484,20 @@ public class AnySearchTest extends AbstractTest {
                 SearchCond.getLeafCond(relationshipTypeCond), SearchCond.getLeafCond(tcond));
         assertTrue(searchCondition.isValid());
 
-        List<Any<?>> matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
+        List<AnyObject> matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
         assertNotNull(matching);
         assertEquals(2, matching.size());
-        assertTrue(IterableUtils.matchesAny(matching, new Predicate<Any<?>>() {
+        assertTrue(IterableUtils.matchesAny(matching, new Predicate<AnyObject>() {
 
             @Override
-            public boolean evaluate(final Any<?> any) {
+            public boolean evaluate(final AnyObject any) {
                 return "fc6dbc3a-6c07-4965-8781-921e7401a4a5".equals(any.getKey());
             }
         }));
-        assertTrue(IterableUtils.matchesAny(matching, new Predicate<Any<?>>() {
+        assertTrue(IterableUtils.matchesAny(matching, new Predicate<AnyObject>() {
 
             @Override
-            public boolean evaluate(final Any<?> any) {
+            public boolean evaluate(final AnyObject any) {
                 return "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(any.getKey());
             }
         }));
@@ -696,4 +706,53 @@ public class AnySearchTest extends AbstractTest {
         assertNotNull(users);
         assertEquals(1, users.size());
     }
+
+    @Test
+    public void issueSYNCOPE980() {
+        AnyType service = entityFactory.newEntity(AnyType.class);
+        service.setKey("SERVICE");
+        service.setKind(AnyTypeKind.ANY_OBJECT);
+        service = anyTypeDAO.save(service);
+
+        Group citizen = groupDAO.findByName("citizen");
+        assertNotNull(citizen);
+
+        AnyObject anyObject = entityFactory.newEntity(AnyObject.class);
+        anyObject.setName("one");
+        anyObject.setType(service);
+        anyObject.setRealm(realmDAO.findByFullPath(SyncopeConstants.ROOT_REALM));
+
+        AMembership membership = entityFactory.newEntity(AMembership.class);
+        membership.setRightEnd(citizen);
+        membership.setLeftEnd(anyObject);
+
+        anyObject.add(membership);
+        anyObjectDAO.save(anyObject);
+
+        anyObject = anyObjectDAO.find("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
+        membership = entityFactory.newEntity(AMembership.class);
+        membership.setRightEnd(citizen);
+        membership.setLeftEnd(anyObject);
+        anyObject.add(membership);
+        anyObjectDAO.save(anyObject);
+
+        anyObjectDAO.flush();
+
+        MembershipCond groupCond = new MembershipCond();
+        groupCond.setGroup("citizen");
+
+        SearchCond searchCondition = SearchCond.getLeafCond(groupCond);
+
+        List<AnyObject> matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
+        assertEquals(2, matching.size());
+
+        AnyTypeCond anyTypeCond = new AnyTypeCond();
+        anyTypeCond.setAnyTypeKey(service.getKey());
+
+        searchCondition = SearchCond.getAndCond(
+                SearchCond.getLeafCond(groupCond), SearchCond.getLeafCond(anyTypeCond));
+
+        matching = searchDAO.search(searchCondition, AnyTypeKind.ANY_OBJECT);
+        assertEquals(1, matching.size());
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/f1d294d6/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
index b7f6558..c652cde 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SearchITCase.java
@@ -30,11 +30,16 @@ import org.apache.commons.collections4.IterableUtils;
 import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.patch.AnyObjectPatch;
+import org.apache.syncope.common.lib.patch.MembershipPatch;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.to.GroupTO;
+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.AnyTypeKind;
 import org.apache.syncope.common.rest.api.beans.AnyQuery;
 import org.apache.syncope.common.rest.api.service.RoleService;
 import org.apache.syncope.fit.AbstractITCase;
@@ -478,4 +483,42 @@ public class SearchITCase extends AbstractITCase {
             assertTrue(user.getUsername().startsWith("bellini"));
         }
     }
+
+    @Test
+    public void issueSYNCOPE980() {
+        AnyTypeTO service = new AnyTypeTO();
+        service.setKey("SERVICE");
+        service.setKind(AnyTypeKind.ANY_OBJECT);
+        Response response = anyTypeService.create(service);
+        assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatusInfo().getStatusCode());
+
+        String serviceKey = null;
+        try {
+            AnyObjectTO anyObjectTO = new AnyObjectTO();
+            anyObjectTO.setName("one");
+            anyObjectTO.setRealm(SyncopeConstants.ROOT_REALM);
+            anyObjectTO.setType(service.getKey());
+            anyObjectTO.getMemberships().add(
+                    new MembershipTO.Builder().group("29f96485-729e-4d31-88a1-6fc60e4677f3").build());
+            serviceKey = createAnyObject(anyObjectTO).getEntity().getKey();
+
+            AnyObjectPatch anyObjectPatch = new AnyObjectPatch();
+            anyObjectPatch.setKey("fc6dbc3a-6c07-4965-8781-921e7401a4a5");
+            anyObjectPatch.getMemberships().add(
+                    new MembershipPatch.Builder().group("29f96485-729e-4d31-88a1-6fc60e4677f3").build());
+            updateAnyObject(anyObjectPatch);
+
+            PagedResult<AnyObjectTO> matching = anyObjectService.search(new AnyQuery.Builder().fiql(
+                    SyncopeClient.getAnyObjectSearchConditionBuilder(service.getKey()).
+                            inGroups("29f96485-729e-4d31-88a1-6fc60e4677f3").
+                            query()).build());
+            assertEquals(1, matching.getSize());
+            assertEquals(serviceKey, matching.getResult().get(0).getKey());
+        } finally {
+            if (serviceKey != null) {
+                anyObjectService.delete(serviceKey);
+            }
+            anyTypeService.delete(service.getKey());
+        }
+    }
 }