← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 2394: Work in progress - datamart / pivot view export

 

------------------------------------------------------------
revno: 2394
committer: Bob Joliffe <bobjolliffe@xxxxxxxxx>
branch nick: dhis2
timestamp: Sun 2010-12-19 00:24:59 +0000
message:
  Work in progress - datamart / pivot view export
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStoreIterator.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStoreIterator.java
  dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/synchronous/
  dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/synchronous/ExportPivotViewService.java
  dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/exp/ExportPivotViewAction.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueService.java*
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStore.java*
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/DefaultAggregatedDataValueService.java*
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStore.java*
  dhis-2/dhis-services/dhis-service-importexport/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportDataValue.hbm.xml
  dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportObject.hbm.xml
  dhis-2/dhis-web/dhis-web-importexport/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-importexport/src/main/resources/struts.xml


--
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/aggregation/AggregatedDataValueService.java' (properties changed: -x to +x)
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueService.java	2010-08-31 08:14:32 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueService.java	2010-12-19 00:24:59 +0000
@@ -11,6 +11,7 @@
 import org.hisp.dhis.dimension.DimensionOption;
 import org.hisp.dhis.indicator.Indicator;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitLevel;
 import org.hisp.dhis.period.Period;
 
 public interface AggregatedDataValueService
@@ -103,6 +104,16 @@
      */
     int deleteAggregatedDataValues();
 
+
+    /**
+     * Returns values for children of an orgunit at a particular level
+     * @param orgunit the root organisationunit
+     * @param level the level to retrieve values at
+     * @param periods the periods to retrieve values for
+     * @return an iterator type object for retrieving the values
+     */
+    public AggregatedDataValueStoreIterator getAggregateDataValuesAtLevel(OrganisationUnit orgunit, OrganisationUnitLevel level, Collection<Period> periods);
+
     // ----------------------------------------------------------------------
     // AggregatedDataMapValue
     // ----------------------------------------------------------------------

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStore.java' (properties changed: -x to +x)
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStore.java	2010-08-31 07:06:55 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStore.java	2010-12-19 00:24:59 +0000
@@ -9,6 +9,7 @@
 import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.dimension.DimensionOption;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitLevel;
 import org.hisp.dhis.period.Period;
 
 public interface AggregatedDataValueStore
@@ -146,6 +147,17 @@
      */
     int deleteAggregatedIndicatorValues();
 
+
+    /**
+     * Returns values for children of an orgunit at a particular level
+     * @param orgunit the root organisationunit
+     * @param level the level to retrieve values at
+     * @param periods the period to retrieve values for
+     * @return an iterator type object for retrieving the values
+     */
+    public AggregatedDataValueStoreIterator getAggregateDataValuesAtLevel(OrganisationUnit orgunit, OrganisationUnitLevel level, Collection<Period> periods);
+
+
     // ----------------------------------------------------------------------
     // AggregatedIndicatorMapValue
     // ----------------------------------------------------------------------

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStoreIterator.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStoreIterator.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/aggregation/AggregatedDataValueStoreIterator.java	2010-12-19 00:24:59 +0000
@@ -0,0 +1,55 @@
+package org.hisp.dhis.aggregation;
+
+/*
+ * Copyright (c) 2004-2010, 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.
+ */
+
+/**
+ * @interface AggregatedDataValueStoreIterator
+ * Provides an object for processing a collection of Aggregateddatavalues, such
+ *  as from a jdbc resultset
+ *
+ * @author bobj
+ */
+public interface AggregatedDataValueStoreIterator {
+
+    // ----------------------------------------------------------------------
+    // AggregatedDataValueStoreIterator
+    // ----------------------------------------------------------------------
+
+    /**
+     * Gets the next AggregatedDataValue
+     *
+     * @return the aggregated value or null.
+     */
+    AggregatedDataValue next();
+
+    /**
+     * Close any underlying resources
+     *
+     */
+    void close();
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/DefaultAggregatedDataValueService.java' (properties changed: -x to +x)
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/DefaultAggregatedDataValueService.java	2010-08-31 07:06:55 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/DefaultAggregatedDataValueService.java	2010-12-19 00:24:59 +0000
@@ -16,6 +16,7 @@
 import org.hisp.dhis.dimension.DimensionOption;
 import org.hisp.dhis.indicator.Indicator;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitLevel;
 import org.hisp.dhis.period.Period;
 
 public class DefaultAggregatedDataValueService
@@ -72,6 +73,11 @@
         return aggregatedDataValueStore.deleteAggregatedDataValues();
     }
 
