=== 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-17 21:46:41 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java 2015-03-05 15:38:58 +0000 @@ -67,13 +67,14 @@ * @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 collapseDataDimensions collapse data dimensions into a single dimension. * @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 dimension, Set filter, String value, AggregationType aggregationType, boolean skipMeta, boolean skipRounding, boolean hierarchyMeta, SortOrder sortOrder, Integer limit, - EventOutputType outputType, DisplayProperty displayProperty, I18nFormat format ); + EventOutputType outputType, boolean collapseDataDimensions, DisplayProperty displayProperty, I18nFormat format ); /** * Used for event query. === 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-03-03 10:20:32 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java 2015-03-05 15:38:58 +0000 @@ -87,6 +87,8 @@ private EventOutputType outputType; + private boolean collapseDataDimensions; + private boolean coordinatesOnly; // ------------------------------------------------------------------------- @@ -134,6 +136,7 @@ params.sortOrder = this.sortOrder; params.limit = this.limit; params.outputType = this.outputType; + params.collapseDataDimensions = this.collapseDataDimensions; params.coordinatesOnly = this.coordinatesOnly; params.periodType = this.periodType; @@ -489,6 +492,16 @@ this.outputType = outputType; } + public boolean isCollapseDataDimensions() + { + return collapseDataDimensions; + } + + public void setCollapseDataDimensions( boolean collapseDataDimensions ) + { + this.collapseDataDimensions = collapseDataDimensions; + } + public boolean isCoordinatesOnly() { return coordinatesOnly; === 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-03-03 16:54:51 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java 2015-03-05 15:38:58 +0000 @@ -53,6 +53,7 @@ import org.hisp.dhis.analytics.AggregationType; import org.hisp.dhis.analytics.AnalyticsSecurityManager; import org.hisp.dhis.analytics.AnalyticsService; +import org.hisp.dhis.analytics.DataQueryParams; import org.hisp.dhis.analytics.EventOutputType; import org.hisp.dhis.analytics.SortOrder; import org.hisp.dhis.analytics.event.EventAnalyticsManager; @@ -179,11 +180,18 @@ grid.addHeader( new GridHeader( dimension.getDimension(), dimension.getDisplayName(), String.class.getName(), false, true ) ); } - for ( QueryItem item : params.getItems() ) - { - String legendSet = item.hasLegendSet() ? item.getLegendSet().getUid() : null; - - grid.addHeader( new GridHeader( item.getItem().getUid(), item.getItem().getName(), item.getTypeAsString(), false, true, item.getOptionSetUid(), legendSet ) ); + if ( params.isCollapseDataDimensions() ) + { + grid.addHeader( new GridHeader( DimensionalObject.DATA_X_DIM_ID, DataQueryParams.DISPLAY_NAME_DATA_X, String.class.getName(), false, true ) ); + } + else + { + for ( QueryItem item : params.getItems() ) + { + String legendSet = item.hasLegendSet() ? item.getLegendSet().getUid() : null; + + grid.addHeader( new GridHeader( item.getItem().getUid(), item.getItem().getName(), item.getTypeAsString(), false, true, item.getOptionSetUid(), legendSet ) ); + } } grid.addHeader( new GridHeader( "value", "Value", Double.class.getName(), false, false ) ); @@ -353,7 +361,7 @@ @Override public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set dimension, Set filter, String value, AggregationType aggregationType, boolean skipMeta, boolean skipRounding, boolean hierarchyMeta, - SortOrder sortOrder, Integer limit, EventOutputType outputType, DisplayProperty displayProperty, I18nFormat format ) + SortOrder sortOrder, Integer limit, EventOutputType outputType, boolean collapseDataDimensions, DisplayProperty displayProperty, I18nFormat format ) { EventQueryParams params = getFromUrl( program, stage, startDate, endDate, dimension, filter, null, null, null, skipMeta, hierarchyMeta, false, displayProperty, null, null, format ); @@ -364,6 +372,7 @@ params.setSortOrder( sortOrder ); params.setLimit( limit ); params.setOutputType( MoreObjects.firstNonNull( outputType, EventOutputType.EVENT ) ); + params.setCollapseDataDimensions( collapseDataDimensions ); params.setAggregate( true ); return params; === 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-02-24 13:57:25 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventQueryPlanner.java 2015-03-05 15:38:58 +0000 @@ -47,6 +47,7 @@ import org.hisp.dhis.common.IllegalQueryException; import org.hisp.dhis.common.MaintenanceModeException; import org.hisp.dhis.common.NameableObject; +import org.hisp.dhis.common.QueryItem; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.organisationunit.OrganisationUnitService; import org.hisp.dhis.period.Period; @@ -166,7 +167,12 @@ for ( EventQueryParams byOrgUnitLevel : groupedByOrgUnitLevel ) { - queries.addAll( convert( queryPlanner.groupByPeriodType( byOrgUnitLevel ) ) ); + List groupedByPeriodType = convert( queryPlanner.groupByPeriodType( byOrgUnitLevel ) ); + + for ( EventQueryParams byPeriodType : groupedByPeriodType ) + { + queries.addAll( groupByItems( byPeriodType ) ); + } } } @@ -245,6 +251,32 @@ return convert( queryPlanner.groupByPartition( params, EVENT_ANALYTICS_TABLE_NAME, tableSuffix ) ); } } + + /** + * Group by items if query items are to be collapsed in order to aggregate + * each item individually. + */ + private List groupByItems( EventQueryParams params ) + { + List queries = new ArrayList<>(); + + if ( params.isCollapseDataDimensions() && params.getItems() != null && !params.getItems().isEmpty() ) + { + for ( QueryItem item : params.getItems() ) + { + EventQueryParams query = params.instance(); + query.getItems().clear(); + query.getItems().add( item ); + queries.add( query ); + } + } + else + { + queries.add( params.instance() ); + } + + return queries; + } private static List convert( List params ) { === 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-27 18:45:42 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/event/data/EventAnalyticsServiceTest.java 2015-03-05 15:38:58 +0000 @@ -181,7 +181,7 @@ filterParams.add( "pe:201401;201402" ); EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null, - null, null, dimensionParams, filterParams, null, null, false, false, false, null, null, null, null, null ); + null, null, dimensionParams, filterParams, null, null, false, false, false, null, null, null, false, null, null ); assertEquals( prA, params.getProgram() ); assertEquals( 1, params.getOrganisationUnits().size() ); @@ -200,7 +200,7 @@ filterParams.add( "pe:201401" ); EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null, - null, null, dimensionParams, filterParams, deA.getUid(), AggregationType.AVERAGE, false, false, false, null, null, null, null, null ); + null, null, dimensionParams, filterParams, deA.getUid(), AggregationType.AVERAGE, false, false, false, null, null, null, false, null, null ); assertEquals( prA, params.getProgram() ); assertEquals( 1, params.getOrganisationUnits().size() ); @@ -261,6 +261,31 @@ } @Test + public void testGetFromAnalyticalObjectC() + { + EventChart chart = new EventChart(); + chart.setProgram( prA ); + + chart.getColumnDimensions().add( deA.getUid() ); + chart.getColumnDimensions().add( atA.getUid() ); + chart.getRowDimensions().add( DimensionalObject.ORGUNIT_DIM_ID ); + chart.getFilterDimensions().add( DimensionalObject.PERIOD_DIM_ID ); + + chart.getDataElementDimensions().add( new TrackedEntityDataElementDimension( deA, null, "GT:2000" ) ); + chart.getAttributeDimensions().add( new TrackedEntityAttributeDimension( atA, null, "LE:5" ) ); + chart.getPeriods().add( peA ); + chart.getPeriods().add( peB ); + chart.getOrganisationUnits().add( ouA ); + + EventQueryParams params = analyticsService.getFromAnalyticalObject( chart, null ); + + assertNotNull( params ); + assertEquals( 2, params.getItems().size() ); + assertEquals( 1, params.getOrganisationUnits().size() ); + assertEquals( 2, params.getFilterPeriods().size() ); + } + + @Test public void testSetItemsForDimensionFilters() { TrackedEntityAttribute tea = new TrackedEntityAttribute(); @@ -309,7 +334,7 @@ filterParams.add( atA.getUid() + ":LE:5" ); EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null, - null, null, dimensionParams, filterParams, null, null, false, false, false, null, null, null, null, null ); + null, null, dimensionParams, filterParams, null, null, false, false, false, null, null, null, false, null, null ); assertEquals( prA, params.getProgram() ); assertEquals( 1, params.getItems().size() ); === 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-17 21:46:41 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java 2015-03-05 15:38:58 +0000 @@ -92,13 +92,14 @@ @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, @RequestParam( required = false ) EventOutputType outputType, + @RequestParam( required = false ) boolean collapseDataDimensions, @RequestParam( required = false ) SortOrder sortOrder, @RequestParam( required = false ) DisplayProperty displayProperty, Model model, HttpServletResponse response ) throws Exception { EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter, - value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() ); + value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, collapseDataDimensions, displayProperty, i18nManager.getI18nFormat() ); contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING ); Grid grid = analyticsService.getAggregatedEventData( params ); @@ -122,13 +123,14 @@ @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, @RequestParam( required = false ) EventOutputType outputType, + @RequestParam( required = false ) boolean collapseDataDimensions, @RequestParam( required = false ) SortOrder sortOrder, @RequestParam( required = false ) DisplayProperty displayProperty, Model model, HttpServletResponse response ) throws Exception { EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter, - value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() ); + value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, collapseDataDimensions, displayProperty, i18nManager.getI18nFormat() ); contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.xml", false ); Grid grid = analyticsService.getAggregatedEventData( params ); @@ -150,13 +152,14 @@ @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, @RequestParam( required = false ) EventOutputType outputType, + @RequestParam( required = false ) boolean collapseDataDimensions, @RequestParam( required = false ) SortOrder sortOrder, @RequestParam( required = false ) DisplayProperty displayProperty, Model model, HttpServletResponse response ) throws Exception { EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter, - value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() ); + value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, collapseDataDimensions, displayProperty, i18nManager.getI18nFormat() ); contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_EXCEL, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.xls", true ); Grid grid = analyticsService.getAggregatedEventData( params ); @@ -178,13 +181,14 @@ @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, @RequestParam( required = false ) EventOutputType outputType, + @RequestParam( required = false ) boolean collapseDataDimensions, @RequestParam( required = false ) SortOrder sortOrder, @RequestParam( required = false ) DisplayProperty displayProperty, Model model, HttpServletResponse response ) throws Exception { EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter, - value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() ); + value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, collapseDataDimensions, displayProperty, i18nManager.getI18nFormat() ); contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_CSV, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.csv", true ); Grid grid = analyticsService.getAggregatedEventData( params ); @@ -206,13 +210,14 @@ @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, @RequestParam( required = false ) EventOutputType outputType, + @RequestParam( required = false ) boolean collapseDataDimensions, @RequestParam( required = false ) SortOrder sortOrder, @RequestParam( required = false ) DisplayProperty displayProperty, Model model, HttpServletResponse response ) throws Exception { EventQueryParams params = analyticsService.getFromUrl( program, stage, startDate, endDate, dimension, filter, - value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() ); + value, aggregationType, skipMeta, skipRounding, hierarchyMeta, sortOrder, limit, outputType, collapseDataDimensions, displayProperty, i18nManager.getI18nFormat() ); contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING, "events.html", false ); Grid grid = analyticsService.getAggregatedEventData( params );