← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 9322: Analytics, impl support for group sets and xml response

 

------------------------------------------------------------
revno: 9322
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2012-12-14 16:04:48 +0100
message:
  Analytics, impl support for group sets and xml response
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/JdbcAnalyticsManager.java
  dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/TextUtils.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-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-12 15:47:03 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/DataQueryParams.java	2012-12-14 15:04:48 +0000
@@ -44,6 +44,7 @@
 {
     public static final String INDICATOR_DIM_ID = "in";
     public static final String DATAELEMENT_DIM_ID = "de";
+    public static final String CATEGORYOPTIONCOMBO_DIM_ID = "coc";
     public static final String PERIOD_DIM_ID = "pe";
     public static final String ORGUNIT_DIM_ID = "ou";
         
@@ -98,8 +99,6 @@
     {
         SortedMap<String, List<String>> map = new TreeMap<String, List<String>>();
         
-        // TODO convert indicators to data elements
-        
         map.put( DATAELEMENT_DIM_ID, dataElements );
         map.put( ORGUNIT_DIM_ID, organisationUnits );
         map.put( PERIOD_DIM_ID, periods );
@@ -115,6 +114,24 @@
         return map;
     }
     
+    public List<String> getDimensionNames()
+    {
+        List<String> list = new ArrayList<String>();
+        
+        list.add( DATAELEMENT_DIM_ID );
+        list.add( CATEGORYOPTIONCOMBO_DIM_ID );
+        list.add( PERIOD_DIM_ID );
+        list.add( ORGUNIT_DIM_ID );
+        list.addAll( dimensions.keySet() );
+        
+        return list;
+    }
+    
+    public List<String> getDynamicDimensionNames()
+    {
+        return new ArrayList<String>( dimensions.keySet() );
+    }
+        
     public void setDimension( String dimension, List<String> values )
     {
         if ( DATAELEMENT_DIM_ID.equals( dimension ) )

=== 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-14 12:37:06 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/DefaultAnalyticsService.java	2012-12-14 15:04:48 +0000
@@ -45,6 +45,8 @@
 public class DefaultAnalyticsService
     implements AnalyticsService
 {
+    private static final String VALUE_NAME = "value";
+    
     //TODO period aggregation for multiple period types
     //TODO hierarchy aggregation for org units at multiple levels
     //TODO indicator aggregation
@@ -59,11 +61,11 @@
         
         Grid grid = new ListGrid();
         
-        grid.addHeader( new GridHeader( "Data element", "de", String.class.getName(), false, true ) );
-        grid.addHeader( new GridHeader( "Category option combo", "coc", String.class.getName(), false, true ) );
-        grid.addHeader( new GridHeader( "Period", "de", String.class.getName(), false, true ) );
-        grid.addHeader( new GridHeader( "Organisation unit", "ou", String.class.getName(), false, true ) );
-        grid.addHeader( new GridHeader( "Value", "value", Double.class.getName(), false, false ) );
+        for ( String col : params.getDimensionNames() )
+        {
+            grid.addHeader( new GridHeader( col, false, true ) );
+            grid.addHeader( new GridHeader( VALUE_NAME, false, false ) );
+        }
         
         for ( Map.Entry<String, Double> entry : map.entrySet() )
         {

=== 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-14 12:37:06 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/data/JdbcAnalyticsManager.java	2012-12-14 15:04:48 +0000
@@ -27,9 +27,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static org.hisp.dhis.system.util.TextUtils.getCommaDelimitedString;
 import static org.hisp.dhis.system.util.TextUtils.getQuotedCommaDelimitedString;
 
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Future;
 
@@ -75,6 +77,8 @@
     // Implementation
     // -------------------------------------------------------------------------
 
+    //TODO optimize when all options in dimensions are selected
+    
     @Async
     public Future<Map<String, Double>> getAggregatedDataValueTotals( DataQueryParams params )
     {
@@ -82,14 +86,28 @@
         
         String periodType = PeriodType.getPeriodTypeFromIsoString( params.getPeriods().iterator().next() ).getName().toLowerCase();
         
-        final String sql = 
-            "SELECT dataelement, 0 as categoryoptioncombo, " + 
-            periodType + " as period, uidlevel" + level + " as organisationunit, SUM(value) as value " +
+        List<String> dimensions = params.getDimensionNames();        
+        List<String> extraDimensions = params.getDynamicDimensionNames();
+        
+        String sql = 
+            "SELECT " + dimensions.get( 0 ) + ", " + 
+            dimensions.get( 1 ) + ", " +
+            periodType + " as " + dimensions.get( 2 ) + ", " + 
+            "uidlevel" + level + " as " + dimensions.get( 3 ) + ", " +
+            getCommaDelimitedString( extraDimensions, false, true ) +
+            "SUM(value) as value " +
+            
             "FROM " + params.getTableName() + " " +
-            "WHERE dataelement IN ( " + getQuotedCommaDelimitedString( params.getDataElements() ) + " ) " +
+            "WHERE " + dimensions.get( 0 ) + " IN ( " + getQuotedCommaDelimitedString( params.getDataElements() ) + " ) " +
             "AND " + periodType + " IN ( " + getQuotedCommaDelimitedString( params.getPeriods() ) + " ) " +
             "AND uidlevel" + level + " IN ( " + getQuotedCommaDelimitedString( params.getOrganisationUnits() ) + " ) " +
-            "GROUP BY dataelement, " + periodType + ", uidlevel" + level;
+            getExtraDimensionQuery( params ) +
+        
+            "GROUP BY " + dimensions.get( 0 ) + ", " + 
+            dimensions.get( 1 ) + ", " +
+            periodType + ", " + 
+            "uidlevel" + level +
+            getCommaDelimitedString( extraDimensions, true, false );
 
         log.info( sql );
         
@@ -99,17 +117,38 @@
         
         while ( rowSet.next() )
         {
-            String key = 
-                rowSet.getString( "dataelement" ) + SEP +
-                rowSet.getString( "categoryoptioncombo" ) + SEP +
-                rowSet.getString( "period" ) + SEP +
-                rowSet.getString( "organisationunit" );
+            StringBuilder key = new StringBuilder();
+            
+            for ( String dim : dimensions )
+            {
+                key.append( rowSet.getString( dim ) + SEP );
+            }
+            
+            key.deleteCharAt( key.length() - SEP.length() );
             
             Double value = rowSet.getDouble( "value" );
             
-            map.put( key, value );
+            map.put( key.toString(), value );
         }
         
         return new AsyncResult<Map<String, Double>>( map );
     }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private String getExtraDimensionQuery( DataQueryParams params )
+    {
+        Map<String, List<String>> dimensionValues = params.getDimensions();
+        
+        String sql = "";
+        
+        for ( String dim : params.getDynamicDimensionNames() )
+        {
+            sql += "AND " + dim + " IN ( " + getQuotedCommaDelimitedString( dimensionValues.get( dim ) ) + " ) ";
+        }
+        
+        return sql;            
+    }    
 }

=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java	2012-12-14 12:37:06 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcAnalyticsTableManager.java	2012-12-14 15:04:48 +0000
@@ -86,7 +86,6 @@
     // Implementation
     // -------------------------------------------------------------------------
   
-    //TODO use uid instead of id
     //TODO average aggregation operator data, pre-aggregate in time dimension, not in org unit dimension
     
     public void createTable( String tableName )
@@ -231,8 +230,8 @@
             columns.add( col );
         }
         
-        String[] de = { "dataelement", "character(11) not null", "de.uid" };
-        String[] co = { "categoryoptioncombo", "character(11) not null", "coc.uid" };
+        String[] de = { "de", "character(11) not null", "de.uid" };
+        String[] co = { "coc", "character(11) not null", "coc.uid" };
         
         columns.addAll( Arrays.asList( de, co ) );
         

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/TextUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/TextUtils.java	2012-11-26 12:54:18 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/TextUtils.java	2012-12-14 15:04:48 +0000
@@ -39,6 +39,7 @@
     public static final TextUtils INSTANCE = new TextUtils();
     
     private static final Pattern LINK_PATTERN = Pattern.compile( "((http://|https://|www\\.).+?)($|\\n|\\r|\\r\\n| )" );
+    private static final String DELIMITER = ", ";
     
     /**
      * Performs the htmlNewline(String) and htmlLinks(String) methods against
@@ -152,26 +153,60 @@
     }
 
     /**
-     * Transforms a collection of Integers into a comma delimited String.
-     * 
-     * @param elements the collection of Integers
-     * @return a comma delimited String.
-     */
-    public static String getCommaDelimitedString( Collection<Integer> elements )
-    {
-        if ( elements != null && elements.size() > 0 )
-        {
-            final StringBuffer buffer = new StringBuffer();        
-        
-            for ( Integer element : elements )
-            {
-                buffer.append( element.toString() ).append( ", " );
-            }
-            
-            return buffer.substring( 0, buffer.length() - ", ".length() );
-        }
-        
-        return null;
+     * Transforms a collection of Integers into a comma delimited String. If the
+     * given collection of elements are null or is empty, an empty String is
+     * returned.
+     * 
+     * @param elements the collection of Integers
+     * @return a comma delimited String.
+     */
+    public static String getCommaDelimitedString( Collection<?> elements )
+    {
+        final StringBuilder builder = new StringBuilder();
+        
+        if ( elements != null && !elements.isEmpty() )
+        {
+            for ( Object element : elements )
+            {
+                builder.append( element.toString() ).append( DELIMITER );
+            }
+            
+            return builder.substring( 0, builder.length() - DELIMITER.length() );
+        }
+        
+        return builder.toString();
+    }
+
+    /**
+     * Transforms a collection of Integers into a comma delimited String. If the
+     * given collection of elements are null or is empty, an empty String is
+     * returned.
+     * 
+     * @param delimitPrefix whether to prefix the string with a delimiter.
+     * @param delimitSuffix whether to suffix the string with a delimiter.
+     * @param elements the collection of Integers
+     * @return a comma delimited String.
+     */
+    public static String getCommaDelimitedString( Collection<?> elements, boolean delimitPrefix, boolean delimitSuffix )
+    {
+        final StringBuilder builder = new StringBuilder();
+        
+        if ( elements != null && !elements.isEmpty() )
+        {
+            if ( delimitPrefix )
+            {
+                builder.append( DELIMITER );
+            }
+            
+            builder.append( getCommaDelimitedString( elements ) );
+            
+            if ( delimitSuffix )
+            {
+                builder.append( DELIMITER );
+            }
+        }
+        
+        return builder.toString();
     }
 
     /**

=== 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	2012-12-14 12:37:06 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AnalyticsController.java	2012-12-14 15:04:48 +0000
@@ -37,6 +37,7 @@
 import org.hisp.dhis.api.utils.ContextUtils.CacheStrategy;
 import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.system.grid.GridUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
@@ -54,18 +55,33 @@
     private ContextUtils contextUtils;
     
     @RequestMapping( method = RequestMethod.GET, consumes = { "application/json" }, produces = { "application/json" } )
-    public String get( InputStream in,
+    public String getJson( InputStream in,
         Model model,
         HttpServletResponse response ) throws Exception
     {
+        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.NO_CACHE ); //TODO
+        
         DataQueryParams params = JacksonUtils.fromJson( in, DataQueryParams.class );
         
         Grid grid = analyticsService.getAggregatedDataValueTotals( params );
         
         model.addAttribute( "model", grid );
         model.addAttribute( "viewClass", "detailed" );        
-        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_JSON, CacheStrategy.NO_CACHE ); //TODO
         
         return "grid";
     }
+
+    @RequestMapping( method = RequestMethod.GET, consumes = { "application/json" }, produces = { "application/xml" } )
+    public void getXml( InputStream in,
+        Model model,
+        HttpServletResponse response ) throws Exception
+    {
+        contextUtils.configureResponse( response, ContextUtils.CONTENT_TYPE_XML, CacheStrategy.NO_CACHE ); //TODO
+        
+        DataQueryParams params = JacksonUtils.fromJson( in, DataQueryParams.class );
+        
+        Grid grid = analyticsService.getAggregatedDataValueTotals( params );
+
+        GridUtils.toXml( grid, response.getOutputStream() );
+    }
 }