[SYNCOPE-661] No more overloaded list / search REST methods + helpers provided 
for Java client invocation


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

Branch: refs/heads/master
Commit: bc2afa9a4cc2b9d0935c39d894f791f71bb1ec31
Parents: 39f8a06
Author: Francesco Chicchiriccò <ilgro...@apache.org>
Authored: Thu Apr 23 10:02:45 2015 +0200
Committer: Francesco Chicchiriccò <ilgro...@apache.org>
Committed: Thu Apr 23 17:06:17 2015 +0200

----------------------------------------------------------------------
 .../client/cli/commands/ReportCommand.java      |   3 +-
 .../console/rest/AbstractSubjectRestClient.java |   7 +-
 .../client/console/rest/GroupRestClient.java    |  22 +-
 .../client/console/rest/ReportRestClient.java   |  13 +-
 .../client/console/rest/TaskRestClient.java     |   9 +-
 .../client/console/rest/UserRestClient.java     |  20 +-
 .../syncope/client/lib/SyncopeClient.java       |  84 +++-
 .../client/lib/builders/ListQueryBuilder.java   |  48 ++
 .../lib/builders/SubjectListQueryBuilder.java   |  61 +++
 .../lib/builders/SubjectSearchQueryBuilder.java |  64 +++
 .../syncope/common/lib/to/PagedResult.java      |   2 +-
 .../syncope/common/rest/api/Preference.java     |   2 +-
 .../common/rest/api/beans/ListQuery.java        |  86 ++++
 .../common/rest/api/beans/SubjectListQuery.java |  41 ++
 .../rest/api/beans/SubjectSearchQuery.java      |  39 ++
 .../common/rest/api/service/GroupService.java   | 126 +----
 .../common/rest/api/service/JAXRSService.java   |   8 -
 .../common/rest/api/service/ReportService.java  |  49 +-
 .../common/rest/api/service/TaskService.java    |  57 +--
 .../common/rest/api/service/UserService.java    | 124 +----
 .../jpa/entity/AttributableSearchTest.java      | 471 -------------------
 .../jpa/entity/SubjectSearchTest.java           | 471 +++++++++++++++++++
 .../relationship/AttributableSearchTest.java    |  72 ---
 .../jpa/relationship/SubjectSearchTest.java     |  72 +++
 .../rest/cxf/QueryResourceInfoComparator.java   | 114 -----
 .../core/rest/cxf/service/GroupServiceImpl.java |  72 +--
 .../rest/cxf/service/ReportServiceImpl.java     |  31 +-
 .../core/rest/cxf/service/TaskServiceImpl.java  |  36 +-
 .../core/rest/cxf/service/UserServiceImpl.java  |  72 +--
 .../src/main/resources/restCXFContext.xml       |   3 -
 .../fit/core/reference/AbstractTaskITCase.java  |   4 +-
 .../core/reference/AuthenticationITCase.java    |  10 +-
 .../syncope/fit/core/reference/GroupITCase.java |  10 +-
 .../core/reference/PropagationTaskITCase.java   |  39 +-
 .../fit/core/reference/PushTaskITCase.java      |   3 +-
 .../fit/core/reference/ReportITCase.java        |   3 +-
 .../fit/core/reference/SchedTaskITCase.java     |   6 +-
 .../fit/core/reference/SearchITCase.java        |  86 ++--
 .../fit/core/reference/SyncTaskITCase.java      |  44 +-
 .../syncope/fit/core/reference/UserITCase.java  |  53 ++-
 pom.xml                                         |   2 +-
 41 files changed, 1252 insertions(+), 1287 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
----------------------------------------------------------------------
diff --git 
a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
 
b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
index 17f0e14..c2ed1fa 100644
--- 
a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
+++ 
b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
@@ -28,6 +28,7 @@ import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.TransformerException;
 import org.apache.syncope.client.cli.SyncopeServices;
 import org.apache.syncope.client.cli.util.XmlUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ReportExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
