← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18294: Event analytics. Added support for value dimesion and aggregation type.

 

------------------------------------------------------------
revno: 18294
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2015-02-17 17:50:34 +0100
message:
  Event analytics. Added support for value dimesion and aggregation type.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/analytics/AggregationType.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.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/DefaultEventQueryPlanner.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-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java
  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/EventAnalyticsController.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/analytics/AggregationType.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/analytics/AggregationType.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/analytics/AggregationType.java	2015-02-17 16:50:34 +0000
@@ -38,7 +38,8 @@
     AVERAGE_SUM_INT_DISAGGREGATION( "avg_sum_int_disaggregation" ), // Sum in organisation unit hierarchy
     AVERAGE_INT( "avg_int" ),
     AVERAGE_INT_DISAGGREGATION( "avg_int_disaggregation" ),
-    AVERAGE_BOOL( "avg" ), 
+    AVERAGE_BOOL( "avg" ),
+    AVERAGE( "average" ), // General average
     COUNT( "count" ), 
     STDDEV( "stddev" ), 
     VARIANCE( "variance" ),

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java	2015-02-16 14:25:40 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java	2015-02-17 16:50:34 +0000
@@ -28,12 +28,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonView;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
-import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
 
 import org.hisp.dhis.analytics.EventOutputType;
 import org.hisp.dhis.chart.BaseChart;
@@ -54,11 +51,13 @@
 import org.hisp.dhis.program.Program;
 import org.hisp.dhis.program.ProgramStage;
 import org.hisp.dhis.user.User;
-import org.hisp.dhis.analytics.EventOutputType;
 
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
 
 /**
  * @author Jan Henrik Overland

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java	2015-02-03 14:33:39 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java	2015-02-17 16:50:34 +0000
@@ -636,6 +636,14 @@
     {
         return this.aggregationType != null && this.aggregationType.equals( aggregationType );
     }
+    
+    /**
+     * Indicates whether an aggregation type is specified.
+     */
+    public boolean hasAggregationType()
+    {
+        return this.aggregationType != null;
+    }
 
     /**
      * Creates a mapping between the data periods, based on the data period type

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java	2015-02-15 17:50:12 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java	2015-02-17 16:50:34 +0000
@@ -30,6 +30,7 @@
 
 import java.util.Set;
 
+import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.EventOutputType;
 import org.hisp.dhis.analytics.SortOrder;
 import org.hisp.dhis.common.AnalyticalObject;
@@ -51,13 +52,47 @@
 
     /**
      * Used for aggregate query.
+     * 
+     * @param program the program identifier.
+     * @param stage the program stage identifier.
+     * @param startDate the start date.
+     * @param endDate the end date.
+     * @param dimension the set of dimensions.
+     * @param filter the set of filters.
+     * @param value the value dimension identifier.
+     * @param aggregationType the aggregation type for the value dimension.
+     * @param skipMeta whether to skip meta-data in response.
+     * @param hierarchyMeta whether to include hierarchy meta-data in the response.
+     * @param sortOrder the sort order of the aggregate values.
+     * @param limit the max limit of records to return.
+     * @param outputType the event output type.
+     * @param displayProperty the display property to use for meta-data.
+     * @param format the i18n format.
      */
     EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, 
-        Set<String> dimension, Set<String> filter, boolean skipMeta, boolean hierarchyMeta, SortOrder sortOrder, 
-        Integer limit, EventOutputType outputType, DisplayProperty displayProperty, I18nFormat format );
+        Set<String> dimension, Set<String> filter, String value, AggregationType aggregationType, 
+        boolean skipMeta, boolean hierarchyMeta, SortOrder sortOrder, Integer limit, 
+        EventOutputType outputType, DisplayProperty displayProperty, I18nFormat format );
 
     /**
      * Used for event query.
+     * 
+     * @param program the program identifier.
+     * @param stage the program stage identifier.
+     * @param startDate the start date.
+     * @param endDate the end date.
+     * @param dimension the set of dimensions.
+     * @param filter the set of filters.
+     * @param ouMode the organisation unit mode.
+     * @param asc the dimensions to be sorted ascending.
+     * @param desc the dimensions to be sorted descending.
+     * @param skipMeta whether to skip meta-data in response.
+     * @param hierarchyMeta whether to include hierarchy meta-data in the response.
+     * @param coordinatesOnly whether to only return events which have coordinates.
+     * @param displayProperty the display property to use for meta-data.
+     * @param page the page number.
+     * @param pageSize the page size.
+     * @param format the i18n format.
      */
     EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set<String> dimension, Set<String> filter, 
         String ouMode, Set<String> asc, Set<String> desc, boolean skipMeta, boolean hierarchyMeta, boolean coordinatesOnly, 

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java	2015-02-15 17:50:12 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java	2015-02-17 16:50:34 +0000
@@ -66,7 +66,9 @@
     private List<QueryItem> items = new ArrayList<>();
     
     private List<QueryItem> itemFilters = new ArrayList<>();