+    public AggregatedDataValueStoreIterator getAggregateDataValuesAtLevel(OrganisationUnit orgunit, OrganisationUnitLevel level, Collection<Period> periods)
+    {
+       return aggregatedDataValueStore.getAggregateDataValuesAtLevel(orgunit, level, periods);
+    }
+
     // -------------------------------------------------------------------------
     // AggregatedDataMapValue
     // -------------------------------------------------------------------------

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStore.java' (properties changed: -x to +x)
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStore.java	2010-11-25 22:22:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStore.java	2010-12-19 00:24:59 +0000
@@ -1,10 +1,13 @@
 package org.hisp.dhis.aggregation.jdbc;
 
+import org.hisp.dhis.aggregation.AggregatedDataValueStoreIterator;
+import org.hisp.dhis.organisationunit.OrganisationUnitLevel;
 import static org.hisp.dhis.system.util.ConversionUtils.getIdentifiers;
 import static org.hisp.dhis.system.util.TextUtils.getCommaDelimitedString;
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.sql.Statement;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
@@ -12,6 +15,8 @@
 import org.amplecode.quick.StatementHolder;
 import org.amplecode.quick.StatementManager;
 import org.amplecode.quick.mapper.ObjectMapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.aggregation.AggregatedDataValue;
 import org.hisp.dhis.aggregation.AggregatedDataValueStore;
 import org.hisp.dhis.aggregation.AggregatedIndicatorValue;
@@ -37,6 +42,13 @@
 public class JdbcAggregatedDataValueStore
     extends HibernateGenericStore<CaseAggregationCondition> implements AggregatedDataValueStore
 {
+
+    // number of rows to fetch from db for large resultset
+    private int FETCH_SIZE = 100;
+
+    private static final Log log = LogFactory.getLog( JdbcAggregatedDataValueStore.class );
+
+
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
@@ -126,7 +138,46 @@
             holder.close();
         }
     }