@@ -97,7 +98,7 @@ public class ReportCommand extends AbstractCommand {
         } else if (list) {
             LOG.debug("- report list command");
             try {
-                for (final ReportTO reportTO : 
reportService.list().getResult()) {
+                for (ReportTO reportTO : 
reportService.list(SyncopeClient.getListQueryBuilder().build()).getResult()) {
                     System.out.println(reportTO);
                 }
             } catch (final SyncopeClientException ex) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/console/src/main/java/org/apache/syncope/client/console/rest/AbstractSubjectRestClient.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/AbstractSubjectRestClient.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/AbstractSubjectRestClient.java
index 4b64b30..8b11b35 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/AbstractSubjectRestClient.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/AbstractSubjectRestClient.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.rest;
 
 import java.util.List;
 import org.apache.syncope.common.lib.to.AbstractAttributableTO;
+import org.apache.syncope.common.lib.to.AbstractSubjectTO;
 import org.apache.syncope.common.lib.to.BulkAction;
 import org.apache.syncope.common.lib.to.BulkActionResult;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
@@ -36,12 +37,12 @@ public abstract class AbstractSubjectRestClient extends 
BaseRestClient {
 
     public abstract int searchCount(String realm, String fiql);
 
-    public abstract List<? extends AbstractAttributableTO> search(
-            String realm, String fiql,            int page, int size, final 
SortParam<String> sort);
+    public abstract List<? extends AbstractSubjectTO> search(
+            String realm, String fiql, int page, int size, final 
SortParam<String> sort);
 
     public abstract ConnObjectTO getConnectorObject(String resourceName, Long 
key);
 
-    public abstract AbstractAttributableTO delete(String etag, Long key);
+    public abstract AbstractSubjectTO delete(String etag, Long key);
 
     public abstract BulkActionResult bulkAction(BulkAction action);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
index 89d016c..64138bb 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/GroupRestClient.java
@@ -18,12 +18,12 @@
  */
 package org.apache.syncope.client.console.rest;
 
-import java.util.Collections;
 import java.util.List;
 
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.console.commons.status.StatusBean;
 import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.mod.GroupMod;
 import org.apache.syncope.common.lib.to.BulkAction;
 import org.apache.syncope.common.lib.to.BulkActionResult;
@@ -49,22 +49,24 @@ public class GroupRestClient extends 
AbstractSubjectRestClient {
 
     @Override
     public int count(final String realm) {
-        return 
getService(GroupService.class).list(Collections.singletonList(realm), 1, 
1).getTotalCount();
-    }
-
-    public List<GroupTO> list(final String realm) {
-        return 
getService(GroupService.class).list(Collections.singletonList(realm), 1, 
1000).getResult();
+        return getService(GroupService.class).
+                
list(SyncopeClient.getSubjectListQueryBuilder().realm(realm).page(1).size(1).build()).
+                getTotalCount();
     }
 
     @Override
     public List<GroupTO> list(final String realm, final int page, final int 
size, final SortParam<String> sort) {
         return getService(GroupService.class).
-                list(Collections.singletonList(realm), page, size, 
toOrderBy(sort)).getResult();
+                
list(SyncopeClient.getSubjectListQueryBuilder().realm(realm).page(page).size(size).
+                        orderBy(toOrderBy(sort)).build()).
+                getResult();
     }
 
     @Override
     public int searchCount(final String realm, final String fiql) {
-        return 
getService(GroupService.class).search(Collections.singletonList(realm), fiql, 
1, 1).getTotalCount();
+        return getService(GroupService.class).
+                
search(SyncopeClient.getSubjectSearchQueryBuilder().realm(realm).fiql(fiql).page(1).size(1).build()).
+                getTotalCount();
     }
 
     @Override
@@ -72,7 +74,9 @@ public class GroupRestClient extends 
AbstractSubjectRestClient {
             final String realm, final String fiql, final int page, final int 
size, final SortParam<String> sort) {
 
         return getService(GroupService.class).
-                search(Collections.singletonList(realm), fiql, page, size, 
toOrderBy(sort)).getResult();
+                
search(SyncopeClient.getSubjectSearchQueryBuilder().realm(realm).fiql(fiql).page(page).size(size).
+                        orderBy(toOrderBy(sort)).build()).
+                getResult();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
index ffce9c7..617a2c7 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
@@ -21,6 +21,7 @@ package org.apache.syncope.client.console.rest;
 import java.util.ArrayList;
 import java.util.List;
 import javax.ws.rs.core.Response;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
@@ -54,15 +55,21 @@ public class ReportRestClient extends BaseRestClient 
implements ExecutionRestCli
     }
 
     public List<ReportTO> list() {
-        return getService(ReportService.class).list().getResult();
+        return getService(ReportService.class).
+                list(SyncopeClient.getListQueryBuilder().build()).
+                getResult();
     }
 
     public List<ReportTO> list(final int page, final int size, final 
SortParam<String> sort) {
-        return getService(ReportService.class).list(page, size, 
toOrderBy(sort)).getResult();
+        return getService(ReportService.class).
+                
list(SyncopeClient.getListQueryBuilder().page(page).size(size).orderBy(toOrderBy(sort)).build()).
+                getResult();
     }
 
     public int count() {
-        return getService(ReportService.class).list(1, 1).getTotalCount();
+        return getService(ReportService.class).
+                
list(SyncopeClient.getListQueryBuilder().page(1).size(1).build()).
+                getTotalCount();
     }
 
     public void create(final ReportTO reportTO) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index be4976e..cea466e 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@ -20,6 +20,7 @@ package org.apache.syncope.client.console.rest;
 
 import java.util.List;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.AbstractTaskTO;
 import org.apache.syncope.common.lib.to.BulkAction;
 import org.apache.syncope.common.lib.to.BulkActionResult;
@@ -60,14 +61,18 @@ public class TaskRestClient extends BaseRestClient 
implements ExecutionRestClien
      * @return number of stored tasks.
      */
     public int count(final String kind) {
-        return getService(TaskService.class).list(TaskType.fromString(kind), 
1, 1).getTotalCount();
+        return getService(TaskService.class).
+                list(TaskType.fromString(kind), 
SyncopeClient.getListQueryBuilder().page(1).size(1).build()).
+                getTotalCount();
     }
 
     @SuppressWarnings("unchecked")
     public <T extends AbstractTaskTO> List<T> list(final Class<T> reference,
             final int page, final int size, final SortParam<String> sort) {
 
-        return (List<T>) 
getService(TaskService.class).list(getTaskType(reference), page, size, 
toOrderBy(sort)).
+        return (List<T>) getService(TaskService.class).
+                list(getTaskType(reference), 
SyncopeClient.getListQueryBuilder().page(page).size(size).
+                        orderBy(toOrderBy(sort)).build()).
                 getResult();
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
----------------------------------------------------------------------
diff --git 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
index cb30536..a39df68 100644
--- 
a/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
+++ 
b/client/console/src/main/java/org/apache/syncope/client/console/rest/UserRestClient.java
@@ -18,11 +18,11 @@
  */
 package org.apache.syncope.client.console.rest;
 
-import java.util.Collections;
 import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.console.commons.status.StatusBean;
 import org.apache.syncope.client.console.commons.status.StatusUtils;
+import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
 import org.apache.syncope.common.lib.mod.StatusMod;
@@ -51,13 +51,17 @@ public class UserRestClient extends 
AbstractSubjectRestClient {
 
     @Override
     public int count(final String realm) {
-        return 
getService(UserService.class).list(Collections.singletonList(realm), 1, 
1).getTotalCount();
+        return getService(UserService.class).
+                
list(SyncopeClient.getSubjectListQueryBuilder().realm(realm).page(1).size(1).build()).
+                getTotalCount();
     }
 
     @Override
     public List<UserTO> list(final String realm, final int page, final int 
size, final SortParam<String> sort) {
         return getService(UserService.class).
-                list(Collections.singletonList(realm), page, size, 
toOrderBy(sort)).getResult();
+                
list(SyncopeClient.getSubjectListQueryBuilder().realm(realm).page(page).size(size).
+                        orderBy(toOrderBy(sort)).build()).
+                getResult();
     }
 
     public UserTO create(final UserTO userTO, final boolean storePassword) {
@@ -98,15 +102,19 @@ public class UserRestClient extends 
AbstractSubjectRestClient {
 
     @Override
     public int searchCount(final String realm, final String fiql) {
-        return 
getService(UserService.class).search(Collections.singletonList(realm), fiql, 1, 
1).getTotalCount();
+        return getService(UserService.class).
+                
search(SyncopeClient.getSubjectSearchQueryBuilder().realm(realm).fiql(fiql).page(1).size(1).build()).
+                getTotalCount();
     }
 
     @Override
     public List<UserTO> search(
             final String realm, final String fiql, final int page, final int 
size, final SortParam<String> sort) {
-        
+
         return getService(UserService.class).
-                search(Collections.singletonList(realm), fiql, page, size, 
toOrderBy(sort)).getResult();
+                
search(SyncopeClient.getSubjectSearchQueryBuilder().realm(realm).fiql(fiql).page(page).size(size).
+                        orderBy(toOrderBy(sort)).build()).
+                getResult();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
----------------------------------------------------------------------
diff --git 
a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java 
b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
index 9aa5990..1bfbb4f 100644
--- a/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
+++ b/client/lib/src/main/java/org/apache/syncope/client/lib/SyncopeClient.java
@@ -30,6 +30,9 @@ import javax.ws.rs.core.Response;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.syncope.client.lib.builders.ListQueryBuilder;
+import org.apache.syncope.client.lib.builders.SubjectListQueryBuilder;
+import org.apache.syncope.client.lib.builders.SubjectSearchQueryBuilder;
 import org.apache.syncope.common.lib.search.OrderByClauseBuilder;
 import org.apache.syncope.common.lib.search.GroupFiqlSearchConditionBuilder;
 import org.apache.syncope.common.lib.search.UserFiqlSearchConditionBuilder;
@@ -68,33 +71,64 @@ public class SyncopeClient {
     }
 
     /**
-     * Returns a new instance of <tt>UserFiqlSearchConditionBuilder</tt>, for 
assisted building of FIQL queries.
+     * Returns a new instance of {@link UserFiqlSearchConditionBuilder}, for 
assisted building of FIQL queries.
      *
-     * @return default instance of <tt>UserFiqlSearchConditionBuilder</tt>
+     * @return default instance of {@link UserFiqlSearchConditionBuilder}
      */
     public static UserFiqlSearchConditionBuilder 
getUserSearchConditionBuilder() {
         return new UserFiqlSearchConditionBuilder();
     }
 
     /**
-     * Returns a new instance of <tt>GroupFiqlSearchConditionBuilder</tt>, for 
assisted building of FIQL queries.
+     * Returns a new instance of {@link GroupFiqlSearchConditionBuilder}, for 
assisted building of FIQL queries.
      *
-     * @return default instance of <tt>GroupFiqlSearchConditionBuilder</tt>
+     * @return default instance of {@link GroupFiqlSearchConditionBuilder}
      */
     public static GroupFiqlSearchConditionBuilder 
getGroupSearchConditionBuilder() {
         return new GroupFiqlSearchConditionBuilder();
     }
 
     /**
-     * Returns a new instance of <tt>OrderByClauseBuilder</tt>, for assisted 
building of <tt>orderby</tt> clauses.
+     * Returns a new instance of {@link OrderByClauseBuilder}, for assisted 
building of {@link orderby} clauses.
      *
-     * @return default instance of <tt>OrderByClauseBuilder</tt>
+     * @return default instance of {@link OrderByClauseBuilder}
      */
     public static OrderByClauseBuilder getOrderByClauseBuilder() {
         return new OrderByClauseBuilder();
     }
 
     /**
+     * Returns a new instance of {@link ListQueryBuilder}, for assisted 
building of some service's {@code list()}
+     * arguments.
+     *
+     * @return default instance of {@link ListQueryBuilder}
+     */
+    public static ListQueryBuilder getListQueryBuilder() {
+        return new ListQueryBuilder();
+    }
+
+    /**
+     * Returns a new instance of {@link SubjectListQueryBuilder}, for assisted 
building of some service's {@code list()}
+     * arguments.
+     *
+     * @return default instance of {@link SubjectListQueryBuilder}
+     */
+    public static SubjectListQueryBuilder getSubjectListQueryBuilder() {
+        return new SubjectListQueryBuilder();
+    }
+
+    /**
+     * Returns a new instance of {@link SubjectSearchQueryBuilder}, for 
assisted building of some service's
+     * {@code search()}
+     * arguments.
+     *
+     * @return default instance of {@link SubjectSearchQueryBuilder}
+     */
+    public static SubjectSearchQueryBuilder getSubjectSearchQueryBuilder() {
+        return new SubjectSearchQueryBuilder();
+    }
+
+    /**
      * Creates an instance of the given service class, with configured content 
type and authentication.
      *
      * @param <T> any service class
@@ -162,37 +196,37 @@ public class SyncopeClient {
     }
 
     /**
-     * Sets the <tt>Prefer</tt> header on the give service instance.
+     * Sets the {@code Prefer} header on the give service instance.
      *
      * @param <T> any service class
      * @param service service class instance
-     * @param preference preference to be set via <tt>Prefer</tt> header
-     * @return given service instance, with <tt>Prefer</tt> header set
+     * @param preference preference to be set via {@code Prefer} header
+     * @return given service instance, with {@code Prefer} header set
      */
     public <T> T prefer(final T service, final Preference preference) {
         return header(service, RESTHeaders.PREFER, preference.toString());
     }
 
     /**
-     * Creates an instance of the given service class, with <tt>Prefer</tt> 
header set.
+     * Creates an instance of the given service class, with {@code Prefer} 
header set.
      *
      * @param <T> any service class
      * @param serviceClass service class reference
-     * @param preference preference to be set via <tt>Prefer</tt> header
-     * @return service instance of the given reference class, with 
<tt>Prefer</tt> header set
+     * @param preference preference to be set via {@code Prefer} header
+     * @return service instance of the given reference class, with {@code 
Prefer} header set
      */
     public <T> T prefer(final Class<T> serviceClass, final Preference 
preference) {
         return header(serviceClass, RESTHeaders.PREFER, preference.toString());
     }
 
     /**
-     * Sets the <tt>If-Match</tt> or <tt>If-None-Match</tt> header on the 
given service instance.
+     * Sets the {@code If-Match} or {@code If-None-Match} header on the given 
service instance.
      *
      * @param <T> any service class
      * @param service service class instance
      * @param etag ETag value
-     * @param ifNot if true then <tt>If-None-Match</tt> is set, 
<tt>If-Match</tt> otherwise
-     * @return given service instance, with <tt>If-Match</tt> or 
<tt>If-None-Match</tt> set
+     * @param ifNot if true then {@code If-None-Match} is set, {@code 
If-Match} otherwise
+     * @return given service instance, with {@code If-Match} or {@code 
If-None-Match} set
      */
     private <T> T match(final T service, final EntityTag etag, final boolean 
ifNot) {
         WebClient.client(service).match(etag, ifNot);
@@ -200,59 +234,59 @@ public class SyncopeClient {
     }
 
     /**
-     * Sets the <tt>If-Match</tt> header on the given service instance.
+     * Sets the {@code If-Match} header on the given service instance.
      *
      * @param <T> any service class
      * @param service service class instance
      * @param etag ETag value
-     * @return given service instance, with <tt>If-Match</tt> set
+     * @return given service instance, with {@code If-Match} set
      */
     public <T> T ifMatch(final T service, final EntityTag etag) {
         return match(service, etag, false);
     }
 
     /**
-     * Creates an instance of the given service class, with <tt>If-Match</tt> 
header set.
+     * Creates an instance of the given service class, with {@code If-Match} 
header set.
      *
      * @param <T> any service class
      * @param serviceClass service class reference
      * @param etag ETag value
-     * @return given service instance, with <tt>If-Match</tt> set
+     * @return given service instance, with {@code If-Match} set
      */
     public <T> T ifMatch(final Class<T> serviceClass, final EntityTag etag) {
         return match(getService(serviceClass), etag, false);
     }
 
     /**
-     * Sets the <tt>If-None-Match</tt> header on the given service instance.
+     * Sets the {@code If-None-Match} header on the given service instance.
      *
      * @param <T> any service class
      * @param service service class instance
      * @param etag ETag value
-     * @return given service instance, with <tt>If-None-Match</tt> set
+     * @return given service instance, with {@code If-None-Match} set
      */
     public <T> T ifNoneMatch(final T service, final EntityTag etag) {
         return match(service, etag, true);
     }
 
     /**
-     * Creates an instance of the given service class, with 
<tt>If-None-Match</tt> header set.
+     * Creates an instance of the given service class, with {@code 
If-None-Match} header set.
      *
      * @param <T> any service class
      * @param serviceClass service class reference
      * @param etag ETag value
-     * @return given service instance, with <tt>If-None-Match</tt> set
+     * @return given service instance, with {@code If-None-Match} set
      */
     public <T> T ifNoneMatch(final Class<T> serviceClass, final EntityTag 
etag) {
         return match(getService(serviceClass), etag, true);
     }
 
     /**
-     * Fetches <tt>ETag</tt> header value from latest service run (if 
available).
+     * Fetches {@code ETag} header value from latest service run (if 
available).
      *
      * @param <T> any service class
      * @param service service class instance
-     * @return <tt>ETag</tt> header value from latest service run (if 
available)
+     * @return {@code ETag} header value from latest service run (if available)
      */
     public <T> EntityTag getLatestEntityTag(final T service) {
         return WebClient.client(service).getResponse().getEntityTag();

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
 
b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
new file mode 100644
index 0000000..5d6202a
--- /dev/null
+++ 
b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/ListQueryBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib.builders;
+
+import org.apache.syncope.common.rest.api.beans.ListQuery;
+
+public class ListQueryBuilder {
+
+    private final ListQuery instance = new ListQuery();
+
+    public ListQueryBuilder page(final Integer page) {
+        instance.setPage(page);
+
+        return this;
+    }
+
+    public ListQueryBuilder size(final Integer size) {
+        instance.setSize(size);
+
+        return this;
+    }
+
+    public ListQueryBuilder orderBy(final String orderBy) {
+        instance.setOrderBy(orderBy);
+
+        return this;
+    }
+
+    public ListQuery build() {
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectListQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectListQueryBuilder.java
 
b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectListQueryBuilder.java
new file mode 100644
index 0000000..6aec945
--- /dev/null
+++ 
b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectListQueryBuilder.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib.builders;
+
+import java.util.ArrayList;
+import org.apache.syncope.common.rest.api.beans.ListQuery;
+import org.apache.syncope.common.rest.api.beans.SubjectListQuery;
+
+public class SubjectListQueryBuilder extends ListQueryBuilder {
+
+    private final SubjectListQuery instance = new SubjectListQuery();
+
+    @Override
+    public SubjectListQueryBuilder page(final Integer page) {
+        return SubjectListQueryBuilder.class.cast(super.page(page));
+    }
+
+    @Override
+    public SubjectListQueryBuilder size(final Integer size) {
+        return SubjectListQueryBuilder.class.cast(super.size(size));
+    }
+
+    @Override
+    public SubjectListQueryBuilder orderBy(final String orderBy) {
+        return SubjectListQueryBuilder.class.cast(super.orderBy(orderBy));
+    }
+
+    public SubjectListQueryBuilder realm(final String realm) {
+        if (instance.getRealms() == null) {
+            instance.setRealms(new ArrayList<String>());
+        }
+
+        return this;
+    }
+
+    @Override
+    public SubjectListQuery build() {
+        ListQuery lq = super.build();
+        instance.setPage(lq.getPage());
+        instance.setSize(lq.getSize());
+        instance.setOrderBy(lq.getOrderBy());
+
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectSearchQueryBuilder.java
----------------------------------------------------------------------
diff --git 
a/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectSearchQueryBuilder.java
 
b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectSearchQueryBuilder.java
new file mode 100644
index 0000000..b74860e
--- /dev/null
+++ 
b/client/lib/src/main/java/org/apache/syncope/client/lib/builders/SubjectSearchQueryBuilder.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.client.lib.builders;
+
+import org.apache.syncope.common.rest.api.beans.SubjectListQuery;
+import org.apache.syncope.common.rest.api.beans.SubjectSearchQuery;
+
+public class SubjectSearchQueryBuilder extends SubjectListQueryBuilder {
+
+    private final SubjectSearchQuery instance = new SubjectSearchQuery();
+
+    @Override
+    public SubjectSearchQueryBuilder realm(final String realm) {
+        return SubjectSearchQueryBuilder.class.cast(super.realm(realm));
+    }
+
+    @Override
+    public SubjectSearchQueryBuilder page(final Integer page) {
+        return SubjectSearchQueryBuilder.class.cast(super.page(page));
+    }
+
+    @Override
+    public SubjectSearchQueryBuilder size(final Integer size) {
+        return SubjectSearchQueryBuilder.class.cast(super.size(size));
+    }
+
+    @Override
+    public SubjectSearchQueryBuilder orderBy(final String orderBy) {
+        return SubjectSearchQueryBuilder.class.cast(super.orderBy(orderBy));
+    }
+
+    public SubjectSearchQueryBuilder fiql(final String fiql) {
+        instance.setFiql(fiql);
+
+        return this;
+    }
+
+    @Override
+    public SubjectSearchQuery build() {
+        SubjectListQuery slq = super.build();
+        instance.setRealms(slq.getRealms());
+        instance.setPage(slq.getPage());
+        instance.setSize(slq.getSize());
+        instance.setOrderBy(slq.getOrderBy());
+
+        return instance;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedResult.java
----------------------------------------------------------------------
diff --git 
a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedResult.java 
b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedResult.java
index f383ece..b17db6d 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedResult.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PagedResult.java
@@ -39,7 +39,7 @@ public class PagedResult<T extends AbstractBaseBean> extends 
AbstractBaseBean {
 
     private URI next;
 
-    private final List<T> result = new ArrayList<T>();
+    private final List<T> result = new ArrayList<>();
 
     private int page;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/Preference.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/Preference.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/Preference.java
index 5cda9cf..a448c03 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/Preference.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/Preference.java
@@ -30,7 +30,7 @@ public enum Preference {
     RETURN_CONTENT("return-content"),
     RETURN_NO_CONTENT("return-no-content");
 
-    private String literal;
+    private final String literal;
 
     private Preference(final String literal) {
         this.literal = literal;

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
new file mode 100644
index 0000000..1a85fe4
--- /dev/null
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/ListQuery.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.beans;
+
+import java.io.Serializable;
+import javax.validation.constraints.Min;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.QueryParam;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.rest.api.service.JAXRSService;
+
+public class ListQuery implements Serializable {
+
+    private static final long serialVersionUID = -371488230250055359L;
+
+    private Integer page;
+
+    private Integer size;
+
+    private String orderBy;
+
+    public Integer getPage() {
+        return page;
+    }
+
+    @Min(1)
+    @QueryParam(JAXRSService.PARAM_PAGE)
+    @DefaultValue("1")
+    public void setPage(final Integer page) {
+        this.page = page;
+    }
+
+    public Integer getSize() {
+        return size;
+    }
+
+    @Min(1)
+    @QueryParam(JAXRSService.PARAM_SIZE)
+    @DefaultValue("25")
+    public void setSize(final Integer size) {
+        this.size = size;
+    }
+
+    @QueryParam(JAXRSService.PARAM_ORDERBY)
+    public String getOrderBy() {
+        return orderBy;
+    }
+
+    public void setOrderBy(final String orderBy) {
+        this.orderBy = orderBy;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public String toString() {
+        return ReflectionToStringBuilder.toString(this, 
ToStringStyle.MULTI_LINE_STYLE);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectListQuery.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectListQuery.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectListQuery.java
new file mode 100644
index 0000000..47ff005
--- /dev/null
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectListQuery.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.beans;
+
+import java.util.List;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.MatrixParam;
+import org.apache.syncope.common.lib.SyncopeConstants;
+
+public class SubjectListQuery extends ListQuery {
+
+    private static final long serialVersionUID = -5197167078435619636L;
+
+    private List<String> realms;
+
+    public List<String> getRealms() {
+        return realms;
+    }
+
+    @DefaultValue(SyncopeConstants.ROOT_REALM)
+    @MatrixParam("realm")
+    public void setRealms(final List<String> realms) {
+        this.realms = realms;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectSearchQuery.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectSearchQuery.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectSearchQuery.java
new file mode 100644
index 0000000..d7f7344
--- /dev/null
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SubjectSearchQuery.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.common.rest.api.beans;
+
+import javax.ws.rs.QueryParam;
+import org.apache.syncope.common.rest.api.service.JAXRSService;
+
+public class SubjectSearchQuery extends SubjectListQuery {
+
+    private static final long serialVersionUID = -6736562952418964707L;
+
+    private String fiql;
+
+    public String getFiql() {
+        return fiql;
+    }
+
+    @QueryParam(JAXRSService.PARAM_FIQL)
+    public void setFiql(final String fiql) {
+        this.fiql = fiql;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
index 337bebc..b612a6e 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/GroupService.java
@@ -19,23 +19,20 @@
 package org.apache.syncope.common.rest.api.service;
 
 import java.util.List;
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.cxf.jaxrs.model.wadl.Description;
 import org.apache.cxf.jaxrs.model.wadl.Descriptions;
 import org.apache.cxf.jaxrs.model.wadl.DocTarget;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.mod.GroupMod;
 import org.apache.syncope.common.lib.to.BulkAction;
 import org.apache.syncope.common.lib.to.BulkActionResult;
@@ -44,6 +41,8 @@ import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
 import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
 import org.apache.syncope.common.lib.wrap.ResourceName;
+import org.apache.syncope.common.rest.api.beans.SubjectListQuery;
+import org.apache.syncope.common.rest.api.beans.SubjectSearchQuery;
 
 /**
  * REST operations for groups.
@@ -79,128 +78,25 @@ public interface GroupService extends JAXRSService {
     List<GroupTO> own();
 
     /**
-     * Returns a paged list of existing groups.
+     * Returns a paged list of existing groups matching the given query.
      *
-     * @param realms realms under which groups are defined
-     * @return paged list of all existing groups
+     * @param listQuery query conditions
+     * @return paged list of existing groups matching the given query
      */
     @GET
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms);
+    PagedResult<GroupTO> list(@BeanParam SubjectListQuery listQuery);
 
     /**
-     * Returns a paged list of existing groups.
+     * Returns a paged list of groups matching the given query.
      *
-     * @param realms realms under which groups are defined
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of all existing groups
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of existing groups matching page/size conditions.
-     *
-     * @param realms realms under which groups are defined
-     * @param page result page number
-     * @param size number of entries per page
-     * @return paged list of existing groups matching page/size conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size);
-
-    /**
-     * Returns a paged list of existing groups matching page/size conditions.
-     *
-     * @param realms realms under which groups are defined
-     * @param page result page number
-     * @param size number of entries per page
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of existing groups matching page/size conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of groups matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which groups are defined
-     * @param fiql FIQL search expression
-     * @return paged list of groups matching the provided FIQL search condition
-     */
-    @GET
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @QueryParam(PARAM_FIQL) String fiql);
-
-    /**
-     * Returns a paged list of groups matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which groups are defined
-     * @param fiql FIQL search expression
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of groups matching the provided FIQL search condition
-     */
-    @GET
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @QueryParam(PARAM_FIQL) String fiql,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of groups matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which groups are defined
-     * @param fiql FIQL search expression
-     * @param page result page number
-     * @param size number of entries per page
-     * @return paged list of groups matching the provided FIQL search condition
-     */
-    @GET
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @QueryParam(PARAM_FIQL) String fiql,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size);
-
-    /**
-     * Returns a paged list of groups matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which groups are defined
-     * @param fiql FIQL search expression
-     * @param page result page number
-     * @param size number of entries per page
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of groups matching the provided FIQL search condition
+     * @param searchQuery query conditions
+     * @return paged list of groups matching the given query
      */
     @GET
     @Path("search")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<GroupTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @QueryParam(PARAM_FIQL) String fiql,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
+    PagedResult<GroupTO> search(@BeanParam SubjectSearchQuery searchQuery);
 
     /**
      * Creates a new group.

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
index cd5c473..bfd166a 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/JAXRSService.java
@@ -24,16 +24,8 @@ public interface JAXRSService {
 
     String PARAM_PAGE = "page";
 
-    String DEFAULT_PARAM_PAGE = "1";
-
-    int DEFAULT_PARAM_PAGE_VALUE = Integer.valueOf(DEFAULT_PARAM_PAGE);
-
     String PARAM_SIZE = "size";
 
-    String DEFAULT_PARAM_SIZE = "25";
-
-    int DEFAULT_PARAM_SIZE_VALUE = Integer.valueOf(DEFAULT_PARAM_SIZE);
-
     String PARAM_ORDERBY = "orderby";
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
index 1e9f943..0037d0a 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReportService.java
@@ -19,11 +19,10 @@
 package org.apache.syncope.common.rest.api.service;
 
 import java.util.List;
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
-import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.PUT;
@@ -41,6 +40,7 @@ import org.apache.syncope.common.lib.to.ReportExecTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
 import org.apache.syncope.common.lib.wrap.ReportletConfClass;
+import org.apache.syncope.common.rest.api.beans.ListQuery;
 
 /**
  * REST operations for reports.
@@ -81,51 +81,14 @@ public interface ReportService extends JAXRSService {
     ReportExecTO readExecution(@NotNull @PathParam("executionKey") Long 
executionKey);
 
     /**
-     * Returns a paged list of all existing reports.
+     * Returns a paged list of all existing reports matching the given query;
      *
-     * @return paged list of all existing reports
+     * @param listQuery query conditions
+     * @return paged list of existing reports matching the given query
      */
     @GET
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<ReportTO> list();
-
-    /**
-     * Returns a paged list of all existing reports.
-     *
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of all existing reports
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<ReportTO> list(@QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of all existing reports matching page/size 
conditions.
-     *
-     * @param page selected page in relation to size
-     * @param size number of entries per page
-     * @return paged list of existing reports matching page/size conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<ReportTO> list(
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size);
-
-    /**
-     * Returns a paged list of all existing reports matching page/size 
conditions.
-     *
-     * @param page selected page in relation to size
-     * @param size number of entries per page
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of existing reports matching page/size conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<ReportTO> list(
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
+    PagedResult<ReportTO> list(@BeanParam ListQuery listQuery);
 
     /**
      * Creates a new report.

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
index 24c9b0e..8240a23 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/TaskService.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.common.rest.api.service;
 
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -44,6 +44,7 @@ import org.apache.syncope.common.lib.to.ReportExecTO;
 import org.apache.syncope.common.lib.to.SchedTaskTO;
 import org.apache.syncope.common.lib.to.TaskExecTO;
 import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.rest.api.beans.ListQuery;
 
 /**
  * REST operations for tasks.
@@ -75,60 +76,18 @@ public interface TaskService extends JAXRSService {
     TaskExecTO readExecution(@NotNull @PathParam("executionKey") Long 
executionKey);
 
     /**
-     * Returns a list of tasks with matching type.
+     * Returns a paged list of existing tasks matching type and the given 
query.
      *
      * @param taskType type of tasks to be listed
+     * @param listQuery query conditions
      * @param <T> type of taskTO
-     * @return list of tasks with matching type
+     * @return paged list of existing tasks matching type and the given query
      */
     @GET
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    <T extends AbstractTaskTO> PagedResult<T> list(@NotNull 
@MatrixParam("type") TaskType taskType);
-
-    /**
-     * Returns a list of tasks with matching type.
-     *
-     * @param taskType type of tasks to be listed
-     * @param orderBy list of ordering clauses, separated by comma
-     * @param <T> type of taskTO
-     * @return list of tasks with matching type
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    <T extends AbstractTaskTO> PagedResult<T> list(@NotNull 
@MatrixParam("type") TaskType taskType,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of existing tasks matching type and page/size 
conditions.
-     *
-     * @param taskType type of tasks to be listed
-     * @param page page number of tasks in relation to page size
-     * @param size number of tasks listed per page
-     * @param orderBy list of ordering clauses, separated by comma
-     * @param <T> type of taskTO
-     * @return paged list of existing tasks matching type and page/size 
conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    <T extends AbstractTaskTO> PagedResult<T> list(@NotNull 
@MatrixParam("type") TaskType taskType,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of existing tasks matching type and page/size 
conditions.
-     *
-     * @param taskType type of tasks to be listed
-     * @param page page number of tasks in relation to page size
-     * @param size number of tasks listed per page
-     * @param <T> type of taskTO
-     * @return paged list of existing tasks matching type and page/size 
conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    <T extends AbstractTaskTO> PagedResult<T> list(@MatrixParam("type") 
TaskType taskType,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size);
+    <T extends AbstractTaskTO> PagedResult<T> list(
+            @NotNull @MatrixParam("type") TaskType taskType,
+            @BeanParam ListQuery listQuery);
 
     /**
      * Creates a new task.

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
index 76595d3..8c13935 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.common.rest.api.service;
 
 import java.util.List;
-import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
+import javax.ws.rs.BeanParam;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
 import javax.ws.rs.DefaultValue;
@@ -36,7 +36,6 @@ import javax.ws.rs.core.Response;
 import org.apache.cxf.jaxrs.model.wadl.Description;
 import org.apache.cxf.jaxrs.model.wadl.Descriptions;
 import org.apache.cxf.jaxrs.model.wadl.DocTarget;
-import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.mod.ResourceAssociationMod;
 import org.apache.syncope.common.lib.mod.StatusMod;
 import org.apache.syncope.common.lib.mod.UserMod;
@@ -47,6 +46,8 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.ResourceAssociationActionType;
 import org.apache.syncope.common.lib.types.ResourceDeassociationActionType;
 import org.apache.syncope.common.lib.wrap.ResourceName;
+import org.apache.syncope.common.rest.api.beans.SubjectListQuery;
+import org.apache.syncope.common.rest.api.beans.SubjectSearchQuery;
 
 /**
  * REST operations for users.
@@ -94,128 +95,25 @@ public interface UserService extends JAXRSService {
     UserTO read(@NotNull @PathParam("userKey") Long userKey);
 
     /**
-     * Returns a paged list of existing users.
+     * Returns a paged list of existing users matching the given query.
      *
-     * @param realms realms under which users are defined
-     * @return paged list of all existing users
+     * @param listQuery query conditions
+     * @return paged list of existing users matching the given query
      */
     @GET
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms);
+    PagedResult<UserTO> list(@BeanParam SubjectListQuery listQuery);
 
     /**
-     * Returns a paged list of existing users.
+     * Returns a paged list of users matching the given query.
      *
-     * @param realms realms under which users are defined
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of all existing users
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of existing users matching page/size conditions.
-     *
-     * @param realms realms under which users are defined
-     * @param page result page number
-     * @param size number of entries per page
-     * @return paged list of existing users matching page/size conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size);
-
-    /**
-     * Returns a paged list of existing users matching page/size conditions.
-     *
-     * @param realms realms under which users are defined
-     * @param page result page number
-     * @param size number of entries per page
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of existing users matching page/size conditions
-     */
-    @GET
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> list(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of users matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which users are defined
-     * @param fiql FIQL search expression
-     * @return paged list of users matching the provided FIQL search condition
-     */
-    @GET
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @QueryParam(PARAM_FIQL) String fiql);
-
-    /**
-     * Returns a paged list of users matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which users are defined
-     * @param fiql FIQL search expression
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of users matching the provided FIQL search condition
-     */
-    @GET
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @NotNull @QueryParam(PARAM_FIQL) String fiql,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
-
-    /**
-     * Returns a paged list of users matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which users are defined
-     * @param fiql FIQL search expression
-     * @param page result page number
-     * @param size number of entries per page
-     * @return paged list of users matching the provided FIQL search condition
-     */
-    @GET
-    @Path("search")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @QueryParam(PARAM_FIQL) String fiql,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size);
-
-    /**
-     * Returns a paged list of users matching the provided FIQL search 
condition.
-     *
-     * @param realms realms under which users are defined
-     * @param fiql FIQL search expression
-     * @param page result page number
-     * @param size number of entries per page
-     * @param orderBy list of ordering clauses, separated by comma
-     * @return paged list of users matching the provided FIQL search condition
+     * @param searchQuery query conditions
+     * @return paged list of users matching the given query
      */
     @GET
     @Path("search")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    PagedResult<UserTO> search(
-            @DefaultValue(SyncopeConstants.ROOT_REALM) @QueryParam("realm") 
List<String> realms,
-            @QueryParam(PARAM_FIQL) String fiql,
-            @NotNull @Min(1) @QueryParam(PARAM_PAGE) 
@DefaultValue(DEFAULT_PARAM_PAGE) Integer page,
-            @NotNull @Min(1) @QueryParam(PARAM_SIZE) 
@DefaultValue(DEFAULT_PARAM_SIZE) Integer size,
-            @QueryParam(PARAM_ORDERBY) String orderBy);
+    PagedResult<UserTO> search(@BeanParam SubjectSearchQuery searchQuery);
 
     /**
      * Creates a new user.

http://git-wip-us.apache.org/repos/asf/syncope/blob/bc2afa9a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AttributableSearchTest.java
----------------------------------------------------------------------
diff --git 
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AttributableSearchTest.java
 
b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AttributableSearchTest.java
deleted file mode 100644
index ea93dae..0000000
--- 
a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/AttributableSearchTest.java
+++ /dev/null
@@ -1,471 +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.entity;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-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.SubjectType;
-import org.apache.syncope.core.persistence.api.dao.GroupDAO;
-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.MembershipCond;
-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.SearchCond;
-import org.apache.syncope.core.persistence.api.dao.search.SubjectCond;
-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.AbstractTest;
-import org.junit.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-@Transactional
-public class AttributableSearchTest extends AbstractTest {
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private GroupDAO groupDAO;
-
-    @Autowired
-    private SubjectSearchDAO searchDAO;
-
-    @Test
-    public void userMatch() {
-        User user = userDAO.find(1L);
-        assertNotNull(user);
-
-        MembershipCond membershipCond = new MembershipCond();
-        membershipCond.setGroupId(5L);
-
-        assertFalse(searchDAO.matches(user, 
SearchCond.getLeafCond(membershipCond), SubjectType.USER));
-
-        membershipCond.setGroupId(1L);
-
-        assertTrue(searchDAO.matches(user, 
SearchCond.getLeafCond(membershipCond), SubjectType.USER));
-    }
-
-    @Test
-    public void groupMatch() {
-        Group group = groupDAO.find(1L);
-        assertNotNull(group);
-
-        AttributeCond attrCond = new AttributeCond();
-        attrCond.setSchema("show");
-        attrCond.setType(AttributeCond.Type.ISNOTNULL);
-
-        assertTrue(searchDAO.matches(group, SearchCond.getLeafCond(attrCond), 
SubjectType.GROUP));
-    }
-
-    @Test
-    public void searchWithLikeCondition() {
-        AttributeCond fullnameLeafCond = new 
AttributeCond(AttributeCond.Type.LIKE);
-        fullnameLeafCond.setSchema("fullname");
-        fullnameLeafCond.setExpression("%o%");
-
-        MembershipCond membershipCond = new MembershipCond();
-        membershipCond.setGroupId(1L);
-
-        AttributeCond loginDateCond = new AttributeCond(AttributeCond.Type.EQ);
-        loginDateCond.setSchema("loginDate");
-        loginDateCond.setExpression("2009-05-26");
-
-        SearchCond subCond = 
SearchCond.getAndCond(SearchCond.getLeafCond(fullnameLeafCond), 
SearchCond.getLeafCond(
-                membershipCond));
-
-        assertTrue(subCond.isValid());
-
-        SearchCond cond = SearchCond.getAndCond(subCond, 
SearchCond.getLeafCond(loginDateCond));
-
-        assertTrue(cond.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, cond, SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchWithNotCondition() {
-        AttributeCond fullnameLeafCond = new 
AttributeCond(AttributeCond.Type.EQ);
-        fullnameLeafCond.setSchema("fullname");
-        fullnameLeafCond.setExpression("Giuseppe Verdi");
-
-        SearchCond cond = SearchCond.getNotLeafCond(fullnameLeafCond);
-        assertTrue(cond.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, cond, SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(4, users.size());
-
-        Set<Long> ids = new HashSet<>(users.size());
-        for (User user : users) {
-            ids.add(user.getKey());
-        }
-        assertTrue(ids.contains(1L));
-        assertTrue(ids.contains(3L));
-    }
-
-    @Test
-    public void searchByBoolean() {
-        AttributeCond coolLeafCond = new AttributeCond(AttributeCond.Type.EQ);
-        coolLeafCond.setSchema("cool");
-        coolLeafCond.setExpression("true");
-
-        SearchCond cond = SearchCond.getLeafCond(coolLeafCond);
-        assertTrue(cond.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, cond, SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-
-        assertEquals(Long.valueOf(4L), users.get(0).getKey());
-    }
-
-    @Test
-    public void searchByPageAndSize() {
-        AttributeCond fullnameLeafCond = new 
AttributeCond(AttributeCond.Type.LIKE);
-        fullnameLeafCond.setSchema("fullname");
-        fullnameLeafCond.setExpression("%o%");
-
-        MembershipCond membershipCond = new MembershipCond();
-        membershipCond.setGroupId(1L);
-
-        AttributeCond loginDateCond = new AttributeCond(AttributeCond.Type.EQ);
-        loginDateCond.setSchema("loginDate");
-        loginDateCond.setExpression("2009-05-26");
-
-        SearchCond subCond = SearchCond.getAndCond(
-                SearchCond.getLeafCond(fullnameLeafCond), 
SearchCond.getLeafCond(membershipCond));
-
-        assertTrue(subCond.isValid());
-
-        SearchCond cond = SearchCond.getAndCond(subCond, 
SearchCond.getLeafCond(loginDateCond));
-
-        assertTrue(cond.isValid());
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                cond, 1, 2, Collections.<OrderByClause>emptyList(),
-                SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                cond, 2, 2, Collections.<OrderByClause>emptyList(),
-                SubjectType.USER);
-        assertNotNull(users);
-        assertTrue(users.isEmpty());
-    }
-
-    @Test
-    public void searchByMembership() {
-        MembershipCond membershipCond = new MembershipCond();
-        membershipCond.setGroupId(1L);
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(membershipCond), SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(2, users.size());
-
-        membershipCond = new MembershipCond();
-        membershipCond.setGroupId(5L);
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getNotLeafCond(membershipCond), SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(5, users.size());
-    }
-
-    @Test
-    public void searchByIsNull() {
-        AttributeCond coolLeafCond = new 
AttributeCond(AttributeCond.Type.ISNULL);
-        coolLeafCond.setSchema("cool");
-
-        List<User> users = searchDAO.search(
-                SyncopeConstants.FULL_ADMIN_REALMS, 
SearchCond.getLeafCond(coolLeafCond), SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(4, users.size());
-
-        coolLeafCond = new AttributeCond(AttributeCond.Type.ISNOTNULL);
-        coolLeafCond.setSchema("cool");
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(coolLeafCond), SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchByResource() {
-        ResourceCond ws2 = new ResourceCond();
-        ws2.setResourceName("ws-target-resource-2");
-
-        ResourceCond ws1 = new ResourceCond();
-        ws1.setResourceName("ws-target-resource-list-mappings-2");
-
-        SearchCond searchCondition = 
SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), 
SearchCond.getLeafCond(ws1));
-
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, 
SubjectType.USER);
-
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void searchByBooleanSubjectCond() {
-        AttributeCond booleanCond = new AttributeCond(SubjectCond.Type.EQ);
-        booleanCond.setSchema("show");
-        booleanCond.setExpression("true");
-
-        List<Group> matchingGroups = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                SearchCond.getLeafCond(booleanCond), SubjectType.GROUP);
-        assertNotNull(matchingGroups);
-        assertFalse(matchingGroups.isEmpty());
-    }
-
-    @Test
-    public void searchByUsernameAndKey() {
-        SubjectCond usernameLeafCond = new SubjectCond(SubjectCond.Type.LIKE);
-        usernameLeafCond.setSchema("username");
-        usernameLeafCond.setExpression("%ini");
-
-        SubjectCond idRightCond = new SubjectCond(SubjectCond.Type.LT);
-        idRightCond.setSchema("key");
-        idRightCond.setExpression("2");
-
-        SearchCond searchCondition = SearchCond.getAndCond(
-                SearchCond.getLeafCond(usernameLeafCond),
-                SearchCond.getLeafCond(idRightCond));
-
-        List<User> matchingUsers = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, SubjectType.USER);
-
-        assertNotNull(matchingUsers);
-        assertEquals(1, matchingUsers.size());
-        assertEquals("rossini", matchingUsers.iterator().next().getUsername());
-        assertEquals(1L, matchingUsers.iterator().next().getKey(), 0);
-    }
-
-    @Test
-    public void searchByGroupNameAndKey() {
-        SubjectCond groupNameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
-        groupNameLeafCond.setSchema("name");
-        groupNameLeafCond.setExpression("root");
-
-        SubjectCond idRightCond = new SubjectCond(SubjectCond.Type.LT);
-        idRightCond.setSchema("key");
-        idRightCond.setExpression("2");
-
-        SearchCond searchCondition = SearchCond.getAndCond(
-                SearchCond.getLeafCond(groupNameLeafCond),
-                SearchCond.getLeafCond(idRightCond));
-
-        assertTrue(searchCondition.isValid());
-
-        List<Group> matchingGroups = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, SubjectType.GROUP);
-
-        assertNotNull(matchingGroups);
-        assertEquals(1, matchingGroups.size());
-        assertEquals("root", matchingGroups.iterator().next().getName());
-        assertEquals(1L, matchingGroups.iterator().next().getKey(), 0);
-    }
-
-    @Test
-    public void searchByUsernameAndFullname() {
-        SubjectCond usernameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
-        usernameLeafCond.setSchema("username");
-        usernameLeafCond.setExpression("rossini");
-
-        AttributeCond idRightCond = new AttributeCond(AttributeCond.Type.LIKE);
-        idRightCond.setSchema("fullname");
-        idRightCond.setExpression("Giuseppe V%");
-
-        SearchCond searchCondition = SearchCond.getOrCond(
-                SearchCond.getLeafCond(usernameLeafCond),
-                SearchCond.getLeafCond(idRightCond));
-
-        List<User> matchingUsers = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, SubjectType.USER);
-        assertNotNull(matchingUsers);
-        assertEquals(2, matchingUsers.size());
-    }
-
-    @Test
-    public void searchById() {
-        SubjectCond idLeafCond = new SubjectCond(SubjectCond.Type.LT);
-        idLeafCond.setSchema("id");
-        idLeafCond.setExpression("2");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(idLeafCond);
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, 
SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-        assertEquals(1L, users.iterator().next().getKey(), 0);
-
-        idLeafCond = new SubjectCond(SubjectCond.Type.LT);
-        idLeafCond.setSchema("id");
-        idLeafCond.setExpression("4");
-
-        searchCondition = SearchCond.getNotLeafCond(idLeafCond);
-        assertTrue(searchCondition.isValid());
-
-        users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, 
searchCondition, SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(2, users.size());
-        assertTrue(CollectionUtils.exists(users, new Predicate<User>() {
-
-            @Override
-            public boolean evaluate(User user) {
-                return user.getKey() == 4;
-            }
-        }));
-    }
-
-    @Test
-    public void userOrderBy() {
-        SubjectCond usernameLeafCond = new SubjectCond(SubjectCond.Type.EQ);
-        usernameLeafCond.setSchema("username");
-        usernameLeafCond.setExpression("rossini");
-        AttributeCond idRightCond = new AttributeCond(AttributeCond.Type.LIKE);
-        idRightCond.setSchema("fullname");
-        idRightCond.setExpression("Giuseppe V%");
-        SearchCond searchCondition = SearchCond.getOrCond(
-                SearchCond.getLeafCond(usernameLeafCond), 
SearchCond.getLeafCond(idRightCond));
-
-        List<OrderByClause> orderByClauses = new ArrayList<>();
-        OrderByClause orderByClause = new OrderByClause();
-        orderByClause.setField("username");
-        orderByClause.setDirection(OrderByClause.Direction.DESC);
-        orderByClauses.add(orderByClause);
-        orderByClause = new OrderByClause();
-        orderByClause.setField("fullname");
-        orderByClause.setDirection(OrderByClause.Direction.ASC);
-        orderByClauses.add(orderByClause);
-
-        List<User> users = searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, orderByClauses, SubjectType.USER);
-        assertEquals(searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, 
searchCondition, SubjectType.USER),
-                users.size());
-    }
-
-    @Test
-    public void groupOrderBy() {
-        SubjectCond idLeafCond = new SubjectCond(SubjectCond.Type.LIKE);
-        idLeafCond.setSchema("name");
-        idLeafCond.setExpression("%r");
-        SearchCond searchCondition = SearchCond.getLeafCond(idLeafCond);
-        assertTrue(searchCondition.isValid());
-
-        OrderByClause orderByClause = new OrderByClause();
-        orderByClause.setField("name");
-
-        List<Group> groups = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, Collections.singletonList(orderByClause), 
SubjectType.GROUP);
-        assertEquals(searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS,
-                searchCondition, SubjectType.GROUP),
-                groups.size());
-    }
-
-    @Test
-    public void issue202() {
-        ResourceCond ws2 = new ResourceCond();
-        ws2.setResourceName("ws-target-resource-2");
-
-        ResourceCond ws1 = new ResourceCond();
-        ws1.setResourceName("ws-target-resource-list-mappings-1");
-
-        SearchCond searchCondition =
-                SearchCond.getAndCond(SearchCond.getNotLeafCond(ws2), 
SearchCond.getNotLeafCond(ws1));
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, 
SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(2, users.size());
-        assertTrue(CollectionUtils.exists(users, new Predicate<User>() {
-
-            @Override
-            public boolean evaluate(User user) {
-                return user.getKey() == 4;
-            }
-        }));
-    }
-
-    @Test
-    public void issue242() {
-        SubjectCond cond = new SubjectCond(AttributeCond.Type.LIKE);
-        cond.setSchema("id");
-        cond.setExpression("test%");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(cond);
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, 
SubjectType.USER);
-        assertNotNull(users);
-        assertTrue(users.isEmpty());
-    }
-
-    @Test
-    public void issueSYNCOPE46() {
-        SubjectCond cond = new SubjectCond(AttributeCond.Type.LIKE);
-        cond.setSchema("username");
-        cond.setExpression("%ossin%");
-
-        SearchCond searchCondition = SearchCond.getLeafCond(cond);
-        assertTrue(searchCondition.isValid());
-
-        List<User> users = 
searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS, searchCondition, 
SubjectType.USER);
-        assertNotNull(users);
-        assertEquals(1, users.size());
-    }
-
-    @Test
-    public void issueSYNCOPE433() {
-        AttributeCond isNullCond = new 
AttributeCond(AttributeCond.Type.ISNULL);
-        isNullCond.setSchema("loginDate");
-
-        SubjectCond likeCond = new SubjectCond(AttributeCond.Type.LIKE);
-        likeCond.setSchema("username");
-        likeCond.setExpression("%ossin%");
-
-        SearchCond searchCond = SearchCond.getOrCond(
-                SearchCond.getLeafCond(isNullCond), 
SearchCond.getLeafCond(likeCond));
-
-        Integer count = searchDAO.count(SyncopeConstants.FULL_ADMIN_REALMS, 
searchCond, SubjectType.USER);
-        assertNotNull(count);
-        assertTrue(count > 0);
-    }
-}

Reply via email to