-
+    
+    private NameableObject value;
+    
     private List<String> asc = new ArrayList<>();
     
     private List<String> desc = new ArrayList<>();
@@ -108,8 +110,8 @@
 
         params.dimensions = new ArrayList<>( this.dimensions );
         params.filters = new ArrayList<>( this.filters );
+        params.displayProperty = this.displayProperty;
         params.aggregationType = this.aggregationType;
-        params.displayProperty = this.displayProperty;
 
         params.partitions = new Partitions( this.partitions );
         params.periodType = this.periodType;
@@ -120,6 +122,7 @@
         params.endDate = this.endDate;
         params.items = new ArrayList<>( this.items );
         params.itemFilters = new ArrayList<>( this.itemFilters );
+        params.value = this.value;
         params.asc = new ArrayList<>( this.asc );
         params.desc = new ArrayList<>( this.desc );
         params.organisationUnitMode = this.organisationUnitMode;
@@ -187,6 +190,27 @@
         return duplicates;
     }
     
+    /**
+     * Get NameableObjects part of items and item filters.
+     * @return
+     */
+    public Set<NameableObject> getNameableObjectItems()
+    {
+        Set<NameableObject> objects = new HashSet<NameableObject>();
+        
+        for ( QueryItem item : items )
+        {
+            objects.add( item.getItem() );
+        }
+        
+        for ( QueryItem item : itemFilters )
+        {
+            objects.add( item.getItem() );
+        }
+        
+        return objects;
+    }
+    
     public boolean isOrganisationUnitMode( String mode )
     {
         return organisationUnitMode != null && organisationUnitMode.equalsIgnoreCase( mode );
@@ -245,6 +269,11 @@
         return limit != null && limit > 0;
     }
     
