← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14922: Event analytics. Refactor of QueryItem class to handle dimensions with multiple filters.

 

------------------------------------------------------------
revno: 14922
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2014-04-21 13:05:22 +0200
message:
  Event analytics. Refactor of QueryItem class to handle dimensions with multiple filters.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DimensionalObject.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryFilter.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeDimension.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityDataElementDimension.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceQueryParams.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAttributeDimension.hbm.xml
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityDataElementDimension.hbm.xml


--
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/common/BaseAnalyticalObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java	2014-04-16 14:01:54 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java	2014-04-21 11:05:22 +0000
@@ -343,7 +343,7 @@
         {            
             type = DimensionType.STATIC;
         }
-        else // Group set
+        else
         {
             // Data element group set
             
@@ -415,7 +415,7 @@
             {
                 TrackedEntityAttributeDimension tead = attributes.get( dimension );
                 
-                return new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_ATTRIBUTE, null, tead.getDisplayName(), tead.getOperator(), tead.getFilter() );
+                return new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_ATTRIBUTE, null, tead.getDisplayName(), tead.getFilter() );
             }
             
             // Tracked entity data element
@@ -431,7 +431,7 @@
             {
                 TrackedEntityDataElementDimension tedd = dataElements.get( dimension );
                 
-                return new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_DATAELEMENT, null, tedd.getDisplayName(), tedd.getOperator(), tedd.getFilter() );
+                return new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_DATAELEMENT, null, tedd.getDisplayName(), tedd.getFilter() );
             }
         }
         
@@ -558,7 +558,7 @@
         {
             objects.add( new BaseDimensionalObject( dimension, DimensionType.STATIC, new ArrayList<NameableObject>() ) );
         }
-        else // Group set
+        else
         {
             // Data element group set
             
@@ -624,7 +624,7 @@
             {
                 TrackedEntityAttributeDimension tead = attributes.get( dimension );
                 
-                objects.add( new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_ATTRIBUTE, null, tead.getDisplayName(), tead.getOperator(), tead.getFilter() ) );
+                objects.add( new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_ATTRIBUTE, null, tead.getDisplayName(), tead.getFilter() ) );
             }
             
             // Tracked entity data element
@@ -640,8 +640,8 @@
             {
                 TrackedEntityDataElementDimension tedd = dataElements.get( dimension );
                 
-                objects.add( new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_DATAELEMENT, null, tedd.getDisplayName(), tedd.getOperator(), tedd.getFilter() ) );
-            }            
+                objects.add( new BaseDimensionalObject( dimension, DimensionType.TRACKED_ENTITY_DATAELEMENT, null, tedd.getDisplayName(), tedd.getFilter() ) );
+            }
         }
         
         return objects;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java	2014-04-02 14:08:06 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseDimensionalObject.java	2014-04-21 11:05:22 +0000
@@ -63,12 +63,9 @@
     private List<NameableObject> items = new ArrayList<NameableObject>();
     
     /**
-     * Operator. Applicable for events only.
-     */
-    private String operator;
-    
-    /**
-     * Filter. Applicable for events only.
+     * Filter. Applicable for events. Contains operator and filter on this format:
+     * <operator>:<filter>;<operator>:<filter>
+     * Operator and filter pairs can be repeated any number of times.
      */
     private String filter;
     
@@ -115,13 +112,12 @@
         this.items = new ArrayList<NameableObject>( items );
     }
 
-    public BaseDimensionalObject( String dimension, DimensionType dimensionType, String dimensionName, String displayName, String operator, String filter )
+    public BaseDimensionalObject( String dimension, DimensionType dimensionType, String dimensionName, String displayName, String filter )
     {
         this.uid = dimension;
         this.dimensionType = dimensionType;
         this.dimensionName = dimensionName;
         this.displayName = displayName;
-        this.operator = operator;
         this.filter = filter;
     }
 
@@ -205,20 +201,6 @@
     @JsonProperty
     @JsonView( {DimensionalView.class} )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
