← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18351: wip, optimize web-api object filter by using new QueryService, splits out possible DB queries fro...

 

------------------------------------------------------------
revno: 18351
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2015-02-20 15:28:01 +0700
message:
  wip, optimize web-api object filter by using new QueryService, splits out possible DB queries from filter and runs it thrugh a QueryEngine, the rest is run through the old in-memory filter system.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Query.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restriction.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Typed.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/DefaultObjectFilterService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ObjectFilterService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ops/Op.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java	2015-02-20 04:06:33 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Operator.java	2015-02-20 08:28:01 +0000
@@ -28,6 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.apache.commons.lang3.time.DateUtils;
 import org.hisp.dhis.schema.Klass;
 
 import java.util.Date;
@@ -37,14 +38,15 @@
  */
 public enum Operator
 {
-    EQ( Typed.from( String.class, Number.class, Date.class ), 1 ),
-    NE( Typed.from( String.class, Number.class, Date.class ), 1 ),
-    GT( Typed.from( String.class, Number.class, Date.class ), 1 ),
-    LT( Typed.from( String.class, Number.class, Date.class ), 1 ),
-    GE( Typed.from( String.class, Number.class, Date.class ), 1 ),
-    LE( Typed.from( String.class, Number.class, Date.class ), 1 ),
+    EQ( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ),
+    NE( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ),
+    GT( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ),
+    LT( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ),
+    GE( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ),
+    LE( Typed.from( String.class, Boolean.class, Number.class, Date.class ), 1 ),
     BETWEEN( Typed.from( String.class, Number.class, Date.class ), 2 ),
     LIKE( Typed.from( String.class ), 1 ),
+    ILIKE( Typed.from( String.class ), 1 ),
     IN( 1, Integer.MAX_VALUE );
 
     Integer min;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Query.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Query.java	2015-02-18 13:08:37 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Query.java	2015-02-20 08:28:01 +0000
@@ -32,6 +32,7 @@
 import org.hisp.dhis.schema.Schema;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -89,9 +90,10 @@
         return firstResult;
     }
 
-    public void setFirstResult( Integer firstResult )
+    public Query setFirstResult( Integer firstResult )
     {
         this.firstResult = firstResult;
+        return this;
     }
 
     public Integer getMaxResults()
@@ -99,9 +101,10 @@
         return maxResults;
     }
 
-    public void setMaxResults( Integer maxResults )
+    public Query setMaxResults( Integer maxResults )
     {
         this.maxResults = maxResults;
+        return this;
     }
 
     // Builder
@@ -126,6 +129,12 @@
         return this;
     }
 
+    public Query add( Collection<Restriction> restrictions )
+    {
+        this.restrictions.addAll( restrictions );
+        return this;
+    }
+
     public Query addOrder( Order... orders )
     {
         for ( Order order : orders )
@@ -139,7 +148,7 @@
         return this;
     }
 
-    public Query addOrders( List<Order> orders )
+    public Query addOrders( Collection<Order> orders )
     {
         this.orders.addAll( orders );
         return this;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restriction.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restriction.java	2015-02-18 13:08:37 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restriction.java	2015-02-20 08:28:01 +0000
@@ -29,8 +29,10 @@
  */
 
 import com.google.common.base.MoreObjects;
+import org.apache.commons.lang3.time.DateUtils;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -107,7 +109,7 @@
     // Builder
     public Restriction addParameter( Object parameter )
     {
-        this.parameters.add( parameter );
+        this.parameters.add( ( parameter ) );
         return this;
     }
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java	2015-02-20 04:03:39 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Restrictions.java	2015-02-20 08:28:01 +0000
@@ -28,6 +28,10 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.apache.commons.lang3.time.DateUtils;
+
+import java.util.Date;
+
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
@@ -68,9 +72,15 @@
         return new Restriction( path, Operator.BETWEEN, lside, rside );
     }
 
+    // Map like to ilike for the moment, since like in the web-api is actually ilike..
     public static Restriction like( String path, Object value )
     {
-        return new Restriction( path, Operator.LIKE, value );
+        return new Restriction( path, Operator.ILIKE, value );
+    }
+
+    public static Restriction ilike( String path, Object value )
+    {
+        return new Restriction( path, Operator.ILIKE, value );
     }
 
     public static Restriction in( String path, Object... values )

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Typed.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Typed.java	2015-02-20 04:06:33 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Typed.java	2015-02-20 08:28:01 +0000
@@ -46,6 +46,11 @@
         this.klasses = klasses;
     }
 
