← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 9407: Impl aggregation of average aggregation operator data elements in case where data period type is ...

 

------------------------------------------------------------
revno: 9407
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2012-12-27 20:15:15 +0100
message:
  Impl aggregation of average aggregation operator data elements in case where data period type is less frequent or similar to aggregation period type
added:
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AggregationType.java
modified:
  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/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


--
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
=== added file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AggregationType.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AggregationType.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/AggregationType.java	2012-12-27 19:15:15 +0000
@@ -0,0 +1,33 @@
+package org.hisp.dhis.analytics;
+
+/*
+ * 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.
+ */
+
+public enum AggregationType
+{
+    SUM, AVERAGE_AGGREGATION, AVERAGE_DISAGGREGATION
+}

=== 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	2012-12-21 16:50:36 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java	2012-12-27 19:15:15 +0000
@@ -67,6 +67,8 @@
     
     private transient int organisationUnitLevel;
     
+    private AggregationType aggregationType;
+    
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
@@ -91,6 +93,7 @@
         this.tableName = params.getTableName();
         this.periodType = params.getPeriodType();
         this.organisationUnitLevel = params.getOrganisationUnitLevel();
+        this.aggregationType = params.getAggregationType();
     }
 
     // -------------------------------------------------------------------------
@@ -163,6 +166,14 @@
         return dimensions.containsKey( PERIOD_DIM_ID ) || filters.containsKey( PERIOD_DIM_ID );
     }
     
+    /**
+     * Indicates whether this object is of the given aggregation type.
+     */
+    public boolean isAggregationType( AggregationType aggregationType )
+    {
+        return this.aggregationType != null && this.aggregationType.equals( aggregationType );
+    }
+    
     @Override
     public int hashCode()
     {
@@ -390,5 +401,15 @@
     public void setFilterOrganisationUnits( List<String> organisationUnits )
     {
         filters.put( ORGUNIT_DIM_ID, organisationUnits );
-    }    
+    }
+
+    public AggregationType getAggregationType()
+    {
+        return aggregationType;
+    }
+
+    public void setAggregationType( AggregationType aggregationType )
+    {
+        this.aggregationType = aggregationType;
+    }
 }

=== 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	2012-12-22 12:26:34 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java	2012-12-27 19:15:15 +0000
@@ -50,14 +50,9 @@
 {
     private static final String VALUE_HEADER_NAME = "Value";
     
-    //TODO aggregation levels
-    //     add org unit level as column in tables
+    //TODO average operator aggregation
     //TODO indicator aggregation
     //TODO category sub-totals and totals
-    //TODO use data mart when query can be satisfied
-    //TODO create data mart for average, less-than yearly data elements
-    //     aggregate in time dimension only
-    //     insert into standard analytics table?
     
     @Autowired
     private AnalyticsManager analyticsManager;

=== 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	2012-12-21 16:50:36 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultQueryPlanner.java	2012-12-27 19:15:15 +0000
@@ -27,13 +27,19 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static org.hisp.dhis.dataelement.DataElement.AGGREGATION_OPERATOR_AVERAGE;
+import static org.hisp.dhis.dataelement.DataElement.AGGREGATION_OPERATOR_SUM;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.hisp.dhis.analytics.AggregationType;
 import org.hisp.dhis.analytics.DataQueryParams;
 import org.hisp.dhis.analytics.QueryPlanner;
 import org.hisp.dhis.analytics.table.PartitionUtils;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.PeriodType;
 import org.hisp.dhis.system.util.ListMap;
@@ -50,6 +56,9 @@
     @Autowired
     private OrganisationUnitService organisationUnitService;
     
+    @Autowired
+    private DataElementService dataElementService;
+    
     // -------------------------------------------------------------------------
     // DefaultQueryPlanner implementation
     // -------------------------------------------------------------------------
@@ -72,18 +81,26 @@
         
         for ( DataQueryParams byPartition : groupedByPartition )
         {
-            List<DataQueryParams> groupedByPeriodType = groupByPeriodType( byPartition );
+            List<DataQueryParams> groupedByOrgUnitLevel = groupByOrgUnitLevel( byPartition );
             
-            for ( DataQueryParams byPeriodType : groupedByPeriodType )
+            for ( DataQueryParams byOrgUnitLevel : groupedByOrgUnitLevel )
             {
-                List<DataQueryParams> groupedByOrgUnitLevel = groupByOrgUnitLevel( byPeriodType );
+                List<DataQueryParams> groupedByPeriodType = groupByPeriodType( byOrgUnitLevel );
                 
-                for ( DataQueryParams byOrgUnitLevel : groupedByOrgUnitLevel )
+                for ( DataQueryParams byPeriodType : groupedByPeriodType )
                 {
-                    byOrgUnitLevel.setTableName( byPartition.getTableName() );
-                    byOrgUnitLevel.setPeriodType( byPeriodType.getPeriodType() );
+                    List<DataQueryParams> groupedByAggregationType = groupByAggregationType( byPeriodType );
                     
-                    queries.add( byOrgUnitLevel );
+                    for ( DataQueryParams byAggregationType : groupedByAggregationType )
+                    {
+                        byAggregationType.setTableName( byPartition.getTableName() );
+                        byAggregationType.setOrganisationUnitLevel( byOrgUnitLevel.getOrganisationUnitLevel() );
+                        byAggregationType.setPeriodType( byPeriodType.getPeriodType() );
+                        
+                        //TODO split on data element period type for average disaggregation
+                        
+                        queries.add( byAggregationType );
+                    }
                 }
             }
         }
@@ -250,6 +267,31 @@
         return queries;    
     }
     