-    
+
+    @Override
+    public AggregatedDataValueStoreIterator getAggregateDataValuesAtLevel(OrganisationUnit rootOrgunit, OrganisationUnitLevel level, Collection<Period> periods)
+    {
+        final StatementHolder holder = statementManager.getHolder();
+
+        try
+        {
+            int rootlevel = rootOrgunit.getLevel();
+
+            String periodids = getCommaDelimitedString( getIdentifiers(Period.class, periods));
+
+            final String sql =
+                "SELECT dataelementid, categoryoptioncomboid, periodid, adv.organisationunitid, periodtypeid, adv.level, value " +
+                "FROM aggregateddatavalue AS adv " +
+                "INNER JOIN _orgunitstructure AS ous on adv.organisationunitid=ous.organisationunitid " +
+                "WHERE adv.level = " + level.getLevel() +
+                " AND ous.idlevel" + rootlevel + "=" + rootOrgunit.getId() +
+                " AND adv.periodid IN (" + periodids + ") ";
+
+            log.info("sql: " + sql);
+
+            Statement statement = holder.getStatement();
+
+            statement.setFetchSize(FETCH_SIZE);
+
+            final ResultSet resultSet = statement.executeQuery( sql );
+
+            return new JdbcAggregatedDataValueStoreIterator(resultSet, holder);
+        }
+        catch ( SQLException ex )
+        {
+            throw new RuntimeException( "Failed to get aggregated data value", ex );
+        }
+        finally
+        {
+            // holder.close();
+        }
+    }
+
     public int deleteAggregatedDataValues( Collection<Integer> dataElementIds, Collection<Integer> periodIds, Collection<Integer> organisationUnitIds )
     {
         final String sql =

=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStoreIterator.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStoreIterator.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/aggregation/jdbc/JdbcAggregatedDataValueStoreIterator.java	2010-12-19 00:24:59 +0000
@@ -0,0 +1,103 @@
+package org.hisp.dhis.aggregation.jdbc;
+
+/*
+ * Copyright (c) 2004-2010, 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.sql.ResultSet;
+import java.sql.SQLException;
+import org.amplecode.quick.StatementHolder;
+import org.amplecode.quick.mapper.RowMapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.aggregation.AggregatedDataValue;
+import org.hisp.dhis.aggregation.AggregatedDataValueStoreIterator;
+import org.hisp.dhis.system.objectmapper.AggregatedDataValueRowMapper;
+
+/**
+ *
+ * @author bobj
+ */
+public class JdbcAggregatedDataValueStoreIterator implements AggregatedDataValueStoreIterator {
+
+    private static final Log log = LogFactory.getLog(AggregatedDataValueStoreIterator.class);
+
+    static RowMapper<AggregatedDataValue> rowmapper = new AggregatedDataValueRowMapper();
+
+    private ResultSet resultSet;
+
+    public ResultSet getResultSet() {
+        return resultSet;
+    }
+
+    public void setResultSet(ResultSet resultSet) {
+        this.resultSet = resultSet;
+    }
+
+    private StatementHolder holder;
+
+    public StatementHolder getHolder()
+    {
+        return holder;
+    }
+
+    public void setHolder( StatementHolder holder )
+    {
+        this.holder = holder;
+    }
+
+    public JdbcAggregatedDataValueStoreIterator(ResultSet resultSet, StatementHolder holder) {
+        this.resultSet = resultSet;
+        this.holder = holder;
+    }
+
+    @Override
+    public AggregatedDataValue next() {
+        AggregatedDataValue row = null;
+        try {
+            if (resultSet.next()) {
+                row = rowmapper.mapRow(resultSet);
+            } else {
+                this.close();
+            }
+        } catch (SQLException ex) {
+            log.warn("Error reading aggregateddatavalue row: " + ex);
+        }
+        return row;
+    }
+
+    @Override
+    public void close() {
+        try {
+            if (!resultSet.isClosed()) {
+                resultSet.close();
+            }
+        } catch (SQLException ex) {
+            log.warn("Error closing resultset: " + ex);
+        }
+
+        holder.close();
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/synchronous'
=== added file 'dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/synchronous/ExportPivotViewService.java'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/synchronous/ExportPivotViewService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/synchronous/ExportPivotViewService.java	2010-12-19 00:24:59 +0000
@@ -0,0 +1,125 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.hisp.dhis.importexport.synchronous;
+
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Date;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.aggregation.AggregatedDataValue;
+import org.hisp.dhis.aggregation.AggregatedDataValueService;
+import org.hisp.dhis.aggregation.AggregatedDataValueStore;
+import org.hisp.dhis.aggregation.AggregatedDataValueStoreIterator;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitLevel;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.period.MonthlyPeriodType;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodService;
+
+/**
+ * Exports pivot view synchronously (using calling thread)
+ *
+ * TODO: use exportparams and abstract service
+ * TODO: implement indicator and width-wise queries
+ *
+ * @author bobj
+ */
+
+public class ExportPivotViewService {
+
+    private static final Log log = LogFactory.getLog( ExportPivotViewService.class );
+
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private AggregatedDataValueService aggregatedDataValueService;
+
+    public void setAggregatedDataValueService( AggregatedDataValueService aggregatedDataValueService )
+    {
+        this.aggregatedDataValueService = aggregatedDataValueService;
+    }
+
+    private  OrganisationUnitService organisationUnitService;
+
+    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
+    {
+        this.organisationUnitService = organisationUnitService;
+    }
+
+    private PeriodService periodService;
+
+    public void setPeriodService( PeriodService periodService )
+    {
+        this.periodService = periodService;
+    }
+
+    public void execute (OutputStream out, Date startDate, Date endDate, int level, int root)
+        throws IOException
+    {
+        Writer writer = new BufferedWriter(new OutputStreamWriter(out));
+
+        // out.write("Hello World\n".getBytes());
+
+        Collection<Period> periods 
+            = periodService.getIntersectingPeriodsByPeriodType( new MonthlyPeriodType(), startDate, endDate );
+
+        if (periods.size() == 0)
+        {
+            log.info( "no periods to export");
+            return;
+        }
+
+        OrganisationUnit rootOrgUnit = organisationUnitService.getOrganisationUnit( root );
+
+        if (rootOrgUnit == null)
+        {
+            log.info( "no orgunit root to export with id = " + rootOrgUnit);
+            return;
+        }
+
+        rootOrgUnit.setLevel(organisationUnitService.getLevelOfOrganisationUnit( rootOrgUnit ));
+        
+        log.info("Orgunit: " + rootOrgUnit.getName());
+        log.info("Orgunit level: " + rootOrgUnit.getLevel());
+        
+        OrganisationUnitLevel orgUnitLevel = organisationUnitService.getOrganisationUnitLevelByLevel( level );
+
+        if (orgUnitLevel == null)
+        {
+            log.info( "no level with level id = " + orgUnitLevel);
+            return;
+        }
+
+        log.info( "Exporting for " + rootOrgUnit.getName() + " at level: " + orgUnitLevel.getName());
+
+        AggregatedDataValueStoreIterator advIterator = aggregatedDataValueService.getAggregateDataValuesAtLevel( rootOrgUnit , orgUnitLevel, periods );
+
+        AggregatedDataValue adv = advIterator.next();
+
+        while (adv != null)
+        {
+            // process adv ..
+            writer.write( adv.getPeriodId() + ",");
+            writer.write( adv.getOrganisationUnitId() + ",");
+            writer.write( adv.getDataElementId() + ",");
+            writer.write( adv.getCategoryOptionComboId() + ",");
+            writer.write( adv.getLevel() + "\n");
+
+            adv = advIterator.next();
+        }
+
+        writer.flush();
+    }
+
+}

=== modified file 'dhis-2/dhis-services/dhis-service-importexport/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/resources/META-INF/dhis/beans.xml	2010-12-09 05:53:20 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/resources/META-INF/dhis/beans.xml	2010-12-19 00:24:59 +0000
@@ -381,7 +381,18 @@
 		<property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 		<property name="expressionService" ref="org.hisp.dhis.expression.ExpressionService" />
 	</bean>
-	
+
+	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+	<!-- PivotViewExport                                                    -->
+	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+
+	<bean id="org.hisp.dhis.importexport.synchronous.ExportPivotViewService"
+		class="org.hisp.dhis.importexport.synchronous.ExportPivotViewService">
+		<property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
+		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
+        <property name="aggregatedDataValueService" ref="org.hisp.dhis.aggregation.AggregatedDataValueService" />
+	</bean>
+
 	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
 	<!-- Mapping                                                       -->
 	<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

=== modified file 'dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportDataValue.hbm.xml'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportDataValue.hbm.xml	2009-08-12 21:06:37 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportDataValue.hbm.xml	2010-12-19 00:24:59 +0000
@@ -1,29 +1,17 @@
-<?xml version="1.0"?>
-<!DOCTYPE hibernate-mapping PUBLIC
-  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
-  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
-
-<hibernate-mapping>
-	
-	<class name="org.hisp.dhis.importexport.ImportDataValue" table="importdatavalue">
-
-	<composite-id>
-	   <key-property name="dataElementId" column="dataelementid"/>
-        <key-property name="categoryOptionComboId" column="categoryoptioncomboid"/>
-        <key-property name="periodId" column="periodid"/>	
-        <key-property name="sourceId" column="sourceid"/>
-    </composite-id>
-		
-    <property name="value" column="value"/>
-		
-    <property name="storedBy" column="storedby"/>
-		
-    <property name="timestamp" column="lastupdated" type="date"/>
-		
-    <property name="comment" column="comment" type="text"/>
-		
-	<property name="status" column="status"/>
-		
-	</class>
-
-</hibernate-mapping>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
+<hibernate-mapping>
+  <class name="org.hisp.dhis.importexport.ImportDataValue" table="importdatavalue">
+    <composite-id>
+      <key-property column="dataelementid" name="dataElementId"/>
+      <key-property column="categoryoptioncomboid" name="categoryOptionComboId"/>
+      <key-property column="periodid" name="periodId"/>
+      <key-property column="sourceid" name="sourceId"/>
+    </composite-id>
+    <property column="value" name="value"/>
+    <property column="storedby" name="storedBy"/>
+    <property column="lastupdated" name="timestamp" type="date"/>
+    <property column="comment" name="comment" type="text"/>
+    <property column="status" name="status"/>
+  </class>
+</hibernate-mapping>

=== modified file 'dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportObject.hbm.xml'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportObject.hbm.xml	2009-08-12 21:06:37 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/resources/org/hisp/dhis/importexport/hibernate/ImportObject.hbm.xml	2010-12-19 00:24:59 +0000
@@ -1,26 +1,14 @@
-<?xml version="1.0"?>
-<!DOCTYPE hibernate-mapping PUBLIC
-  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
-  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
-
-<hibernate-mapping>
-	
-	<class name="org.hisp.dhis.importexport.ImportObject" table="importobject">
-		    
-    <id name="id" column="importobjectid">
-      <generator class="native"/>
-    </id>
-
-    <property name="status" column="status"/>
-
-    <property name="className" column="classname"/>
-		
-    <property name="groupMemberType" column="groupmembertype"/>
-
-    <property name="object" column="object" type="serializable" length="65535"/>
-		
-    <property name="compareObject" column="compareobject" type="serializable" length="65535"/>
-	
-	</class>
-
-</hibernate-mapping>
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd";>
+<hibernate-mapping>
+  <class name="org.hisp.dhis.importexport.ImportObject" table="importobject">
+    <id column="importobjectid" name="id">
+      <generator class="native"/>
+    </id>
+    <property column="status" name="status"/>
+    <property column="classname" name="className"/>
+    <property column="groupmembertype" name="groupMemberType"/>
+    <property column="object" length="65535" name="object" type="serializable"/>
+    <property column="compareobject" length="65535" name="compareObject" type="serializable"/>
+  </class>
+</hibernate-mapping>

=== added file 'dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/exp/ExportPivotViewAction.java'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/exp/ExportPivotViewAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/exp/ExportPivotViewAction.java	2010-12-19 00:24:59 +0000
@@ -0,0 +1,225 @@
+package org.hisp.dhis.importexport.action.exp;
+
+/*
+ * Copyright (c) 2004-2010, 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.Date;
+
+import org.hisp.dhis.user.CurrentUserService;
+
+import com.opensymphony.xwork2.Action;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.ServletActionContext;
+import org.hisp.dhis.importexport.synchronous.ExportPivotViewService;
+import org.hisp.dhis.system.util.DateUtils;
+import org.hisp.dhis.system.util.StreamUtils;
+
+/**
+ * @author Bob Jolliffe
+ *
+ * This action is called to export a csv formatted selection from the datamart
+ * It requires 4 parameters:
+ * startdate and enddate: 8 character string representation of date - 20100624
+ * root: id of root organization unit
+ * level: level number to fetch aggregated values for
+ */
+public class ExportPivotViewAction
+    implements Action
+{
+
+    private static final Log log = LogFactory.getLog( ExportPivotViewAction.class );
+
+    private static final DateFormat dateFormat = new SimpleDateFormat( "yyyyMMdd" );
+    // parameter errors
+
+    private static final String NO_STARTDATE = "The request is missing a startDate parameter";
+
+    private static final String NO_ENDDATE = "The request is missing an endDate parameter";
+
+    private static final String BAD_STARTDATE = "The request has a bad startDate parameter. Required format is YYYMMDD";
+
+    private static final String BAD_ENDDATE = "The request has a bad endDate parameter. Required format is YYYMMDD";
+
+    private static final String NO_ROOT = "The request is missing a non-zero dataSourceRoot parameter";
+
+    private static final String NO_LEVEL = "The request is missing a non-zero datasourceLevel parameter";
+    // http header result type
+
+    private static final String CLIENT_ERROR = "client-error";
+
+    private static final int HTTP_ERROR = 400;
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private CurrentUserService currentUserService;
+
+    public void setCurrentUserService( CurrentUserService currentUserService )
+    {
+        this.currentUserService = currentUserService;
+    }
+
+    private ExportPivotViewService exportPivotViewService;
+
+    public void setExportPivotViewService( ExportPivotViewService exportPivotViewService )
+    {
+        this.exportPivotViewService = exportPivotViewService;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private String startDate;
+
+    public void setStartDate( String startDate )
+    {
+        this.startDate = startDate;
+    }
+
+    private String endDate;
+
+    public void setEndDate( String endDate )
+    {
+        this.endDate = endDate;
+    }
+
+    private int dataSourceLevel;
+
+    public void setDataSourceLevel( int dataSourceLevel )
+    {
+        this.dataSourceLevel = dataSourceLevel;
+    }
+
+    private int dataSourceRoot;
+
+    public void setDataSourceRoot( int dataSourceRoot )
+    {
+        this.dataSourceRoot = dataSourceRoot;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+    public String execute() throws IOException
+    {
+        // do a basic audit log
+        HttpServletRequest request = ServletActionContext.getRequest();
+
+        log.info( "PivotView export request from " + currentUserService.getCurrentUsername() +
+            " @ " + request.getRemoteAddr() );
+
+        HttpServletResponse response = ServletActionContext.getResponse();
+
+        // ---------------------------------------------------------------------
+        // Check all parameters
+        // ---------------------------------------------------------------------
+
+        String paramError = null;
+
+        if ( startDate == null )
+        {
+            paramError = NO_STARTDATE;
+        }
+
+        if ( endDate == null )
+        {
+            paramError = NO_ENDDATE;
+        }
+
+        if ( dataSourceRoot == 0 )
+        {
+            paramError = NO_ROOT;
+        }
+
+        if ( dataSourceLevel == 0 )
+        {
+            paramError = NO_LEVEL;
+        }
+
+        Date start = null;
+        Date end = null;
+
+        if ( paramError == null )
+        {
+            try
+            {
+                start = dateFormat.parse( startDate );
+
+                if ( start == null )
+                {
+                    paramError = BAD_STARTDATE;
+                }
+
+                end = dateFormat.parse( endDate );
+
+                if ( end == null )
+                {
+                    paramError = BAD_ENDDATE;
+                }
+            } catch ( java.text.ParseException ex )
+            {
+                paramError = ex.getMessage();
+            }
+        }
+
+        if ( paramError != null )
+        {
+            response.sendError( HTTP_ERROR, paramError );
+            log.info( paramError );
+            return CLIENT_ERROR;
+        }
+
+        // prepare to write output
+        OutputStream out = null;
+
+        // response.setContentType( "application/gzip");
+        // response.addHeader( "Content-Disposition", "attachment; filename=\"test.csv\"" );
+        response.addHeader( "Cache-Control", "no-cache" );
+        response.addHeader( "Expires", DateUtils.getExpiredHttpDateString() );
+
+        try
+        {
+            out = response.getOutputStream();
+            exportPivotViewService.execute(out, start, end, dataSourceLevel, dataSourceRoot);
+        }
+        finally
+        {
+            StreamUtils.closeOutputStream( out );
+        }
+
+        return SUCCESS;
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/resources/META-INF/dhis/beans.xml	2010-07-30 12:59:39 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/resources/META-INF/dhis/beans.xml	2010-12-19 00:24:59 +0000
@@ -186,6 +186,13 @@
 		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
 	</bean>
 
+        <bean id="org.hisp.dhis.importexport.action.exp.ExportPivotViewAction"
+		class="org.hisp.dhis.importexport.action.exp.ExportPivotViewAction"
+		scope="prototype">
+		<property name="currentUserService" ref="org.hisp.dhis.user.CurrentUserService" />
+		<property name="exportPivotViewService" ref="org.hisp.dhis.importexport.synchronous.ExportPivotViewService" />
+	</bean>
+
 	<bean id="org.hisp.dhis.importexport.action.exp.GetExportStatusAction"
 		class="org.hisp.dhis.importexport.action.exp.GetExportStatusAction"
 		scope="prototype">

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/resources/struts.xml	2010-11-19 09:27:17 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/resources/struts.xml	2010-12-19 00:24:59 +0000
@@ -168,13 +168,8 @@
         <param name="contentDisposition">filename="${fileName}"</param>
         <param name="bufferSize">10240</param>				
       </result>
-	</action>
-	
-	<action name="exportDataMart" class="org.hisp.dhis.importexport.action.exp.ExportDataMartAction">
-	  <result name="success" type="velocity-xml">/dhis-web-importexport/responseSuccess.vm</result>
-      <param name="onExceptionReturn">plainTextError</param>
     </action>
-    
+
     <action name="getExportStatus" class="org.hisp.dhis.importexport.action.exp.GetExportStatusAction">
       <result name="success" type="velocity-xml">/dhis-web-importexport/responseExportStatus.vm</result>
       <param name="onExceptionReturn">plainTextError</param>
@@ -195,7 +190,13 @@
       <result name="error" type="velocity-xml">/dhis-web-importexport/responseError.vm</result>
       <param name="onExceptionReturn">plainTextError</param>
     </action>
-    
+
+    <action name="exportPivotView" class="org.hisp.dhis.importexport.action.exp.ExportPivotViewAction">
+      <result name="success" type="outputStreamResult" />
+      <result name="client-error" type="httpheader">
+      </result>
+    </action>
+
     <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
     <!-- Dhis 1.4 Configuration                                        -->
     <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->