+    public boolean hasValueDimension()
+    {
+        return value != null;
+    }
+        
     /**
      * Indicates whether the program of this query requires registration of
      * tracked entity instances.
@@ -270,8 +299,10 @@
             "Stage: " + programStage + ", " +
             "Start date: " + startDate + ", " +
             "End date: " + endDate + ", " +
-            "Items " + items + ", " +
+            "Items: " + items + ", " +
             "Item filters: " + itemFilters + ", " +
+            "Value: " + value + ", " +
+            "Aggregation type: " + aggregationType + ", " +
             "Dimensions: " + dimensions + ", " +
             "Filters: " + filters + "]";
     }
@@ -340,6 +371,16 @@
         this.itemFilters = itemFilters;
     }
 
+    public NameableObject getValue()
+    {
+        return value;
+    }
+
+    public void setValue( NameableObject value )
+    {
+        this.value = value;
+    }
+
     public List<String> getAsc()
     {
         return asc;

=== 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	2015-02-17 15:46:42 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java	2015-02-17 16:50:34 +0000
@@ -49,6 +49,7 @@
 import java.util.Map;
 import java.util.Set;
 
+import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.AnalyticsSecurityManager;
 import org.hisp.dhis.analytics.AnalyticsService;
 import org.hisp.dhis.analytics.EventOutputType;
@@ -343,12 +344,14 @@
 
     @Override
     public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate,
-        Set<String> dimension, Set<String> filter, boolean skipMeta, boolean hierarchyMeta, SortOrder sortOrder, 
+        Set<String> dimension, Set<String> filter, String value, AggregationType aggregationType, boolean skipMeta, boolean hierarchyMeta, SortOrder sortOrder, 
         Integer limit, EventOutputType outputType, DisplayProperty displayProperty, I18nFormat format )
     {
         EventQueryParams params = getFromUrl( program, stage, startDate, endDate, dimension, filter, null, null, null,
             skipMeta, hierarchyMeta, false, displayProperty, null, null, format );
-        
+                
+        params.setValue( getValueDimension( value ) );
+        params.setAggregationType( aggregationType );
         params.setSortOrder( sortOrder );
         params.setLimit( limit );
         params.setOutputType( MoreObjects.firstNonNull( outputType, EventOutputType.EVENT ) );
@@ -627,7 +630,6 @@
                 {
                     map.putAll( IdentifiableObjectUtils.getUidNameMap( objects ) );
                 }
-
             }
         }
 
@@ -662,6 +664,30 @@
             return new QueryItem( at, at.getValueType(), at.hasOptionSet() ? at.getOptionSet().getUid() : null );
         }
 
-        throw new IllegalQueryException( "Item identifier does not reference any item part of the program: " + item );
+        throw new IllegalQueryException( "Item identifier does not reference any data element or attribute part of the program: " + item );
+    }
+    
+    private NameableObject getValueDimension( String value )
+    {
+        if ( value == null )
+        {
+            return null;
+        }
+        
+        DataElement de = dataElementService.getDataElement( value );
+        
+        if ( de != null && de.isNumericType() )
+        {
+            return de;
+        }
+        
+        TrackedEntityAttribute at = attributeService.getTrackedEntityAttribute( value );
+        
+        if ( at != null && at.isNumericType() )
+        {
+            return at;
+        }
+        
+        throw new IllegalQueryException( "Value identifier does not reference any data element or attribute which are numeric type and part of the program: " + value );        
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventQueryPlanner.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventQueryPlanner.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventQueryPlanner.java	2015-02-17 16:50:34 +0000
@@ -108,6 +108,11 @@
             violation = "Query items cannot be specified more than once: " + params.getDuplicateQueryItems();
         }
         
+        if ( params.hasValueDimension() && params.getNameableObjectItems().contains( params.getValue() ) )
+        {
+            violation = "Value dimension cannot also be specified as an item or item filter";
+        }
+        
         if ( !params.hasPeriods() && ( params.getStartDate() == null || params.getEndDate() == null ) )
         {
             violation = "Start and end date or at least one period must be specified";

=== 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	2015-02-15 17:50:12 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java	2015-02-17 16:50:34 +0000
@@ -28,6 +28,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static org.hisp.dhis.analytics.AggregationType.COUNT;
+import static org.hisp.dhis.analytics.AggregationType.MAX;
+import static org.hisp.dhis.analytics.AggregationType.MIN;
+import static org.hisp.dhis.analytics.AggregationType.STDDEV;
+import static org.hisp.dhis.analytics.AggregationType.SUM;
+import static org.hisp.dhis.analytics.AggregationType.VARIANCE;
 import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
 import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
 import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
@@ -85,7 +91,7 @@
     @Override
     public Grid getAggregatedEventData( EventQueryParams params, Grid grid, int maxLimit )
     {
-        String countClause = getCountClause( params );
+        String countClause = getAggregateClause( params );
         
         String sql = "select " + countClause + " as value," + getSelectColumns( params ) + " ";
 
@@ -150,12 +156,10 @@
     {
         SqlRowSet rowSet = jdbcTemplate.queryForRowSet( sql );
 
-        log.debug( "Analytics event aggregate SQL: " + sql );
+        log.info( "Analytics event aggregate SQL: " + sql );
         
         while ( rowSet.next() )
-        {
-            int value = rowSet.getInt( "value" );
-            
+        {            
             grid.addRow();
             
             for ( DimensionalObject dimension : params.getDimensions() )
@@ -170,7 +174,16 @@
                 grid.addValue( itemValue );
             }
             
-            grid.addValue( value );
+            if ( params.hasValueDimension() )
+            {
+                double value = rowSet.getDouble( "value" );
+                grid.addValue( value );
+            }
+            else
+            {
+                int value = rowSet.getInt( "value" );
+                grid.addValue( value );
+            }
         }
     }
     
@@ -309,21 +322,57 @@
     /**
      * Returns the count clause based on the output type.
      */