+    private List<DataQueryParams> groupByAggregationType( DataQueryParams params )
+    {
+        List<DataQueryParams> queries = new ArrayList<DataQueryParams>();
+
+        if ( params.getDatElements() == null || params.getDatElements().isEmpty() )
+        {
+            queries.add( new DataQueryParams( params ) );
+            return queries;
+        }
+     
+        PeriodType periodType = PeriodType.getPeriodTypeByName( params.getPeriodType() );
+        
+        ListMap<AggregationType, String> aggregationTypeDataElementMap = getAggregationTypeDataElementMap( params.getDatElements(), periodType );
+        
+        for ( AggregationType aggregationType : aggregationTypeDataElementMap.keySet() )
+        {
+            DataQueryParams query = new DataQueryParams( params );
+            query.setDataElements( aggregationTypeDataElementMap.get( aggregationType ) );
+            query.setAggregationType( aggregationType );
+            queries.add( query );
+        }
+        
+        return queries;
+    }
+    
     /**
      * Replaces the period filter with individual filters for each period type.
      */
@@ -294,7 +336,7 @@
         
         for ( String period : isoPeriods )
         {
-            String periodTypeName = PeriodType.getPeriodTypeFromIsoString( period ).getName().toLowerCase();
+            String periodTypeName = PeriodType.getPeriodTypeFromIsoString( period ).getName();
             
             map.putValue( periodTypeName, period );
         }
@@ -337,4 +379,38 @@
         
         return map;
     }
+    
+    /**
+     * Creates a mapping between the aggregation type and data element for the
+     * given data elements and period type.
+     */
+    private ListMap<AggregationType, String> getAggregationTypeDataElementMap( Collection<String> dataElements, PeriodType aggregationPeriodType )
+    {
+        ListMap<AggregationType, String> map = new ListMap<AggregationType, String>();
+        
+        for ( String element : dataElements )
+        {
+            DataElement dataElement = dataElementService.getDataElement( element );
+            
+            if ( AGGREGATION_OPERATOR_SUM.equals( dataElement.getAggregationOperator() ) )
+            {
+                map.putValue( AggregationType.SUM, element );
+            }
+            else if ( AGGREGATION_OPERATOR_AVERAGE.equals( dataElement.getAggregationOperator() ) )
+            {
+                PeriodType dataPeriodType = dataElement.getPeriodType();
+                
+                if ( dataPeriodType == null || aggregationPeriodType.getFrequencyOrder() >= dataPeriodType.getFrequencyOrder() )
+                {
+                    map.putValue( AggregationType.AVERAGE_AGGREGATION, element );
+                }
+                else
+                {
+                    map.putValue( AggregationType.AVERAGE_DISAGGREGATION, element );
+                }
+            }
+        }
+        
+        return map;
+    }
 }

=== 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	2012-12-21 16:50:36 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java	2012-12-27 19:15:15 +0000
@@ -30,6 +30,7 @@
 import static org.hisp.dhis.analytics.DataQueryParams.VALUE_ID;
 import static org.hisp.dhis.system.util.TextUtils.getCommaDelimitedString;
 import static org.hisp.dhis.system.util.TextUtils.getQuotedCommaDelimitedString;
+import static org.hisp.dhis.analytics.AggregationType.*;
 
 import java.util.HashMap;
 import java.util.List;
@@ -40,6 +41,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.analytics.AnalyticsManager;
 import org.hisp.dhis.analytics.DataQueryParams;
+import org.hisp.dhis.period.PeriodType;
 import org.hisp.dhis.system.util.SqlHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -76,9 +78,13 @@
         
         SqlHelper sqlHelper = new SqlHelper();
         
-        String sql = 
-            "select " + getCommaDelimitedString( dimensions ) + ", sum(value) as value " +
-            "from " + params.getTableName() + " ";
+        String sql = "select " + getCommaDelimitedString( dimensions ) + ", ";
+        
+        int days = PeriodType.getPeriodTypeByName( params.getPeriodType() ).getFrequencyOrder();
+        
+        sql += params.isAggregationType( AVERAGE_AGGREGATION ) ? "sum(daysxvalue) / " + days : "sum(value)";
+        
+        sql += " as value from " + params.getTableName() + " ";
             
         for ( String dim : dimensions )
         {