dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #22666
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 10965: Analytics API. Impl support for getting responses with table layout. Useful for getting ready-mad...
------------------------------------------------------------
revno: 10965
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2013-05-23 18:57:03 +0200
message:
Analytics API. Impl support for getting responses with table layout. Useful for getting ready-made reports based on dynamic input.
added:
dhis-2/dhis-api/src/test/java/org/hisp/dhis/common/BaseAnalyticalObjectTest.java
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/BaseNameableObject.java
dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DimensionalObject.java
dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.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/DimensionItem.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java
dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/DimensionOptionTest.java
dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java
dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java
dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.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/common/BaseAnalyticalObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseAnalyticalObject.java 2013-05-23 16:57:03 +0000
@@ -35,10 +35,12 @@
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.DimensionalObject.CATEGORYOPTIONCOMBO_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT;
import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT_CHILDREN;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
@@ -46,6 +48,7 @@
import java.util.List;
import java.util.Map;
+import org.apache.commons.lang.StringUtils;
import org.hisp.dhis.common.adapter.JacksonPeriodDeserializer;
import org.hisp.dhis.common.adapter.JacksonPeriodSerializer;
import org.hisp.dhis.common.annotation.Scanned;
@@ -406,21 +409,60 @@
return categoryDims;
}
+ /**
+ * Splits the keys of the given map on the dimension identifier separator,
+ * sorts the identifiers, writes them out as a key and puts the key back into
+ * the map.
+ */
+ public static void sortKeys( Map<String, Double> valueMap )
+ {
+ Map<String, Double> map = new HashMap<String, Double>();
+
+ for ( String key : valueMap.keySet() )
+ {
+ if ( key != null )
+ {
+ String[] ids = key.split( DIMENSION_SEP );
+
+ Collections.sort( Arrays.asList( ids ) );
+
+ String sortedKey = StringUtils.join( ids, DIMENSION_SEP );
+
+ map.put( sortedKey, valueMap.get( key ) );
+ }
+ }
+
+ valueMap.clear();
+ valueMap.putAll( map );
+ }
+
+ /**
+ * Generates an identifier based on the given lists of NameableObjects. Uses
+ * the UIDs for each NameableObject, sorts them and writes them out as a key.
+ */
public static String getIdentifer( List<NameableObject> column, List<NameableObject> row )
{
- StringBuilder id = new StringBuilder();
-
- for ( NameableObject item : column )
- {
- id.append( item.getUid() ).append( "-" );
- }
-
- for ( NameableObject item : row )
- {
- id.append( item.getUid() ).append( "-" );
- }
-
- return id.substring( 0, id.length() - 1 );
+ List<String> ids = new ArrayList<String>();
+
+ if ( column != null )
+ {
+ for ( NameableObject item : column )
+ {
+ ids.add( item.getUid() );
+ }
+ }
+
+ if ( row != null )
+ {
+ for ( NameableObject item : row )
+ {
+ ids.add( item.getUid() );
+ }
+ }
+
+ Collections.sort( ids );
+
+ return StringUtils.join( ids, DIMENSION_SEP );
}
public void mergeWith( BaseAnalyticalObject other )
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/BaseNameableObject.java 2013-05-23 16:57:03 +0000
@@ -172,7 +172,7 @@
{
this.displayDescription = displayDescription;
}
-
+
@Override
public void mergeWith( IdentifiableObject other )
{
=== 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 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/DimensionalObject.java 2013-05-23 16:57:03 +0000
@@ -44,6 +44,8 @@
final String CATEGORYOPTIONCOMBO_DIM_ID = "co";
final String PERIOD_DIM_ID = "pe";
final String ORGUNIT_DIM_ID = "ou";
+
+ final String DIMENSION_SEP = "-";
final List<String> DATA_X_DIMS = Arrays.asList( INDICATOR_DIM_ID, DATAELEMENT_DIM_ID, DATASET_DIM_ID, DATAELEMENT_OPERAND_ID );
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java 2013-05-23 12:59:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/reporttable/ReportTable.java 2013-05-23 16:57:03 +0000
@@ -616,6 +616,10 @@
final String subtitle = StringUtils.trimToEmpty( getParentOrganisationUnitName() ) + SPACE
+ StringUtils.trimToEmpty( reportingPeriodName );
+ valueMap = new HashMap<String, Double>( valueMap );
+
+ sortKeys( valueMap );
+
grid.setTitle( name + " - " + subtitle );
// ---------------------------------------------------------------------
@@ -684,7 +688,7 @@
for ( List<NameableObject> column : gridColumns )
{
- String key = BaseAnalyticalObject.getIdentifer( column, row );
+ String key = getIdentifer( column, row );
Double value = valueMap.get( key );
=== added file 'dhis-2/dhis-api/src/test/java/org/hisp/dhis/common/BaseAnalyticalObjectTest.java'
--- dhis-2/dhis-api/src/test/java/org/hisp/dhis/common/BaseAnalyticalObjectTest.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/test/java/org/hisp/dhis/common/BaseAnalyticalObjectTest.java 2013-05-23 16:57:03 +0000
@@ -0,0 +1,112 @@
+package org.hisp.dhis.common;
+
+/*
+ * Copyright (c) 2004-2012, 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.
+ */
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.hisp.dhis.dataelement.DataElementGroup;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+/**
+* @author Lars Helge Overland
+*/
+public class BaseAnalyticalObjectTest
+{
+ @Test
+ public void testSortKeys()
+ {
+ Map<String, Double> valueMap = new HashMap<String, Double>();
+
+ valueMap.put( "b1-a1-c1", 1d );
+ valueMap.put( "a2-c2-b2", 2d );
+ valueMap.put( "c3-b3-a3", 3d );
+ valueMap.put( "a4-b4-c4", 4d );
+
+ BaseAnalyticalObject.sortKeys( valueMap );
+
+ assertEquals( 4, valueMap.size() );
+ assertTrue( valueMap.containsKey( "a1-b1-c1" ) );
+ assertTrue( valueMap.containsKey( "a2-b2-c2" ) );
+ assertTrue( valueMap.containsKey( "a3-b3-c3" ) );
+ assertTrue( valueMap.containsKey( "a4-b4-c4" ) );
+
+ assertEquals( 1d, valueMap.get( "a1-b1-c1" ), 0.01 );
+ assertEquals( 2d, valueMap.get( "a2-b2-c2" ), 0.01 );
+ assertEquals( 3d, valueMap.get( "a3-b3-c3" ), 0.01 );
+ assertEquals( 4d, valueMap.get( "a4-b4-c4" ), 0.01 );
+
+ valueMap = new HashMap<String, Double>();
+
+ valueMap.put( "b1", 1d );
+ valueMap.put( "b2", 2d );
+
+ BaseAnalyticalObject.sortKeys( valueMap );
+
+ assertEquals( 2, valueMap.size() );
+ assertTrue( valueMap.containsKey( "b1" ) );
+ assertTrue( valueMap.containsKey( "b2" ) );
+
+ assertEquals( 1d, valueMap.get( "b1" ), 0.01 );
+ assertEquals( 2d, valueMap.get( "b2" ), 0.01 );
+
+ valueMap = new HashMap<String, Double>();
+
+ valueMap.put( null, 1d );
+
+ BaseAnalyticalObject.sortKeys( valueMap );
+
+ assertEquals( 0, valueMap.size() );
+ }
+
+ @Test
+ public void testGetIdentifier()
+ {
+ DataElementGroup oA = new DataElementGroup();
+ DataElementGroup oB = new DataElementGroup();
+ DataElementGroup oC = new DataElementGroup();
+
+ oA.setUid( "a1" );
+ oB.setUid( "b1" );
+ oC.setUid( "c1" );
+
+ List<NameableObject> column = new ArrayList<NameableObject>();
+ column.add( oC );
+ column.add( oA );
+
+ List<NameableObject> row = new ArrayList<NameableObject>();
+ row.add( oB );
+
+ assertEquals( "a1-b1-c1", BaseAnalyticalObject.getIdentifer( column, row ) );
+ assertEquals( "b1", BaseAnalyticalObject.getIdentifer( new ArrayList<NameableObject>(), row ) );
+ assertEquals( "b1", BaseAnalyticalObject.getIdentifer( null, row ) );
+ }
+}
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java 2013-05-19 18:49:47 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AnalyticsService.java 2013-05-23 16:57:03 +0000
@@ -27,6 +27,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -48,6 +49,20 @@
* @return aggregated data as a Grid object.
*/
Grid getAggregatedDataValues( DataQueryParams params );
+
+ /**
+ * Generates an aggregated value grid for the given query. The grid will
+ * represent a table with dimensions used as columns and rows as specified
+ * in columnDimensions and rowDimensions arguments.
+ *
+ * @param params the data query parameters.
+ * @param tableLayout whether to render the grid as a table with columns and rows,
+ * or as a normalized plain data source.
+ * @param columns the identifiers of the dimensions to use as columns.
+ * @param rows the identifiers of the dimensions to use as rows.
+ * @return aggregated data as a Grid object.
+ */
+ Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List<String> columns, List<String> rows );
/**
* Generates a mapping where the key represents the dimensional item identifiers
=== 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 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java 2013-05-23 16:57:03 +0000
@@ -33,11 +33,13 @@
import static org.hisp.dhis.common.DimensionType.ORGANISATIONUNIT_GROUPSET;
import static org.hisp.dhis.common.DimensionalObject.CATEGORYOPTIONCOMBO_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.DATAELEMENT_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.DATAELEMENT_OPERAND_ID;
import static org.hisp.dhis.common.DimensionalObject.DATASET_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.DATA_X_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.INDICATOR_DIM_ID;
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.DimensionalObject.DIMENSION_SEP;
import static org.hisp.dhis.common.NameableObjectUtils.asList;
import static org.hisp.dhis.common.NameableObjectUtils.getList;
import static org.hisp.dhis.system.util.CollectionUtils.emptyIfNull;
@@ -86,9 +88,8 @@
private static final String DIMENSION_NAME_SEP = ":";
private static final String OPTION_SEP = ";";
- public static final String DIMENSION_SEP = "-";
- public static final List<String> DATA_DIMS = Arrays.asList( INDICATOR_DIM_ID, DATAELEMENT_DIM_ID, DATASET_DIM_ID );
+ public static final List<String> DATA_DIMS = Arrays.asList( INDICATOR_DIM_ID, DATAELEMENT_DIM_ID, DATAELEMENT_OPERAND_ID, DATASET_DIM_ID );
public static final List<String> FIXED_DIMS = Arrays.asList( DATA_X_DIM_ID, INDICATOR_DIM_ID, DATAELEMENT_DIM_ID, DATASET_DIM_ID, PERIOD_DIM_ID, ORGUNIT_DIM_ID );
public static final int MAX_DIM_OPT_PERM = 10000;
@@ -571,7 +572,8 @@
}
/**
- * Retrieves the options for the given dimension identifier.
+ * Retrieves the options for the given dimension identifier. Returns null if
+ * the dimension is not present.
*/
public List<NameableObject> getDimensionOptions( String dimension )
{
@@ -581,7 +583,8 @@
}
/**
- * Retrieves the dimension with the given dimension identifier.
+ * Retrieves the dimension with the given dimension identifier. Returns null
+ * if the dimension is not present.
*/
public DimensionalObject getDimension( String dimension )
{
@@ -707,6 +710,20 @@
}
/**
+ * Splits the given string on the ; character and returns the items in a
+ * list. Returns null if the given string is null.
+ */
+ public static List<String> getDimensionsFromParam( String param )
+ {
+ if ( param == null )
+ {
+ return null;
+ }
+
+ return Arrays.asList( param.split( OPTION_SEP ) );
+ }
+
+ /**
* Retrieves the measure criteria from the given string. Criteria are separated
* by the option separator, while the criterion filter and value are separated
* with the dimension name separator.
@@ -944,16 +961,56 @@
// Get and set helpers for dimensions or filter
// -------------------------------------------------------------------------
+ /**
+ * Retrieves the options for the the dimension or filter with the given
+ * identifier.
+ */
public List<NameableObject> getDimensionOrFilter( String key )
{
return getDimensionOptions( key ) != null ? getDimensionOptions( key ) : getFilterOptions( key );
}
+ /**
+ * Retrieves the options for the given dimension identifier. If the dx dimension
+ * is specified, all concrete dimensions (in|de|dc|ds) are returned as a single
+ * dimension. Returns an empty array if the dimension is not present.
+ */
+ public NameableObject[] getDimensionArrayCollapseDx( String dimension )
+ {
+ List<NameableObject> items = new ArrayList<NameableObject>();
+
+ if ( DATA_X_DIM_ID.equals( dimension ) )
+ {
+ items.addAll( getDimensionOptionsNullSafe( INDICATOR_DIM_ID ) );
+ items.addAll( getDimensionOptionsNullSafe( DATAELEMENT_DIM_ID ) );
+ items.addAll( getDimensionOptionsNullSafe( DATAELEMENT_OPERAND_ID ) );
+ items.addAll( getDimensionOptionsNullSafe( DATASET_DIM_ID ) );
+ }
+ else
+ {
+ items.addAll( getDimensionOptionsNullSafe( dimension ) );
+ }
+
+ return items.toArray( new NameableObject[0] );
+ }
+
+ /**
+ * Retrieves the options for the given dimension identifier. Returns an empty
+ * list if the dimension is not present.
+ */
+ public List<NameableObject> getDimensionOptionsNullSafe( String dimension )
+ {
+ return getDimensionOptions( dimension ) != null ? getDimensionOptions( dimension ) : new ArrayList<NameableObject>();
+ }
+
+ /**
+ * Indicates whether a dimension or filter with the given identifier exists.
+ */
public boolean hasDimensionOrFilter( String key )
{
return dimensions.indexOf( new BaseDimensionalObject( key ) ) != -1 || filters.indexOf( new BaseDimensionalObject( key ) ) != -1;
}
-
+
// -------------------------------------------------------------------------
// Get and set helpers for dimensions
// -------------------------------------------------------------------------
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DimensionItem.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DimensionItem.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DimensionItem.java 2013-05-23 16:57:03 +0000
@@ -34,6 +34,8 @@
import org.hisp.dhis.common.NameableObject;
import org.hisp.dhis.system.util.CollectionUtils;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
+
/**
* @author Lars Helge Overland
*/
@@ -94,7 +96,7 @@
{
for ( DimensionItem item : items )
{
- builder.append( item.getItem().getUid() ).append( DataQueryParams.DIMENSION_SEP );
+ builder.append( item.getItem().getUid() ).append( DIMENSION_SEP );
}
builder.deleteCharAt( builder.length() - 1 );
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java 2013-05-07 08:37:33 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/QueryPlanner.java 2013-05-23 16:57:03 +0000
@@ -46,6 +46,19 @@
throws IllegalQueryException;
/**
+ * Validates whether the given table layout is valid for the given query.
+ * Throws an IllegalQueryException if the query is not valid with a
+ * descriptive message. Returns normally if the query is valid.
+ *
+ * @param params the query.
+ * @param columns the column dimension identifiers.
+ * @param rows the row dimension identifiers.
+ * @throws IllegalQueryException if the query is invalid.
+ */
+ void validateTableLayout( DataQueryParams params, List<String> columns, List<String> rows )
+ throws IllegalQueryException;
+
+ /**
* Creates a list of DataQueryParams. It is mandatory to group the queries by
* the following criteria: 1) partition / year 2) period type 3) organisation
* unit level. If the number of queries produced by this grouping is equal or
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java 2013-05-23 16:57:03 +0000
@@ -30,7 +30,6 @@
import static org.hisp.dhis.analytics.AnalyticsTableManager.ANALYTICS_TABLE_NAME;
import static org.hisp.dhis.analytics.AnalyticsTableManager.COMPLETENESS_TABLE_NAME;
import static org.hisp.dhis.analytics.AnalyticsTableManager.COMPLETENESS_TARGET_TABLE_NAME;
-import static org.hisp.dhis.analytics.DataQueryParams.DIMENSION_SEP;
import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_CATEGORYOPTIONCOMBO;
import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_DATA_X;
import static org.hisp.dhis.analytics.DataQueryParams.DISPLAY_NAME_ORGUNIT;
@@ -45,12 +44,15 @@
import static org.hisp.dhis.common.DimensionalObject.INDICATOR_DIM_ID;
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.DimensionalObject.DIMENSION_SEP;
import static org.hisp.dhis.common.DimensionalObjectUtils.toDimension;
+import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
import static org.hisp.dhis.common.NameableObjectUtils.asList;
import static org.hisp.dhis.common.NameableObjectUtils.asTypedList;
-import static org.hisp.dhis.common.IdentifiableObjectUtils.getUids;
import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT;
import static org.hisp.dhis.organisationunit.OrganisationUnit.KEY_USER_ORGUNIT_CHILDREN;
+import static org.hisp.dhis.reporttable.ReportTable.IRT2D;
+import static org.hisp.dhis.reporttable.ReportTable.addIfEmpty;
import java.util.ArrayList;
import java.util.Arrays;
@@ -76,6 +78,7 @@
import org.hisp.dhis.analytics.QueryPlanner;
import org.hisp.dhis.common.BaseAnalyticalObject;
import org.hisp.dhis.common.BaseDimensionalObject;
+import org.hisp.dhis.common.CombinationGenerator;
import org.hisp.dhis.common.DimensionType;
import org.hisp.dhis.common.DimensionalObject;
import org.hisp.dhis.common.Grid;
@@ -105,6 +108,7 @@
import org.hisp.dhis.period.RelativePeriodEnum;
import org.hisp.dhis.period.RelativePeriods;
import org.hisp.dhis.period.comparator.AscendingPeriodComparator;
+import org.hisp.dhis.reporttable.ReportTable;
import org.hisp.dhis.system.grid.ListGrid;
import org.hisp.dhis.system.util.ConversionUtils;
import org.hisp.dhis.system.util.DebugUtils;
@@ -357,6 +361,54 @@
return grid;
}
+
+ @Override
+ public Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List<String> columns, List<String> rows )
+ {
+ if ( !tableLayout )
+ {
+ return getAggregatedDataValues( params );
+ }
+
+ queryPlanner.validateTableLayout( params, columns, rows );
+
+ Map<String, Double> valueMap = getAggregatedDataValueMapping( params );
+
+ ReportTable reportTable = new ReportTable();
+
+ List<NameableObject[]> tableColumns = new ArrayList<NameableObject[]>();
+ List<NameableObject[]> tableRows = new ArrayList<NameableObject[]>();
+
+ if ( columns != null )
+ {
+ for ( String dimension : columns )
+ {
+ reportTable.getColumnDimensions().add( dimension );
+
+ tableColumns.add( params.getDimensionArrayCollapseDx( dimension ) );
+ }
+ }
+
+ if ( rows != null )
+ {
+ for ( String dimension : rows )
+ {
+ reportTable.getRowDimensions().add( dimension );
+
+ tableRows.add( params.getDimensionArrayCollapseDx( dimension ) );
+ }
+ }
+
+ reportTable.setGridColumns( new CombinationGenerator<NameableObject>( tableColumns.toArray( IRT2D ) ).getCombinations() );
+ reportTable.setGridRows( new CombinationGenerator<NameableObject>( tableRows.toArray( IRT2D ) ).getCombinations() );
+
+ addIfEmpty( reportTable.getGridColumns() );
+ addIfEmpty( reportTable.getGridRows() );
+
+ Grid grid = reportTable.getGrid( new ListGrid(), valueMap, false );
+
+ return grid;
+ }
@Override
public Map<String, Double> getAggregatedDataValueMapping( DataQueryParams params )
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java 2013-05-23 16:57:03 +0000
@@ -140,6 +140,45 @@
}
}
+ public void validateTableLayout( DataQueryParams params, List<String> columns, List<String> rows )
+ {
+ String violation = null;
+
+ if ( ( columns == null || columns.isEmpty() ) && ( rows == null || rows.isEmpty() ) )
+ {
+ violation = "Cannot generate table layout when columns and rows are empty";
+ }
+
+ if ( columns != null )
+ {
+ for ( String column : columns )
+ {
+ if ( params.getDimensionArrayCollapseDx( column ).length == 0 )
+ {
+ violation = "Column must be present as dimension in query: " + column;
+ }
+ }
+ }
+
+ if ( rows != null )
+ {
+ for ( String row : rows )
+ {
+ if ( params.getDimensionArrayCollapseDx( row ).length == 0 )
+ {
+ violation = "Row must be present as dimension in query: " + row;
+ }
+ }
+ }
+
+ if ( violation != null )
+ {
+ log.warn( "Validation failed: " + violation );
+
+ throw new IllegalQueryException( violation );
+ }
+ }
+
public List<DataQueryParams> planQuery( DataQueryParams params, int optimalQueries, String tableName )
{
validate( params );
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java 2013-05-23 16:57:03 +0000
@@ -31,7 +31,7 @@
import static org.hisp.dhis.analytics.AggregationType.AVERAGE_INT;
import static org.hisp.dhis.analytics.AggregationType.AVERAGE_INT_DISAGGREGATION;
import static org.hisp.dhis.analytics.AggregationType.COUNT;
-import static org.hisp.dhis.analytics.DataQueryParams.DIMENSION_SEP;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
import static org.hisp.dhis.analytics.DataQueryParams.VALUE_ID;
import static org.hisp.dhis.analytics.MeasureFilter.EQ;
import static org.hisp.dhis.analytics.MeasureFilter.GE;
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java 2013-05-19 18:49:47 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/MockAnalyticsService.java 2013-05-23 16:57:03 +0000
@@ -27,6 +27,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -56,7 +57,13 @@
{
throw new NotImplementedException();
}
-
+
+ @Override
+ public Grid getAggregatedDataValues( DataQueryParams params, boolean tableLayout, List<String> columns, List<String> rows )
+ {
+ throw new NotImplementedException();
+ }
+
@Override
public Map<String, Double> getAggregatedDataValueMapping( DataQueryParams params )
{
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/DimensionOptionTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/DimensionOptionTest.java 2013-05-07 08:37:33 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/DimensionOptionTest.java 2013-05-23 16:57:03 +0000
@@ -27,6 +27,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+import static org.hisp.dhis.common.DimensionalObject.DATAELEMENT_DIM_ID;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
+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.system.util.TextUtils.EMPTY;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+
import java.util.ArrayList;
import java.util.List;
@@ -37,11 +45,6 @@
import org.junit.Before;
import org.junit.Test;
-import static org.junit.Assert.*;
-import static org.hisp.dhis.analytics.DataQueryParams.*;
-import static org.hisp.dhis.system.util.TextUtils.EMPTY;
-import static org.hisp.dhis.common.DimensionalObject.*;
-
/**
* @author Lars Helge Overland
*/
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java 2013-05-23 13:38:20 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/test/java/org/hisp/dhis/analytics/data/QueryPlannerTest.java 2013-05-23 16:57:03 +0000
@@ -28,7 +28,7 @@
*/
import static org.hisp.dhis.analytics.AnalyticsTableManager.ANALYTICS_TABLE_NAME;
-import static org.hisp.dhis.analytics.DataQueryParams.DIMENSION_SEP;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
import static org.hisp.dhis.common.DimensionalObject.DATA_X_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.ORGUNIT_DIM_ID;
import static org.hisp.dhis.common.DimensionalObject.PERIOD_DIM_ID;
=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java 2013-05-21 11:39:31 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/main/java/org/hisp/dhis/chart/impl/DefaultChartService.java 2013-05-23 16:57:03 +0000
@@ -34,6 +34,7 @@
import static org.hisp.dhis.chart.Chart.TYPE_PIE;
import static org.hisp.dhis.chart.Chart.TYPE_STACKED_BAR;
import static org.hisp.dhis.chart.Chart.TYPE_STACKED_COLUMN;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
import static org.hisp.dhis.system.util.ConversionUtils.getArray;
import java.awt.BasicStroke;
@@ -53,7 +54,6 @@
import org.apache.commons.math.analysis.UnivariateRealInterpolator;
import org.apache.commons.math.stat.regression.SimpleRegression;
import org.hisp.dhis.analytics.AnalyticsService;
-import org.hisp.dhis.analytics.DataQueryParams;
import org.hisp.dhis.chart.Chart;
import org.hisp.dhis.chart.ChartService;
import org.hisp.dhis.chart.ChartStore;
@@ -735,7 +735,7 @@
{
categoryIndex++;
- String key = series.getUid() + DataQueryParams.DIMENSION_SEP + category.getUid();
+ String key = series.getUid() + DIMENSION_SEP + category.getUid();
Double value = valueMap.get( key );
=== modified file 'dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java'
--- dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java 2013-05-20 06:10:29 +0000
+++ dhis-2/dhis-services/dhis-service-reporting/src/test/java/org/hisp/dhis/reporttable/ReportTableGridTest.java 2013-05-23 16:57:03 +0000
@@ -27,7 +27,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-import static org.hisp.dhis.analytics.DataQueryParams.DIMENSION_SEP;
+import static org.hisp.dhis.common.DimensionalObject.DIMENSION_SEP;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java 2013-04-04 18:06:19 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java 2013-05-23 16:57:03 +0000
@@ -28,6 +28,7 @@
*/
import static org.hisp.dhis.analytics.AnalyticsService.NAMES_META_KEY;
+import static org.hisp.dhis.analytics.DataQueryParams.getDimensionsFromParam;
import java.util.Map;
import java.util.Set;
@@ -75,13 +76,16 @@
@RequestParam(required = false) Set<String> filter,
@RequestParam(required = false) AggregationType aggregationType,
@RequestParam(required = false) String measureCriteria,
+ @RequestParam(required = false) boolean tableLayout,
+ @RequestParam(required = false) String columns,
+ @RequestParam(required = false) String rows,
Model model,
HttpServletResponse response ) throws Exception
{
DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() );
contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.RESPECT_SYSTEM_SETTING );
- Grid grid = analyticsService.getAggregatedDataValues( params );
+ Grid grid = analyticsService.getAggregatedDataValues( params, tableLayout, getDimensionsFromParam( columns ), getDimensionsFromParam( rows ) );
model.addAttribute( "model", grid );
model.addAttribute( "viewClass", "detailed" );
return "grid";
@@ -93,13 +97,16 @@
@RequestParam(required = false) Set<String> filter,
@RequestParam(required = false) AggregationType aggregationType,
@RequestParam(required = false) String measureCriteria,
+ @RequestParam(required = false) boolean tableLayout,
+ @RequestParam(required = false) String columns,
+ @RequestParam(required = false) String rows,
Model model,
HttpServletResponse response ) throws Exception
{
DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() );
contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.RESPECT_SYSTEM_SETTING );
- Grid grid = analyticsService.getAggregatedDataValues( params );
+ Grid grid = analyticsService.getAggregatedDataValues( params, tableLayout, getDimensionsFromParam( columns ), getDimensionsFromParam( rows ) );
GridUtils.toXml( grid, response.getOutputStream() );
}
@@ -109,13 +116,16 @@
@RequestParam(required = false) Set<String> filter,
@RequestParam(required = false) AggregationType aggregationType,
@RequestParam(required = false) String measureCriteria,
+ @RequestParam(required = false) boolean tableLayout,
+ @RequestParam(required = false) String columns,
+ @RequestParam(required = false) String rows,
Model model,
HttpServletResponse response ) throws Exception
{
DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() );
contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_HTML, CacheStrategy.RESPECT_SYSTEM_SETTING );
- Grid grid = analyticsService.getAggregatedDataValues( params );
+ Grid grid = analyticsService.getAggregatedDataValues( params, tableLayout, getDimensionsFromParam( columns ), getDimensionsFromParam( rows ) );
GridUtils.toHtml( substituteMetaData( grid ), response.getWriter() );
}
@@ -125,13 +135,16 @@
@RequestParam(required = false) Set<String> filter,
@RequestParam(required = false) AggregationType aggregationType,
@RequestParam(required = false) String measureCriteria,
+ @RequestParam(required = false) boolean tableLayout,
+ @RequestParam(required = false) String columns,
+ @RequestParam(required = false) String rows,
Model model,
HttpServletResponse response ) throws Exception
{
DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() );
contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_CSV, CacheStrategy.RESPECT_SYSTEM_SETTING, "data.csv", true );
- Grid grid = analyticsService.getAggregatedDataValues( params );
+ Grid grid = analyticsService.getAggregatedDataValues( params, tableLayout, getDimensionsFromParam( columns ), getDimensionsFromParam( rows ) );
GridUtils.toCsv( substituteMetaData( grid ), response.getOutputStream() );
}
@@ -141,13 +154,16 @@
@RequestParam(required = false) Set<String> filter,
@RequestParam(required = false) AggregationType aggregationType,
@RequestParam(required = false) String measureCriteria,
+ @RequestParam(required = false) boolean tableLayout,
+ @RequestParam(required = false) String columns,
+ @RequestParam(required = false) String rows,
Model model,
HttpServletResponse response ) throws Exception
{
DataQueryParams params = analyticsService.getFromUrl( dimension, filter, aggregationType, measureCriteria, i18nManager.getI18nFormat() );
contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_EXCEL, CacheStrategy.RESPECT_SYSTEM_SETTING, "data.xls", true );
- Grid grid = analyticsService.getAggregatedDataValues( params );
+ Grid grid = analyticsService.getAggregatedDataValues( params, tableLayout, getDimensionsFromParam( columns ), getDimensionsFromParam( rows ) );
GridUtils.toXls( substituteMetaData( grid ), response.getOutputStream() );
}