-    private String getCountClause( EventQueryParams params )
+    private String getAggregateClause( EventQueryParams params )
     {
         EventOutputType outputType = params.getOutputType();
         
-        if ( EventOutputType.TRACKED_ENTITY_INSTANCE.equals( outputType ) && params.isProgramRegistration() )
-        {
-            return "count(distinct tei)";
-        }
-        else if ( EventOutputType.ENROLLMENT.equals( outputType ) )
-        {
-            return "count(distinct pi)";
-        }
-        else // EVENT
-        {
-            return "count(psi)";
+        if ( params.hasValueDimension() ) // && isNumeric
+        {
+            String column = statementBuilder.columnQuote( params.getValue().getUid() );
+            
+            if ( params.isAggregationType( SUM ) )
+            {
+                return "sum(" + column + ")";
+            }
+            else if ( params.isAggregationType( COUNT ) )
+            {
+                return "count(" + column + ")";
+            }
+            else if ( params.isAggregationType( STDDEV ) )
+            {
+                return "stddev(" + column + ")";
+            }
+            else if ( params.isAggregationType( VARIANCE ) )
+            {
+                return "variance(" + column + ")";
+            }
+            else if ( params.isAggregationType( MIN ) )
+            {
+                return "min(" + column + ")";
+            }
+            else if ( params.isAggregationType( MAX ) )
+            {
+                return "max(" + column + ")";
+            }
+            else // AVERAGE
+            {
+                return "avg(" + column + ")";
+            }
+        }
+        else
+        {
+            if ( EventOutputType.TRACKED_ENTITY_INSTANCE.equals( outputType ) && params.isProgramRegistration() )
+            {
+                return "count(distinct tei)";
+            }
+            else if ( EventOutputType.ENROLLMENT.equals( outputType ) )
+            {
+                return "count(distinct pi)";
+            }
+            else // EVENT
+            {
+                return "count(psi)";
+            }
         }
     }
     

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java	2015-02-15 17:50:12 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java	2015-02-17 16:50:34 +0000
@@ -37,6 +37,7 @@
 import java.util.Set;
 
 import org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.event.EventAnalyticsService;
 import org.hisp.dhis.analytics.event.EventQueryParams;
 import org.hisp.dhis.common.AnalyticsType;
@@ -157,13 +158,34 @@
         filterParams.add( "pe:201401;201402" );
         
         EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null, 
-            null, null, dimensionParams, filterParams, false, false, null, null, null, null, null );
+            null, null, dimensionParams, filterParams, null, null, false, false, null, null, null, null, null );
         
         assertEquals( prA, params.getProgram() );
         assertEquals( 1, params.getOrganisationUnits().size() );
         assertEquals( 1, params.getItems().size() );
         assertEquals( 2, params.getFilterPeriods().size() );
     }
+
+    @Test
+    public void testGetFromUrlB()
+    {
+        Set<String> dimensionParams = new HashSet<>();
+        dimensionParams.add( "ou:" + ouA.getUid() + ";" + ouB.getId() );
+        dimensionParams.add( atA.getUid() + ":LE:5" );
+        
+        Set<String> filterParams = new HashSet<>();
+        filterParams.add( "pe:201401" );
+        
+        EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null, 
+            null, null, dimensionParams, filterParams, deA.getUid(), AggregationType.AVERAGE, false, false, null, null, null, null, null );
+        
+        assertEquals( prA, params.getProgram() );
+        assertEquals( 1, params.getOrganisationUnits().size() );
+        assertEquals( 1, params.getItems().size() );
+        assertEquals( 1, params.getFilterPeriods().size() );
+        assertEquals( deA, params.getValue() );
+        assertEquals( AggregationType.AVERAGE, params.getAggregationType() );
+    }
     
     @Test
     public void testGetFromAnalyticalObjectA()