+    public Class<?>[] getKlasses()
+    {
+        return klasses;
+    }
+
     public boolean isValid( Klass klass )
     {
         return klass == null || isValid( klass.getKlass() );

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java	2015-02-18 13:08:37 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/query/CriteriaQueryEngine.java	2015-02-20 08:28:01 +0000
@@ -28,8 +28,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.apache.commons.lang3.time.DateUtils;
 import org.hibernate.Criteria;
+import org.hibernate.criterion.Conjunction;
 import org.hibernate.criterion.Criterion;
+import org.hibernate.criterion.Disjunction;
 import org.hibernate.criterion.Restrictions;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.hibernate.HibernateGenericStore;
@@ -37,8 +40,8 @@
 import org.hisp.dhis.schema.Schema;
 import org.springframework.beans.factory.annotation.Autowired;
 
-import javax.annotation.PostConstruct;
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -49,18 +52,9 @@
 public class CriteriaQueryEngine implements QueryEngine
 {
     @Autowired
-    private final List<HibernateGenericStore> hibernateGenericStores = new ArrayList<>();
-
-    private final Map<Class<?>, HibernateGenericStore> stores = new HashMap<>();
-
-    @PostConstruct
-    public void init()
-    {
-        for ( HibernateGenericStore store : hibernateGenericStores )
-        {
-            stores.put( store.getClazz(), store );
-        }
-    }
+    private final List<HibernateGenericStore<? extends IdentifiableObject>> hibernateGenericStores = new ArrayList<>();
+
+    private Map<Class<?>, HibernateGenericStore<? extends IdentifiableObject>> stores = new HashMap<>();
 
     @Override
     @SuppressWarnings( "unchecked" )
@@ -73,7 +67,7 @@
             return new ArrayList<>();
         }
 
-        HibernateGenericStore store = stores.get( schema.getKlass() );
+        HibernateGenericStore store = getStore( (Class<? extends IdentifiableObject>) schema.getKlass() );
 
         if ( store == null )
         {
@@ -92,6 +86,8 @@
 
     private Criteria buildCriteria( Criteria criteria, Query query )
     {
+        Map<Operator, List<Restriction>> restrictions = new HashMap<>();
+
         if ( query.getFirstResult() != null )
         {
             criteria.setFirstResult( query.getFirstResult() );
@@ -104,7 +100,31 @@
 
         for ( Restriction restriction : query.getRestrictions() )
         {
-            criteria.add( getHibernateCriterion( query.getSchema(), restriction ) );
+            if ( !restrictions.containsKey( restriction.getOperator() ) )
+            {
+                restrictions.put( restriction.getOperator(), new ArrayList<Restriction>() );
+            }
+
+            restrictions.get( restriction.getOperator() ).add( restriction );
+        }
+
+        for ( Map.Entry<Operator, List<Restriction>> restriction : restrictions.entrySet() )
+        {
+            if ( restriction.getValue().size() == 1 )
+            {
+                criteria.add( getHibernateCriterion( query.getSchema(), restriction.getValue().get( 0 ) ) );
+            }
+            else
+            {
+                Disjunction disjunction = Restrictions.disjunction();
+
+                for ( Restriction r : restriction.getValue() )
+                {
+                    disjunction.add( getHibernateCriterion( query.getSchema(), r ) );
+                }
+
+                criteria.add( disjunction );
+            }
         }
 
         for ( Order order : query.getOrders() )
@@ -124,43 +144,54 @@
 
         Property property = schema.getProperty( restriction.getPath() );
 
+        List<Object> parameters = new ArrayList<>();
+
+        for ( Object parameter : restriction.getParameters() )
+        {
+            parameters.add( getValue( property, parameter ) );
+        }
+
         switch ( restriction.getOperator() )
         {
             case EQ:
             {
-                return Restrictions.eq( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.eq( property.getFieldName(), parameters.get( 0 ) );
             }
             case NE:
             {
-                return Restrictions.ne( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.ne( property.getFieldName(), parameters.get( 0 ) );
             }
             case GT:
             {
-                return Restrictions.gt( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.gt( property.getFieldName(), parameters.get( 0 ) );
             }
             case LT:
             {
-                return Restrictions.lt( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.lt( property.getFieldName(), parameters.get( 0 ) );
             }
             case GE:
             {
-                return Restrictions.ge( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.ge( property.getFieldName(), parameters.get( 0 ) );
             }
             case LE:
             {
-                return Restrictions.le( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.le( property.getFieldName(), parameters.get( 0 ) );
             }
             case BETWEEN:
             {
-                return Restrictions.between( property.getFieldName(), restriction.getParameter( 0 ), restriction.getParameter( 1 ) );
+                return Restrictions.between( property.getFieldName(), parameters.get( 0 ), parameters.get( 1 ) );
             }
             case LIKE:
             {
-                return Restrictions.like( property.getFieldName(), restriction.getParameter( 0 ) );
+                return Restrictions.like( property.getFieldName(), parameters.get( 0 ) );
+            }
+            case ILIKE:
+            {
+                return Restrictions.ilike( property.getFieldName(), parameters.get( 0 ) );
             }
             case IN:
             {
-                return Restrictions.in( property.getFieldName(), restriction.getParameters() );
+                return Restrictions.in( property.getFieldName(), parameters );
             }
         }
 
@@ -192,4 +223,103 @@
 
         return criteriaOrder;
     }
+
+    private void initStoreMap()
+    {
+        if ( !stores.isEmpty() )
+        {
+            return;
+        }
+
+        for ( HibernateGenericStore<? extends IdentifiableObject> store : hibernateGenericStores )
+        {
+            stores.put( store.getClazz(), store );
+        }
+    }
+
+    private HibernateGenericStore getStore( Class<? extends IdentifiableObject> klass )
+    {
+        initStoreMap();
+        return stores.get( klass );
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private <T> T getValue( Property property, Object objectValue )
+    {
+        Class<?> klass = property.getKlass();
+
+        if ( !String.class.isInstance( objectValue ) )
+        {
+            return (T) objectValue;
+        }
+
+        String value = (String) objectValue;
+
+        if ( klass.isInstance( value ) )
+        {
+            return (T) value;
+        }
+
+        if ( Boolean.class.isAssignableFrom( klass ) )
+        {
+            try
+            {
+                return (T) Boolean.valueOf( value );
+            }
+            catch ( Exception ignored )
+            {
+            }
+        }
+        else if ( Integer.class.isAssignableFrom( klass ) )
+        {
+            try
+            {
+                return (T) Integer.valueOf( value );
+            }
+            catch ( Exception ignored )
+            {
+            }
+        }
+        else if ( Float.class.isAssignableFrom( klass ) )
+        {
+            try
+            {
+                return (T) Float.valueOf( value );
+            }
+            catch ( Exception ignored )
+            {
+            }
+        }
+        else if ( Double.class.isAssignableFrom( klass ) )
+        {
+            try
+            {
+                return (T) Double.valueOf( value );
+            }
+            catch ( Exception ignored )
+            {
+            }
+        }
+        else if ( Date.class.isAssignableFrom( klass ) )
+        {
+            try
+            {
+                return (T) DateUtils.parseDate( value,
+                    "yyyy-MM-dd'T'HH:mm:ssZ",
+                    "yyyy-MM-dd'T'HH:mm:ss",
+                    "yyyy-MM-dd'T'HH:mm",
+                    "yyyy-MM-dd'T'HH",
+                    "yyyy-MM-dd",
+                    "yyyy-MM",
+                    "yyyyMMdd",
+                    "yyyyMM",
+                    "yyyy" );
+            }
+            catch ( Exception ignored )
+            {
+            }
+        }
+
+        return null;
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/DefaultObjectFilterService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/DefaultObjectFilterService.java	2015-02-06 03:50:03 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/DefaultObjectFilterService.java	2015-02-20 08:28:01 +0000
@@ -29,16 +29,24 @@
  */
 
 import com.google.common.collect.Lists;
+import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.dxf2.objectfilter.ops.Op;
 import org.hisp.dhis.dxf2.objectfilter.ops.OpStatus;
 import org.hisp.dhis.dxf2.parser.ParserService;
+import org.hisp.dhis.query.Order;
+import org.hisp.dhis.query.Query;
+import org.hisp.dhis.query.QueryService;
+import org.hisp.dhis.query.Restriction;
+import org.hisp.dhis.query.Restrictions;
 import org.hisp.dhis.schema.Property;
 import org.hisp.dhis.schema.Schema;
 import org.hisp.dhis.schema.SchemaService;
 import org.hisp.dhis.system.util.ReflectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -53,6 +61,124 @@
     @Autowired
     private SchemaService schemaService;
 
+    @Autowired
+    private QueryService queryService;
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T extends IdentifiableObject> List<T> query( Class<? extends IdentifiableObject> klass, List<String> filters, int first, int max )
+    {
+        Schema schema = schemaService.getDynamicSchema( klass );
+        Query query = Query.from( schema );
+        query.setFirstResult( first ).setMaxResults( max );
+        query.add( getRestrictions( schema, filters ) );
+
+        if ( schema.haveProperty( "name" ) && schema.getProperty( "name" ).isPersisted() )
+        {
+            query.addOrder( Order.asc( schema.getProperty( "name" ) ) );
+        }
+        else
+        {
+            query.addOrder( Order.desc( schema.getProperty( "created" ) ) );
+        }
+
+        return (List<T>) queryService.query( query ).getItems();
+    }
+
+    private List<Restriction> getRestrictions( Schema schema, List<String> filters )
+    {
+        List<Restriction> restrictions = new ArrayList<>();
+        List<String> candidates = getRestrictionCandidates( schema, filters );
+
+        if ( candidates.isEmpty() )
+        {
+            return restrictions;
+        }
+
+        for ( String candidate : candidates )
+        {
+            restrictions.add( getRestriction( schema, candidate ) );
+        }
+
+        return restrictions;
+    }
+
+    private List<String> getRestrictionCandidates( Schema schema, List<String> filters )
+    {
+        List<String> candidates = new ArrayList<>();
+
+        Iterator<String> iterator = filters.iterator();
+
+        while ( iterator.hasNext() )
+        {
+            String candidate = iterator.next();
+
+            if ( !candidate.contains( "." ) && getRestriction( schema, candidate ) != null )
+            {
+                candidates.add( candidate );
+                iterator.remove();
+            }
+        }
+
+        return candidates;
+    }
+
+    private Restriction getRestriction( Schema schema, String filter )
+    {
+        if ( filter == null )
+        {
+            return null;
+        }
+
+        String[] split = filter.split( ":" );
+
+        if ( split.length != 3 )
+        {
+            return null;
+        }
+
+        Property property = schema.getProperty( split[0] );
+
+        if ( property == null || !property.isPersisted() || !property.isSimple() )
+        {
+            return null;
+        }
+
+        switch ( split[1] )
+        {
+            case "eq":
+            {
+                return Restrictions.eq( split[0], split[2] );
+            }
+            case "neq":
+            {
+                return Restrictions.ne( split[0], split[2] );
+            }
+            case "gt":
+            {
+                return Restrictions.gt( split[0], split[2] );
+            }
+            case "lt":
+            {
+                return Restrictions.lt( split[0], split[2] );
+            }
+            case "gte":
+            {
+                return Restrictions.ge( split[0], split[2] );
+            }
+            case "lte":
+            {
+                return Restrictions.le( split[0], split[2] );
+            }
+            case "like":
+            {
+                return Restrictions.like( split[0], "%" + split[2] + "%" );
+            }
+        }
+
+        return null;
+    }
+
     @Override
     public <T> List<T> filter( List<T> objects, List<String> filters )
     {

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ObjectFilterService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ObjectFilterService.java	2015-02-06 03:50:03 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ObjectFilterService.java	2015-02-20 08:28:01 +0000
@@ -28,6 +28,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import org.hisp.dhis.common.IdentifiableObject;
+
 import java.util.List;
 
 /**
@@ -36,6 +38,17 @@
 public interface ObjectFilterService
 {
     /**
+     * Splits out candidates for DB query, and returns result.
+     * <p/>
+     * WARNING: filters list will be modified, filters that have been taken care of using Query will be removed.
+     *
+     * @param klass   Class to query
+     * @param filters Filter string
+     * @return Filtered object list
+     */
+    <T extends IdentifiableObject> List<T> query( Class<? extends IdentifiableObject> klass, List<String> filters, int first, int max );
+
+    /**
      * Filter a list of objects based on un-parsed filter string.
      * In-memory filter
      *

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ops/Op.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ops/Op.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/objectfilter/ops/Op.java	2015-02-20 08:28:01 +0000
@@ -103,6 +103,16 @@
             {
             }
         }
+        else if ( Double.class.isAssignableFrom( klass ) )
+        {
+            try
+            {
+                return (T) Double.valueOf( value );
+            }
+            catch ( Exception ignored )
+            {
+            }
+        }
         else if ( Date.class.isAssignableFrom( klass ) )
         {
             for ( SimpleDateFormat simpleDateFormat : simpleDateFormats )

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java	2015-02-18 02:48:51 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java	2015-02-20 08:28:01 +0000
@@ -28,19 +28,10 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.io.IOException;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
 import org.hisp.dhis.acl.AclService;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObject;
@@ -87,10 +78,17 @@
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import com.google.common.base.Enums;
-import com.google.common.base.Joiner;
-import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -146,106 +144,23 @@
     {
         List<String> fields = Lists.newArrayList( contextService.getParameterValues( "fields" ) );
         List<String> filters = Lists.newArrayList( contextService.getParameterValues( "filter" ) );
-
         List<Order> orders = orderOptions.getOrders( getSchema() );
 
         WebOptions options = new WebOptions( rpParameters );
         WebMetaData metaData = new WebMetaData();
 
-        Schema schema = getSchema();
-
         if ( fields.isEmpty() )
         {
             fields.add( ":identifiable" );
         }
 
-        boolean hasPaging = options.hasPaging();
-
-        List<T> entities;
-
-        if ( !orders.isEmpty() )
-        {
-            if ( options.hasPaging() )
-            {
-                int count = manager.getCount( getEntityClass() );
-                Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
-                metaData.setPager( pager );
-                entities = manager.getBetween( getEntityClass(), pager.getOffset(), pager.getPageSize(), orders );
-                hasPaging = false;
-            }
-            else
-            {
-                entities = (List<T>) manager.getAll( getEntityClass(), orders );
-                hasPaging = false;
-            }
-        }
-        else if ( filters.isEmpty() )
-        {
-            entities = getEntityList( metaData, options, filters );
-            hasPaging = false;
-        }
-        else
-        {
-            Iterator<String> iterator = filters.iterator();
-            String name = null;
-
-            // Use database query for name filter
-
-            if ( schema.haveProperty( "name" ) && schema.getProperty( "name" ).isPersisted() )
-            {
-                while ( iterator.hasNext() )
-                {
-                    String filter = iterator.next();
-
-                    if ( filter.startsWith( "name:like:" ) )
-                    {
-                        name = filter.substring( "name:like:".length() );
-                        iterator.remove();
-                        break;
-                    }
-                }
-            }
-
-            if ( name != null )
-            {
-                if ( options.hasPaging() )
-                {
-                    int count = manager.getCountLikeName( getEntityClass(), name );
-
-                    Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
-                    metaData.setPager( pager );
-
-                    entities = Lists.newArrayList( manager.getBetweenLikeName( getEntityClass(), name, pager.getOffset(), pager.getPageSize() ) );
-                    hasPaging = false;
-                }
-                else
-                {
-                    entities = Lists.newArrayList( manager.getLikeName( getEntityClass(), name ) );
-                }
-            }
-            else
-            {
-                // Get full list when using filters other than name / objects without persisted name
-
-                if ( !filters.isEmpty() )
-                {
-                    if ( options.hasPaging() )
-                    {
-                        hasPaging = true;
-                        options.getOptions().put( "paging", "false" );
-                    }
-                }
-
-                entities = getEntityList( metaData, options, filters );
-            }
-        }
-
+        List<T> entities = getEntityList( metaData, options, filters );
         Pager pager = metaData.getPager();
 
         entities = objectFilterService.filter( entities, filters );
         translate( entities, translateOptions );
 
-        if ( hasPaging )
+        if ( options.hasPaging() )
         {
             pager = new Pager( options.getPage(), entities.size(), options.getPageSize() );
             entities = PagerUtils.pageCollection( entities, pager );
@@ -835,18 +750,18 @@
         {
             entityList = Lists.newArrayList( manager.filter( getEntityClass(), options.getOptions().get( "query" ) ) );
         }
-        else if ( options.hasPaging() )
+        else if ( options.hasPaging() && filters.isEmpty() )
         {
             int count = manager.getCount( getEntityClass() );
 
             Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
             metaData.setPager( pager );
 
-            entityList = Lists.newArrayList( manager.getBetweenSorted( getEntityClass(), pager.getOffset(), pager.getPageSize() ) );
+            entityList = objectFilterService.query( getEntityClass(), filters, pager.getOffset(), pager.getPageSize() );
         }
         else
         {
-            entityList = Lists.newArrayList( manager.getAllSorted( getEntityClass() ) );
+            entityList = objectFilterService.query( getEntityClass(), filters, 0, Integer.MAX_VALUE );
         }
 
         return entityList;