-    public String getOperator()
-    {
-        return operator;
-    }
-
-    public void setOperator( String operator )
-    {
-        this.operator = operator;
-    }
-
-    @Override
-    @JsonProperty
-    @JsonView( {DimensionalView.class} )
-    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
     public String getFilter()
     {
         return filter;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DimensionalObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DimensionalObject.java	2014-04-01 12:44:59 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DimensionalObject.java	2014-04-21 11:05:22 +0000
@@ -106,12 +106,7 @@
     boolean hasItems();
     
     /**
-     * Gets the operator. Applicable for events only.
-     */
-    String getOperator();
-
-    /**
-     * Gets the filter. Applicable for events only.
+     * Gets the filter. Contains operator and filter. Applicable for events.
      */
     String getFilter();
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryFilter.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryFilter.java	2014-04-07 16:50:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryFilter.java	2014-04-21 11:05:22 +0000
@@ -71,7 +71,7 @@
     // Logic
     // -------------------------------------------------------------------------
     
-    public boolean hasFilter()
+    public boolean isFilter()
     {
         return operator != null && !operator.isEmpty() && filter != null && !filter.isEmpty();
     }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java	2014-04-07 16:50:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java	2014-04-21 11:05:22 +0000
@@ -39,10 +39,11 @@
  * @author Lars Helge Overland
  */
 public class QueryItem
-    extends QueryFilter
 {
     private IdentifiableObject item;
 
+    private List<QueryFilter> filters = new ArrayList<QueryFilter>();
+    
     private boolean numeric;
 
     // -------------------------------------------------------------------------
@@ -53,15 +54,31 @@
     {
         this.item = item;
     }
+
+    public QueryItem( IdentifiableObject item, boolean numeric )
+    {
+        this.item = item;
+        this.numeric = numeric;
+    }
     
     public QueryItem( IdentifiableObject item, String operator, String filter, boolean numeric )
     {
         this.item = item;
-        this.operator = operator;
-        this.filter = filter;
-        this.numeric = numeric;
-    }
-
+        this.numeric = numeric;
+        
+        if ( operator != null && filter != null )
+        {
+            this.filters.add( new QueryFilter( operator, filter ) );
+        }
+    }
+    
+    public QueryItem( IdentifiableObject item, List<QueryFilter> filters, boolean numeric )
+    {
+        this.item = item;
+        this.filters = filters;
+        this.numeric = numeric;
+    }
+    
     // -------------------------------------------------------------------------
     // Logic
     // -------------------------------------------------------------------------
@@ -75,6 +92,11 @@
     {
         return isNumeric() ? Double.class.getName() : String.class.getName();
     }
+    
+    public boolean hasFilter()
+    {
+        return filters != null && !filters.isEmpty();
+    }
 
     public static List<QueryItem> getQueryItems( Collection<? extends IdentifiableObject> objects )
     {
@@ -82,7 +104,7 @@
         
         for ( IdentifiableObject object : objects )
         {
-            queryItems.add( new QueryItem( object, null, null, false ) );
+            queryItems.add( new QueryItem( object, false ) );
         }
         
         return queryItems;
@@ -124,7 +146,7 @@
     @Override
     public String toString()
     {
-        return "[Item: " + item + ", operator: " + operator + ", filter: " + filter + "]";
+        return "[Item: " + item + ", filters: " + filters + "]";
     }
     
     // -------------------------------------------------------------------------
@@ -141,6 +163,16 @@
         this.item = item;
     }
 
+    public List<QueryFilter> getFilters()
+    {
+        return filters;
+    }
+
+    public void setFilters( List<QueryFilter> filters )
+    {
+        this.filters = filters;
+    }
+
     public boolean isNumeric()
     {
         return numeric;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeDimension.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeDimension.java	2014-04-02 12:55:41 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttributeDimension.java	2014-04-21 11:05:22 +0000
@@ -35,10 +35,16 @@
 {
     private int id;
     
+    /**
+     * Attribute.
+     */
     private TrackedEntityAttribute attribute;
     
-    private String operator;
-    
+    /**
+     * Operator and filter on this format:
+     * <operator>:<filter>;<operator>:<filter>
+     * Operator and filter pairs can be repeated any number of times.
+     */
     private String filter;
 
     // -------------------------------------------------------------------------
@@ -87,16 +93,6 @@
         this.attribute = attribute;
     }
 
-    public String getOperator()
-    {
-        return operator;
-    }
-
-    public void setOperator( String operator )
-    {
-        this.operator = operator;
-    }
-
     public String getFilter()
     {
         return filter;
@@ -106,5 +102,4 @@
     {
         this.filter = filter;
     }
-
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityDataElementDimension.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityDataElementDimension.java	2014-04-02 12:55:41 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityDataElementDimension.java	2014-04-21 11:05:22 +0000
@@ -36,12 +36,18 @@
 {
     private int id;
     
+    /**
+     * Data element.
+     */
     private DataElement dataElement;
 
-    private String operator;
-    
+    /**
+     * Operator and filter on this format:
+     * <operator>:<filter>;<operator>:<filter>
+     * Operator and filter pairs can be repeated any number of times.
+     */
     private String filter;
-
+    
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
@@ -88,16 +94,6 @@
         this.dataElement = dataElement;
     }
 
-    public String getOperator()
-    {
-        return operator;
-    }
-
-    public void setOperator( String operator )
-    {
-        this.operator = operator;
-    }
-
     public String getFilter()
     {
         return filter;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceQueryParams.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceQueryParams.java	2014-04-18 14:01:25 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityInstanceQueryParams.java	2014-04-21 11:05:22 +0000
@@ -159,6 +159,8 @@
     // -------------------------------------------------------------------------
     
     /**
+     * //TODO allow attributes only once and allow multiple filters per item
+     * 
      * Performs a set of operations on this params.
      * 
      * <ul>
@@ -166,7 +168,7 @@
      * If a query item is specified as an attribute item as well as a filter 
      * item, the filter item will be removed. In that case, if the attribute 
      * item does not have a filter value and the filter item has a filter value, 
-     * it will be applied to the attribute item.
+     * it will be applied to the attribute item. 
      * </li>
      * </ul> 
      */
@@ -184,10 +186,9 @@
             {
                 QueryItem attribute = attributes.get( index );
                 
-                if ( !attribute.hasFilter() )
+                if ( !attribute.hasFilter() && filter.hasFilter() )
                 {
-                    attribute.setOperator( filter.getOperator() );
-                    attribute.setFilter( filter.getFilter() );
+                    attribute.getFilters().add( filter.getFilters().iterator().next() );
                 }
                 
                 filterIter.remove();

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java	2014-04-08 18:25:25 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/dimension/DefaultDimensionService.java	2014-04-21 11:05:22 +0000
@@ -427,7 +427,6 @@
                 {
                     TrackedEntityAttributeDimension attributeDimension = new TrackedEntityAttributeDimension();
                     attributeDimension.setAttribute( identifiableObjectManager.get( TrackedEntityAttribute.class, dimensionId ) );
-                    attributeDimension.setOperator( dimension.getOperator() );
                     attributeDimension.setFilter( dimension.getFilter() );
                     
                     object.getAttributeDimensions().add( attributeDimension );
@@ -436,7 +435,6 @@
                 {
                     TrackedEntityDataElementDimension dataElementDimension = new TrackedEntityDataElementDimension();
                     dataElementDimension.setDataElement( identifiableObjectManager.get( DataElement.class, dimensionId ) );
-                    dataElementDimension.setOperator( dimension.getOperator() );
                     dataElementDimension.setFilter( dimension.getFilter() );
                     
                     object.getDataElementDimensions().add( dataElementDimension );

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2014-04-14 08:42:46 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2014-04-21 11:05:22 +0000
@@ -36,7 +36,6 @@
 import static org.hisp.dhis.common.NameableObjectUtils.asTypedList;
 import static org.hisp.dhis.organisationunit.OrganisationUnit.getParentGraphMap;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
@@ -61,6 +60,7 @@
 import org.hisp.dhis.common.IllegalQueryException;
 import org.hisp.dhis.common.NameableObject;
 import org.hisp.dhis.common.Pager;
+import org.hisp.dhis.common.QueryFilter;
 import org.hisp.dhis.common.QueryItem;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementService;
@@ -344,7 +344,7 @@
                 }
                 else
                 {
-                    params.getItems().addAll( getQueryItems( dim, pr ) );
+                    params.getItems().add( getQueryItem( dim, pr ) );
                 }
             }
         }
@@ -362,7 +362,7 @@
                 }
                 else
                 {
-                    params.getItemFilters().addAll( getQueryItems( dim, pr ) );
+                    params.getItemFilters().add( getQueryItem( dim, pr ) );
                 }
             }
         }
@@ -411,27 +411,26 @@
     // Supportive methods
     // -------------------------------------------------------------------------
 
-    private List<QueryItem> getQueryItems( String dimension, Program program )
+    private QueryItem getQueryItem( String dimension, Program program )
     {
-        List<QueryItem> items = new ArrayList<QueryItem>();
-
-        if ( !dimension.contains( DimensionalObjectUtils.DIMENSION_NAME_SEP ) )
+        String[] split = dimension.split( DimensionalObjectUtils.DIMENSION_NAME_SEP );
+        
+        if ( split == null || ( split.length % 2 != 1 ) )
         {
-            items.add( getItem( program, dimension, null, null ) );
+            throw new IllegalQueryException( "Query item or filter is invalid: " + dimension );
         }
-        else // Filter
-        {
-            String[] split = dimension.split( DimensionalObjectUtils.DIMENSION_NAME_SEP );
-
-            if ( split == null || split.length != 3 )
+        
+        QueryItem queryItem = getQueryItem( program, split[0] );
+        
+        if ( split.length > 1 )
+        {   
+            for ( int i = 1; i < split.length; i += 2 )
             {
-                throw new IllegalQueryException( "Item filter has invalid format: " + dimension );
+                queryItem.getFilters().add( new QueryFilter( split[i], split[i+1] ) );
             }
-
-            items.add( getItem( program, split[0], split[1], split[2] ) );
         }
 
-        return items;
+        return queryItem;
     }
 
     private Map<String, String> getUidNameMap( EventQueryParams params )
@@ -497,7 +496,7 @@
 
     private String getSortItem( String item, Program program )
     {
-        if ( !SORTABLE_ITEMS.contains( item.toLowerCase() ) && getItem( program, item, null, null ) == null )
+        if ( !SORTABLE_ITEMS.contains( item.toLowerCase() ) && getQueryItem( program, item ) == null )
         {
             throw new IllegalQueryException( "Descending sort item is invalid: " + item );
         }
@@ -507,20 +506,20 @@
         return item;
     }
 
-    private QueryItem getItem( Program program, String item, String operator, String filter )
+    private QueryItem getQueryItem( Program program, String item )
     {
         DataElement de = dataElementService.getDataElement( item );
 
         if ( de != null && program.getAllDataElements().contains( de ) )
         {
-            return new QueryItem( de, operator, filter, de.isNumericType() );
+            return new QueryItem( de, de.isNumericType() );
         }
 
         TrackedEntityAttribute at = attributeService.getTrackedEntityAttribute( item );
 
         if ( at != null && program.getTrackedEntityAttributes().contains( at ) )
         {
-            return new QueryItem( at, operator, filter, at.isNumericType() );
+            return new QueryItem( at, at.isNumericType() );
         }
 
         throw new IllegalQueryException( "Item identifier does not reference any item part of the program: " + item );

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	2014-04-20 20:56:55 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	2014-04-21 11:05:22 +0000
@@ -50,6 +50,7 @@
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.NameableObject;
+import org.hisp.dhis.common.QueryFilter;
 import org.hisp.dhis.common.QueryItem;
 import org.hisp.dhis.jdbc.StatementBuilder;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -386,15 +387,21 @@
         {
             if ( item.hasFilter() )
             {
-                sql += "and " + getColumn( item ) + " " + item.getSqlOperator() + " " + getSqlFilter( item ) + " ";
+                for ( QueryFilter filter : item.getFilters() )
+                {
+                    sql += "and " + getColumn( item ) + " " + filter.getSqlOperator() + " " + getSqlFilter( filter, item.isNumeric() ) + " ";
+                }
             }
         }
         
-        for ( QueryItem filter : params.getItemFilters() )
+        for ( QueryItem item : params.getItemFilters() )
         {
-            if ( filter.hasFilter() )
+            if ( item.hasFilter() )
             {
-                sql += "and " + getColumn( filter ) + " " + filter.getSqlOperator() + " " + getSqlFilter( filter ) + " ";
+                for ( QueryFilter filter : item.getFilters() )
+                {
+                    sql += "and " + getColumn( item ) + " " + filter.getSqlOperator() + " " + getSqlFilter( filter, item.isNumeric() ) + " ";
+                }
             }
         }
         
@@ -419,13 +426,13 @@
     /**
      * Returns the filter value for the given query item.
      */
-    private String getSqlFilter( QueryItem item )
+    private String getSqlFilter( QueryFilter filter, boolean numeric )
     {
-        String encodedFilter = statementBuilder.encode( item.getFilter(), false );
-        
-        String sqlFilter = item.getSqlFilter( encodedFilter );
-        
-        return item.isNumeric() ? sqlFilter : sqlFilter.toLowerCase();
+        String encodedFilter = statementBuilder.encode( filter.getFilter(), false );
+        
+        String sqlFilter = filter.getSqlFilter( encodedFilter );
+        
+        return numeric ? sqlFilter : sqlFilter.toLowerCase();
     }
 
     /**

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-04-14 13:47:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2014-04-21 11:05:22 +0000
@@ -704,6 +704,9 @@
         executeSql( "UPDATE attribute SET userattribute=false WHERE userattribute IS NULL" );
         executeSql( "UPDATE attribute SET usergroupattribute=false WHERE usergroupattribute IS NULL" );
         executeSql( "UPDATE attribute SET datasetattribute=false WHERE datasetattribute IS NULL" );
+        
+        executeSql( "ALTER TABLE trackedentityattributedimension DROP COLUMN operator" );
+        executeSql( "ALTER TABLE trackedentitydataelementdimension DROP COLUMN operator" );
 
         // update attribute.code, set to null if code=''
         executeSql( "UPDATE attribute SET code=NULL WHERE code=''" );
@@ -720,8 +723,6 @@
         log.info( "Tables updated" );
     }
 
-  
-
     private void upgradeDataValuesWithAttributeOptionCombo()
     {
         final String sql = statementBuilder.getNumberOfColumnsInPrimaryKey( "datavalue" );

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java	2014-04-18 14:01:25 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/DefaultTrackedEntityInstanceService.java	2014-04-21 11:05:22 +0000
@@ -436,7 +436,14 @@
             throw new IllegalQueryException( "Attribute does not exist: " + item );
         }
         
-        return new QueryItem( at, operator, filter, at.isNumericType() );
+        if ( operator != null && filter != null )
+        {
+            return new QueryItem( at, operator, filter, at.isNumericType() );
+        }
+        else
+        {
+            return new QueryItem( at, at.isNumericType() );
+        }        
     }
     
     @Override

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java	2014-04-18 18:17:51 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/trackedentity/hibernate/HibernateTrackedEntityInstanceStore.java	2014-04-21 11:05:22 +0000
@@ -66,6 +66,7 @@
 import org.hibernate.criterion.Restrictions;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.common.OrganisationUnitSelectionMode;
+import org.hisp.dhis.common.QueryFilter;
 import org.hisp.dhis.common.QueryItem;
 import org.hisp.dhis.common.SetMap;
 import org.hisp.dhis.common.hibernate.HibernateIdentifiableObjectStore;
@@ -257,14 +258,17 @@
                 "trackedentityattributevalue as " + col + " " + "on " + col + ".trackedentityinstanceid = tei.trackedentityinstanceid " + 
                 "and " + col + ".trackedentityattributeid = " + item.getItem().getId() + " ";
 
-            final String filter = statementBuilder.encode( item.getFilter(), false );
-
             if ( !params.isOrQuery() && item.hasFilter() )
             {
-                final String queryCol = item.isNumeric() ? (col + ".value") : "lower(" + col + ".value)";
-
-                sql += "and " + queryCol + " " + item.getSqlOperator() + " "
-                    + StringUtils.lowerCase( item.getSqlFilter( filter ) ) + " ";
+                for ( QueryFilter filter : item.getFilters() )
+                {
+                    final String encodedFilter = statementBuilder.encode( filter.getFilter(), false );
+    
+                    final String queryCol = item.isNumeric() ? (col + ".value") : "lower(" + col + ".value)";
+    
+                    sql += "and " + queryCol + " " + filter.getSqlOperator() + " "
+                        + StringUtils.lowerCase( filter.getSqlFilter( encodedFilter ) ) + " ";
+                }
             }
         }
 

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAttributeDimension.hbm.xml'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAttributeDimension.hbm.xml	2014-03-26 21:55:22 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityAttributeDimension.hbm.xml	2014-04-21 11:05:22 +0000
@@ -12,8 +12,6 @@
 
     <many-to-one name="attribute" class="org.hisp.dhis.trackedentity.TrackedEntityAttribute" 
         column="trackedentityattributeid" foreign-key="fk_attributedimension_attributeid" />
-
-    <property name="operator" />
     
     <property name="filter" />
 

=== modified file 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityDataElementDimension.hbm.xml'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityDataElementDimension.hbm.xml	2014-03-26 21:55:22 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/trackedentity/hibernate/TrackedEntityDataElementDimension.hbm.xml	2014-04-21 11:05:22 +0000
@@ -13,8 +13,6 @@
     <many-to-one name="dataElement" class="org.hisp.dhis.dataelement.DataElement" 
         column="dataelementid" foreign-key="fk_dataelementdimension_dataelementid" />
 
-    <property name="operator" />
-    
     <property name="filter" />
 
   </class>