=== modified file 'dhis-2/dhis-services/dhis-service-analytics/pom.xml' --- dhis-2/dhis-services/dhis-service-analytics/pom.xml 2015-01-23 14:07:46 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/pom.xml 2015-02-15 17:50:12 +0000 @@ -52,6 +52,10 @@ org.amplecode quick + + com.google.guava + guava + === added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/EventOutputType.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/EventOutputType.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/EventOutputType.java 2015-02-15 17:50:12 +0000 @@ -0,0 +1,37 @@ +package org.hisp.dhis.analytics; + +/* + * Copyright (c) 2004-2015, University of Oslo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * Neither the name of the HISP project nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @author Lars Helge Overland + */ +public enum EventOutputType +{ + EVENT, ENROLLMENT, TRACKED_ENTITY_INSTANCE; +} === 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-01-17 07:41:26 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventAnalyticsService.java 2015-02-15 17:50:12 +0000 @@ -30,6 +30,7 @@ import java.util.Set; +import org.hisp.dhis.analytics.EventOutputType; import org.hisp.dhis.analytics.SortOrder; import org.hisp.dhis.common.AnalyticalObject; import org.hisp.dhis.common.DisplayProperty; @@ -53,7 +54,7 @@ */ EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set dimension, Set filter, boolean skipMeta, boolean hierarchyMeta, SortOrder sortOrder, - Integer limit, boolean uniqueInstances, DisplayProperty displayProperty, I18nFormat format ); + Integer limit, EventOutputType outputType, 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-01-17 07:41:26 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java 2015-02-15 17:50:12 +0000 @@ -37,6 +37,7 @@ import java.util.Set; import org.hisp.dhis.analytics.DataQueryParams; +import org.hisp.dhis.analytics.EventOutputType; import org.hisp.dhis.analytics.Partitions; import org.hisp.dhis.analytics.SortOrder; import org.hisp.dhis.common.DimensionalObject; @@ -80,7 +81,7 @@ private Integer limit; - private boolean uniqueInstances; + private EventOutputType outputType; private boolean coordinatesOnly; @@ -126,7 +127,7 @@ params.pageSize = this.pageSize; params.sortOrder = this.sortOrder; params.limit = this.limit; - params.uniqueInstances = this.uniqueInstances; + params.outputType = this.outputType; params.coordinatesOnly = this.coordinatesOnly; params.periodType = this.periodType; @@ -421,14 +422,14 @@ this.limit = limit; } - public boolean isUniqueInstances() + public EventOutputType getOutputType() { - return uniqueInstances; + return outputType; } - public void setUniqueInstances( boolean uniqueInstances ) + public void setOutputType( EventOutputType outputType ) { - this.uniqueInstances = uniqueInstances; + this.outputType = outputType; } public boolean isCoordinatesOnly() === 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-10 18:40:27 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java 2015-02-15 17:50:12 +0000 @@ -51,6 +51,7 @@ import org.hisp.dhis.analytics.AnalyticsSecurityManager; import org.hisp.dhis.analytics.AnalyticsService; +import org.hisp.dhis.analytics.EventOutputType; import org.hisp.dhis.analytics.SortOrder; import org.hisp.dhis.analytics.event.EventAnalyticsManager; import org.hisp.dhis.analytics.event.EventAnalyticsService; @@ -91,6 +92,8 @@ import org.hisp.dhis.util.Timer; import org.springframework.beans.factory.annotation.Autowired; +import com.google.common.base.MoreObjects; + /** * @author Lars Helge Overland */ @@ -341,14 +344,14 @@ @Override public EventQueryParams getFromUrl( String program, String stage, String startDate, String endDate, Set dimension, Set filter, boolean skipMeta, boolean hierarchyMeta, SortOrder sortOrder, - Integer limit, boolean uniqueInstances, DisplayProperty displayProperty, I18nFormat format ) + 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.setSortOrder( sortOrder ); params.setLimit( limit ); - params.setUniqueInstances( uniqueInstances ); + params.setOutputType( MoreObjects.firstNonNull( outputType, EventOutputType.EVENT ) ); params.setAggregate( true ); return params; === 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-01-17 07:41:26 +0000 +++ 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 @@ -43,6 +43,7 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hisp.dhis.analytics.EventOutputType; import org.hisp.dhis.analytics.event.EventAnalyticsManager; import org.hisp.dhis.analytics.event.EventQueryParams; import org.hisp.dhis.common.DimensionType; @@ -84,7 +85,7 @@ @Override public Grid getAggregatedEventData( EventQueryParams params, Grid grid, int maxLimit ) { - String countClause = ( params.isProgramRegistration() && params.isUniqueInstances() ) ? "count(distinct tei)" : "count(psi)"; + String countClause = getCountClause( params ); String sql = "select " + countClause + " as value," + getSelectColumns( params ) + " "; @@ -306,6 +307,27 @@ // ------------------------------------------------------------------------- /** + * Returns the count clause based on the output type. + */ + private String getCountClause( 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)"; + } + } + + /** * Returns the dynamic select columns. Dimensions come first and query items * second. */ === modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java' --- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java 2015-01-23 17:23:01 +0000 +++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java 2015-02-15 17:50:12 +0000 @@ -283,6 +283,7 @@ } String[] psi = { quote( "psi" ), "character(11) not null", "psi.uid" }; + String[] pi = { quote( "pi" ), "character(11) not null", "pi.uid" }; String[] ps = { quote( "ps" ), "character(11) not null", "ps.uid" }; String[] ed = { quote( "executiondate" ), "timestamp", "psi.executiondate" }; String[] longitude = { quote( "longitude" ), dbl, "psi.longitude" }; @@ -291,7 +292,7 @@ String[] oun = { quote( "ouname" ), "character varying(230) not null", "ou.name" }; String[] ouc = { quote( "oucode" ), "character varying(50)", "ou.code" }; - columns.addAll( Arrays.asList( psi, ps, ed, longitude, latitude, ou, oun, ouc ) ); + columns.addAll( Arrays.asList( psi, pi, ps, ed, longitude, latitude, ou, oun, ouc ) ); if ( table.hasProgram() && table.getProgram().isRegistration() ) { === 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-01-17 07:41:26 +0000 +++ 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 @@ -157,7 +157,7 @@ filterParams.add( "pe:201401;201402" ); EventQueryParams params = analyticsService.getFromUrl( prA.getUid(), null, - null, null, dimensionParams, filterParams, false, false, null, null, false, null, null ); + null, null, dimensionParams, filterParams, false, false, null, null, null, null, null ); assertEquals( prA, params.getProgram() ); assertEquals( 1, params.getOrganisationUnits().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-01-17 07:41:26 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/EventAnalyticsController.java 2015-02-15 17:50:12 +0000 @@ -35,6 +35,7 @@ import javax.servlet.http.HttpServletResponse; +import org.hisp.dhis.analytics.EventOutputType; import org.hisp.dhis.analytics.SortOrder; import org.hisp.dhis.analytics.event.EventAnalyticsService; import org.hisp.dhis.analytics.event.EventQueryParams; @@ -86,14 +87,14 @@ @RequestParam( required = false ) boolean skipMeta, @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, - @RequestParam( required = false ) boolean uniqueInstances, + @RequestParam( required = false ) EventOutputType outputType, @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, - skipMeta, hierarchyMeta, sortOrder, limit, uniqueInstances, displayProperty, i18nManager.getI18nFormat() ); + skipMeta, hierarchyMeta, sortOrder, limit, outputType, displayProperty, i18nManager.getI18nFormat() ); contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING ); Grid grid = analyticsService.getAggregatedEventData( params ); @@ -113,14 +114,14 @@ @RequestParam( required = false ) boolean skipMeta, @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, - @RequestParam( required = false ) boolean uniqueInstances, + @RequestParam( required = false ) EventOutputType outputType, @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, - skipMeta, hierarchyMeta, sortOrder, limit, uniqueInstances, displayProperty, i18nManager.getI18nFormat() ); + 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 ); @@ -138,14 +139,14 @@ @RequestParam( required = false ) boolean skipMeta, @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, - @RequestParam( required = false ) boolean uniqueInstances, + @RequestParam( required = false ) EventOutputType outputType, @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, - skipMeta, hierarchyMeta, sortOrder, limit, uniqueInstances, displayProperty, i18nManager.getI18nFormat() ); + 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 ); @@ -163,14 +164,14 @@ @RequestParam( required = false ) boolean skipMeta, @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, - @RequestParam( required = false ) boolean uniqueInstances, + @RequestParam( required = false ) EventOutputType outputType, @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, - skipMeta, hierarchyMeta, sortOrder, limit, uniqueInstances, displayProperty, i18nManager.getI18nFormat() ); + 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 ); @@ -188,14 +189,14 @@ @RequestParam( required = false ) boolean skipMeta, @RequestParam( required = false ) boolean hierarchyMeta, @RequestParam( required = false ) Integer limit, - @RequestParam( required = false ) boolean uniqueInstances, + @RequestParam( required = false ) EventOutputType outputType, @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, - skipMeta, hierarchyMeta, sortOrder, limit, uniqueInstances, displayProperty, i18nManager.getI18nFormat() ); + 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 );