=== 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-17 07:22:47 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java	2015-02-17 16:50:34 +0000
@@ -28,10 +28,19 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-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 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 org.hisp.dhis.acl.AclService;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.IdentifiableObject;
@@ -78,17 +87,10 @@
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-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;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java	2015-02-15 17:50:12 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java	2015-02-17 16:50:34 +0000
@@ -35,6 +35,7 @@
 
 import javax.servlet.http.HttpServletResponse;
 
+import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.EventOutputType;
 import org.hisp.dhis.analytics.SortOrder;
 import org.hisp.dhis.analytics.event.EventAnalyticsService;
@@ -84,6 +85,8 @@
         @RequestParam( required = false ) String endDate,
         @RequestParam Set<String> dimension,
         @RequestParam( required = false ) Set<String> filter,
+        @RequestParam( required = false ) String value,
+        @RequestParam( required = false ) AggregationType aggregationType,
         @RequestParam( required = false ) boolean skipMeta,
         @RequestParam( required = false ) boolean hierarchyMeta,
         @RequestParam( required = false ) Integer limit,
@@ -94,7 +97,7 @@
         HttpServletResponse response ) throws Exception
     {
         EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
-            skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
+            value, aggregationType, skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING );
         Grid grid = analyticsService.getAggregatedEventData( params );
@@ -111,6 +114,8 @@
         @RequestParam( required = false ) String endDate,
         @RequestParam Set<String> dimension,
         @RequestParam( required = false ) Set<String> filter,
+        @RequestParam( required = false ) String value,
+        @RequestParam( required = false ) AggregationType aggregationType,
         @RequestParam( required = false ) boolean skipMeta,
         @RequestParam( required = false ) boolean hierarchyMeta,
         @RequestParam( required = false ) Integer limit,
@@ -121,7 +126,7 @@
         HttpServletResponse response ) throws Exception
     {
         EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
-            skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
+            value, aggregationType, skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.xml", false );
         Grid grid = analyticsService.getAggregatedEventData( params );
@@ -136,6 +141,8 @@
         @RequestParam( required = false ) String endDate,
         @RequestParam Set<String> dimension,
         @RequestParam( required = false ) Set<String> filter,
+        @RequestParam( required = false ) String value,
+        @RequestParam( required = false ) AggregationType aggregationType,
         @RequestParam( required = false ) boolean skipMeta,
         @RequestParam( required = false ) boolean hierarchyMeta,
         @RequestParam( required = false ) Integer limit,
@@ -146,7 +153,7 @@
         HttpServletResponse response ) throws Exception
     {
         EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
-            skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
+            value, aggregationType, skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_EXCEL, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.xls", true );
         Grid grid = analyticsService.getAggregatedEventData( params );
@@ -161,6 +168,8 @@
         @RequestParam( required = false ) String endDate,
         @RequestParam Set<String> dimension,
         @RequestParam( required = false ) Set<String> filter,
+        @RequestParam( required = false ) String value,
+        @RequestParam( required = false ) AggregationType aggregationType,
         @RequestParam( required = false ) boolean skipMeta,
         @RequestParam( required = false ) boolean hierarchyMeta,
         @RequestParam( required = false ) Integer limit,
@@ -171,7 +180,7 @@
         HttpServletResponse response ) throws Exception
     {
         EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
-            skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
+            value, aggregationType, skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_CSV, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.csv", true );
         Grid grid = analyticsService.getAggregatedEventData( params );
@@ -186,6 +195,8 @@
         @RequestParam( required = false ) String endDate,
         @RequestParam Set<String> dimension,
         @RequestParam( required = false ) Set<String> filter,
+        @RequestParam( required = false ) String value,
+        @RequestParam( required = false ) AggregationType aggregationType,
         @RequestParam( required = false ) boolean skipMeta,
         @RequestParam( required = false ) boolean hierarchyMeta,
         @RequestParam( required = false ) Integer limit,
@@ -196,7 +207,7 @@
         HttpServletResponse response ) throws Exception
     {
         EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter,
-            skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
+            value, aggregationType, skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() );
 
         contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.html", false );
         Grid grid = analyticsService.getAggregatedEventData( params );