← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 13042: Implement unit tests on PatientAggregateReport service methods

 

------------------------------------------------------------
revno: 13042
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2013-11-28 13:19:32 +0700
message:
  Implement unit tests on PatientAggregateReport service methods
removed:
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionManager.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/jdbc/
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionManager.java
added:
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportServiceTest.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportStoreTest.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionStore.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/hibernate/HibernateCaseAggregationConditionStore.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/patientreport/hibernate/HibernatePatientAggregateReportStore.java
  dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-patient/src/test/java/org/hisp/dhis/patient/PatientStoreTest.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/TestCaseAggregationConditionAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.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/caseaggregation/CaseAggregationConditionService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java	2013-08-23 15:56:19 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java	2013-11-28 06:19:32 +0000
@@ -55,7 +55,7 @@
     void deleteCaseAggregationCondition( CaseAggregationCondition caseAggregationCondition );
 
     CaseAggregationCondition getCaseAggregationCondition( int id );
-    
+
     CaseAggregationCondition getCaseAggregationCondition( String name );
 
     Collection<CaseAggregationCondition> getAllCaseAggregationCondition();
@@ -67,12 +67,6 @@
 
     Collection<CaseAggregationCondition> getCaseAggregationCondition( Collection<DataElement> dataElements );
 
-    Grid getAggregateValue( CaseAggregationCondition aggregationCondition, Collection<Integer> orgunitIds,
-        Period period, I18nFormat format, I18n i18n );
-
-    void insertAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
-        Period period );
-    
     Collection<DataElement> getDataElementsInCondition( String aggregationExpression );
 
     Collection<Program> getProgramsInCondition( String aggregationExpression );
@@ -81,11 +75,41 @@
 
     String getConditionDescription( String condition );
 
+    /**
+     * Aggregate data values from query builder formulas defined based on
+     * datasets which have data elements defined in the formulas
+     * 
+     * @param caseAggregateSchedule
+     * @param taskStrategy Specify how to get period list based on period type
+     *        of each dataset. There are four options, include last month, last
+     *        3 month, last 6 month and last 12 month
+     */
     void aggregate( List<CaseAggregateSchedule> caseAggregateSchedules, String taskStrategy );
 
-    boolean hasOrgunitProgramStageCompleted( String expresstion );
-    
-    Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit, Period period,
-        I18nFormat format, I18n i18n );
-    
+    /**
+     * Return a data value table aggregated of a query builder formula
+     * 
+     * @param caseAggregationCondition The query builder expression
+     * @param orgunitIds The ids of organisation unit where to aggregate data
+     *        value
+     * @param period The date range for aggregate data value
+     * @param format
+     * @param i18n
+     */
+    Grid getAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
+        Period period, I18nFormat format, I18n i18n );
+
+    void insertAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
+        Period period );
+
+    Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
+        Period period, I18nFormat format, I18n i18n );
+
+    String parseExpressionToSql( boolean isInsert, String caseExpression, String operator, Integer aggregateDeId,
+        String aggregateDeName, Integer optionComboId, String optionComboName, Integer deSumId,
+        Collection<Integer> orgunitIds, Period period );
+
+    String parseExpressionDetailsToSql( String caseExpression, String operator, Integer orgunitId, Period period );
+
+    List<Integer> executeSQL( String sql );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionStore.java	2013-08-23 15:56:19 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionStore.java	2013-11-28 06:19:32 +0000
@@ -29,10 +29,16 @@
  */
 
 import java.util.Collection;
+import java.util.List;
 
 import org.hisp.dhis.common.GenericNameableObjectStore;
+import org.hisp.dhis.common.Grid;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.i18n.I18n;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.period.Period;
 
 /**
  * @author Chau Thu Tran
@@ -49,5 +55,67 @@
     CaseAggregationCondition get( DataElement dataElement, DataElementCategoryOptionCombo optionCombo );
 
     Collection<CaseAggregationCondition> get( Collection<DataElement> dataElements );
-    
+
+    /**
+     * Generate period list based on period Type and taskStrategy option
+     * 
+     * @param periodTypeName The name of period type
+     * @param taskStrategy Specify how to get period list based on period type
+     *        of each dataset. There are four options, include last month, last
+     *        3 month, last 6 month and last 12 month
+     * 
+     */
+    Collection<Period> getPeriods( String periodTypeName, String taskStrategy );
+
+    Grid getAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
+        Period period, I18nFormat format, I18n i18n );
+
+    Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
+        Period period, I18nFormat format, I18n i18n );
+
+    /**
+     * Insert data values into database directly
+     * 
+     * @param caseAggregationCondition The query builder expression
+     * @param orgunitIds The ids of organisation unit where to aggregate data
+     *        value
+     * @param period The date range for aggregate data value
+     */
+    void insertAggregateValue( String expression, String operator, Integer dataElementId, Integer optionComboId,
+        Integer deSumId, Collection<Integer> orgunitIds, Period period );
+
+    /**
+     * Return standard SQL from query builder formula
+     * 
+     * @param isInsert Insert aggregate result into database directly
+     * @param caseExpression The query builder expression
+     * @param operator There are six operators, includes Number of persons,
+     *        Number of visits, Sum, Average, Minimum and Maximum of data
+     *        element values.
+     * @param aggregateDeId The id of aggregate data element
+     * @param aggregateDeName The name of aggregate data element
+     * @param optionComboId The id of category option combo
+     * @param optionComboName The name of category option combo
+     * @param deSumId The id of aggregate data element which used for aggregate
+     *        data values for operator Sum, Average, Minimum and Maximum of data
+     *        element values. This fill is null for other operators.
+     * @param orgunitId The id of organisation unit where to aggregate data
+     *        value
+     * @param startDate Start date
+     * @param endDate End date
+     */
+    String parseExpressionToSql( boolean isInsert, String caseExpression, String operator, Integer aggregateDeId,
+        String aggregateDeName, Integer optionComboId, String optionComboName, Integer deSumId,
+        Collection<Integer> orgunitIds, Period period );
+
+    /**
+     * Aggregate data values for the dataset by periods with a organisation unit
+     * list
+     * 
+     */
+    void runAggregate( Collection<Integer> orgunitIds, CaseAggregateSchedule dataSet, Collection<Period> periods );
+
+    String parseExpressionDetailsToSql( String caseExpression, String operator, Integer orgunitId, Period period );
+
+    List<Integer> executeSQL( String sql );
 }

=== removed file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionManager.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionManager.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionManager.java	1970-01-01 00:00:00 +0000
@@ -1,114 +0,0 @@
-package org.hisp.dhis.caseaggregation;
-
-/*
- * Copyright (c) 2004-2013, 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.Collection;
-import java.util.List;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.Future;
-
-import org.hisp.dhis.common.Grid;
-import org.hisp.dhis.i18n.I18n;
-import org.hisp.dhis.i18n.I18nFormat;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.period.Period;
-
-/**
- * @author Chau Thu Tran
- */
-public interface CaseAggregationConditionManager
-{
-    List<Integer> executeSQL( String sql );
-
-    /**
-     * Aggregate data values from query builder formulas defined based on
-     * datasets which have data elements defined in the formulas
-     * 
-     * @param caseAggregateSchedule
-     * @param taskStrategy Specify how to get period list based on period type
-     *        of each dataset. There are four options, include last month, last
-     *        3 month, last 6 month and last 12 month
-     */
-    Future<?> aggregate( ConcurrentLinkedQueue<CaseAggregateSchedule> caseAggregateSchedule, String taskStrategy );
-
-    /**
-     * Return a data value table aggregated of a query builder formula
-     * 
-     * @param caseAggregationCondition The query builder expression
-     * @param orgunitIds The ids of organisation unit where to aggregate data
-     *        value
-     * @param period The date range for aggregate data value
-     * @param format
-     * @param i18n
-     */
-    Grid getAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
-        Period period, I18nFormat format, I18n i18n );
-
-    /**
-     * Insert data values into database directly
-     * 
-     * @param caseAggregationCondition The query builder expression
-     * @param orgunitIds The ids of organisation unit where to aggregate data
-     *        value
-     * @param period The date range for aggregate data value
-     */
-    void insertAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
-        Period period );
-
-    /**
-     * Return standard SQL from query builder formula
-     * 
-     * @param isInsert Insert aggregate result into database directly
-     * @param caseExpression The query builder expression
-     * @param operator There are six operators, includes Number of persons,
-     *        Number of visits, Sum, Average, Minimum and Maximum of data
-     *        element values.
-     * @param aggregateDeId The id of aggregate data element
-     * @param aggregateDeName The name of aggregate data element
-     * @param optionComboId The id of category option combo
-     * @param optionComboName The name of category option combo
-     * @param deSumId The id of aggregate data element which used for aggregate
-     *        data values for operator Sum, Average, Minimum and Maximum of data
-     *        element values. This fill is null for other operators.
-     * @param orgunitId The id of organisation unit where to aggregate data
-     *        value
-     * @param startDate Start date
-     * @param endDate End date
-     */
-    String parseExpressionToSql( boolean isInsert, String caseExpression, String operator, Integer aggregateDeId,
-        String aggregateDeName, Integer optionComboId, String optionComboName, Integer deSumId,
-        Collection<Integer> orgunitIds, Period period );
-
-    boolean hasOrgunitProgramStageCompleted( String expresstion );
-    
-    Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
-        Period period, I18nFormat format, I18n i18n );
-    
-    String parseExpressionDetailsToSql( String caseExpression, String operator, Integer orgunitId, Period period );
-}

=== modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java	2013-11-28 06:19:32 +0000
@@ -64,6 +64,7 @@
 import org.hisp.dhis.program.ProgramStageService;
 import org.hisp.dhis.system.util.ConcurrentUtils;
 import org.hisp.dhis.system.util.SystemUtils;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -85,8 +86,6 @@
 
     private CaseAggregationConditionStore aggregationConditionStore;
 
-    private CaseAggregationConditionManager aggregationConditionManager;
-
     private DataElementService dataElementService;
 
     private ProgramStageService programStageService;
@@ -106,11 +105,6 @@
         this.aggregationConditionStore = aggregationConditionStore;
     }
 
-    public void setAggregationConditionManager( CaseAggregationConditionManager aggregationConditionManager )
-    {
-        this.aggregationConditionManager = aggregationConditionManager;
-    }
-
     public void setPatientAttributeService( PatientAttributeService patientAttributeService )
     {
         this.patientAttributeService = patientAttributeService;
@@ -189,28 +183,6 @@
         return i18n( i18nService, aggregationConditionStore.get( dataElement, optionCombo ) );
     }
 
-    @Override
-    public Grid getAggregateValue( CaseAggregationCondition aggregationCondition, Collection<Integer> orgunitIds,
-        Period period, I18nFormat format, I18n i18n )
-    {
-        return aggregationConditionManager.getAggregateValue( aggregationCondition, orgunitIds, period, format, i18n );
-    }
-
-    @Override
-    public Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
-        Period period, I18nFormat format, I18n i18n )
-    {
-        return aggregationConditionManager.getAggregateValueDetails( aggregationCondition, orgunit, period, format,
-            i18n );
-    }
-
-    @Override
-    public void insertAggregateValue( CaseAggregationCondition caseAggregationCondition,
-        Collection<Integer> orgunitIds, Period period )
-    {
-        aggregationConditionManager.insertAggregateValue( caseAggregationCondition, orgunitIds, period );
-    }
-
     public String getConditionDescription( String condition )
     {
         StringBuffer description = new StringBuffer();
@@ -422,15 +394,81 @@
 
         for ( int i = 0; i < getProcessNo(); i++ )
         {
-            futures.add( aggregationConditionManager.aggregate( datasetQ, taskStrategy ) );
+            futures.add( aggregateValueManager( datasetQ, taskStrategy ) );
         }
 
         ConcurrentUtils.waitForCompletion( futures );
     }
 
-    public boolean hasOrgunitProgramStageCompleted( String expresstion )
-    {
-        return aggregationConditionManager.hasOrgunitProgramStageCompleted( expresstion );
+    @Async
+    private Future<?> aggregateValueManager( ConcurrentLinkedQueue<CaseAggregateSchedule> caseAggregateSchedule,
+        String taskStrategy )
+    {
+        taskLoop: while ( true )
+        {
+            CaseAggregateSchedule dataSet = caseAggregateSchedule.poll();
+
+            if ( dataSet == null )
+            {
+                break taskLoop;
+            }
+
+            Collection<Period> periods = aggregationConditionStore.getPeriods( dataSet.getPeriodTypeName(),
+                taskStrategy );
+
+            aggregationConditionStore.runAggregate( null, dataSet, periods );
+        }
+
+        return null;
+    }
+
+    public Grid getAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
+        Period period, I18nFormat format, I18n i18n )
+    {
+        return aggregationConditionStore.getAggregateValue( caseAggregationCondition, orgunitIds, period, format, i18n );
+    }
+
+    @Override
+    public Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
+        Period period, I18nFormat format, I18n i18n )
+    {
+        return aggregationConditionStore.getAggregateValueDetails( aggregationCondition, orgunit, period, format, i18n );
+    }
+
+    /**
+     * Insert data elements into database directly
+     * 
+     */
+    public void insertAggregateValue( CaseAggregationCondition caseAggregationCondition,
+        Collection<Integer> orgunitIds, Period period )
+    {
+        Integer deSumId = (caseAggregationCondition.getDeSum() == null) ? null : caseAggregationCondition.getDeSum()
+            .getId();
+
+        aggregationConditionStore.insertAggregateValue( caseAggregationCondition.getAggregationExpression(),
+            caseAggregationCondition.getOperator(), caseAggregationCondition.getAggregationDataElement().getId(),
+            caseAggregationCondition.getOptionCombo().getId(), deSumId, orgunitIds, period );
+    }
+
+    @Override
+    public String parseExpressionDetailsToSql( String caseExpression, String operator, Integer orgunitId, Period period )
+    {
+        return aggregationConditionStore.parseExpressionDetailsToSql( caseExpression, operator, orgunitId, period );
+    }
+
+    @Override
+    public String parseExpressionToSql( boolean isInsert, String caseExpression, String operator,
+        Integer aggregateDeId, String aggregateDeName, Integer optionComboId, String optionComboName, Integer deSumId,
+        Collection<Integer> orgunitIds, Period period )
+    {
+        return parseExpressionToSql( isInsert, caseExpression, operator, aggregateDeId, aggregateDeName, optionComboId,
+            optionComboName, deSumId, orgunitIds, period );
+    }
+
+    @Override
+    public List<Integer> executeSQL( String sql )
+    {
+        return executeSQL( sql );
     }
 
     // -------------------------------------------------------------------------

=== modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/hibernate/HibernateCaseAggregationConditionStore.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/hibernate/HibernateCaseAggregationConditionStore.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/hibernate/HibernateCaseAggregationConditionStore.java	2013-11-28 06:19:32 +0000
@@ -28,14 +28,58 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_ATTRIBUTE;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_PROPERTY;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_PROPERTY;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_STAGE;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_STAGE_DATAELEMENT;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_STAGE_PROPERTY;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_ID;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_OBJECT;
+import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_12_MONTH;
+import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_3_MONTH;
+import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_6_MONTH;
+import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_MONTH;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Calendar;
 import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.hibernate.criterion.Restrictions;
+import org.hisp.dhis.caseaggregation.CaseAggregateSchedule;
 import org.hisp.dhis.caseaggregation.CaseAggregationCondition;
 import org.hisp.dhis.caseaggregation.CaseAggregationConditionStore;
+import org.hisp.dhis.common.Grid;
+import org.hisp.dhis.common.GridHeader;
 import org.hisp.dhis.common.hibernate.HibernateIdentifiableObjectStore;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.i18n.I18n;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.jdbc.StatementBuilder;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.period.CalendarPeriodType;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodType;
+import org.hisp.dhis.system.grid.ListGrid;
+import org.hisp.dhis.system.util.DateUtils;
+import org.hisp.dhis.system.util.TextUtils;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
 
 /**
  * @author Chau Thu Tran
@@ -46,6 +90,49 @@
     extends HibernateIdentifiableObjectStore<CaseAggregationCondition>
     implements CaseAggregationConditionStore
 {
+    private final String IS_NULL = "is null";
+
+    private final String PROPERTY_AGE = "age";
+
+    private final String IN_CONDITION_GET_ALL = "*";
+
+    private final String IN_CONDITION_START_SIGN = "@";
+
+    private final String IN_CONDITION_END_SIGN = "#";
+
+    private final String IN_CONDITION_COUNT_X_TIMES = "COUNT";
+
+    public static final String STORED_BY_DHIS_SYSTEM = "DHIS-System";
+
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private JdbcTemplate jdbcTemplate;
+
+    public void setJdbcTemplate( JdbcTemplate jdbcTemplate )
+    {
+        this.jdbcTemplate = jdbcTemplate;
+    }
+
+    private StatementBuilder statementBuilder;
+
+    public void setStatementBuilder( StatementBuilder statementBuilder )
+    {
+        this.statementBuilder = statementBuilder;
+    }
+
+    private DataElementService dataElementService;
+
+    public void setDataElementService( DataElementService dataElementService )
+    {
+        this.dataElementService = dataElementService;
+    }
+
+    // -------------------------------------------------------------------------
+    // Implementation Methods
+    // -------------------------------------------------------------------------
+
     @SuppressWarnings( "unchecked" )
     @Override
     public Collection<CaseAggregationCondition> get( DataElement dataElement )
@@ -66,4 +153,1015 @@
     {
         return getCriteria( Restrictions.in( "aggregationDataElement", dataElements ) ).list();
     }
+
+    public Grid getAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
+        Period period, I18nFormat format, I18n i18n )
+    {
+        Collection<Integer> _orgunitIds = getServiceOrgunit( DateUtils.getMediumDateString( period.getStartDate() ),
+            DateUtils.getMediumDateString( period.getEndDate() ) );
+        _orgunitIds.retainAll( orgunitIds );
+
+        if ( _orgunitIds.size() > 0 )
+        {
+            Grid grid = new ListGrid();
+            grid.setTitle( caseAggregationCondition.getDisplayName() );
+            grid.setSubtitle( format.formatPeriod( period ) );
+
+            grid.addHeader( new GridHeader( i18n.getString( "dataelementid" ), true, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "categoryoptioncomboid" ), true, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "periodid" ), true, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "organisationunitid" ), true, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "comment" ), true, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "dataelementname" ), false, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "categoryoptioncomboname" ), false, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "organisationunitname" ), false, true ) );
+            grid.addHeader( new GridHeader( i18n.getString( "value" ), false, true ) );
+
+            Integer deSumId = (caseAggregationCondition.getDeSum() == null) ? null : caseAggregationCondition
+                .getDeSum().getId();
+            String sql = parseExpressionToSql( false, caseAggregationCondition.getAggregationExpression(),
+                caseAggregationCondition.getOperator(), caseAggregationCondition.getAggregationDataElement().getId(),
+                caseAggregationCondition.getAggregationDataElement().getDisplayName(), caseAggregationCondition
+                    .getOptionCombo().getId(), caseAggregationCondition.getOptionCombo().getDisplayName(), deSumId,
+                _orgunitIds, period );
+
+            SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
+            grid.addRows( rs );
+
+            return grid;
+        }
+
+        return null;
+    }
+
+    @Override
+    public Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
+        Period period, I18nFormat format, I18n i18n )
+    {
+        Grid grid = new ListGrid();
+        grid.setTitle( orgunit.getName() + " - " + aggregationCondition.getDisplayName() );
+        grid.setSubtitle( format.formatPeriod( period ) );
+
+        String sql = parseExpressionDetailsToSql( aggregationCondition.getAggregationExpression(),
+            aggregationCondition.getOperator(), orgunit.getId(), period );
+
+        SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
+
+        for ( String colName : rs.getMetaData().getColumnNames() )
+        {
+            grid.addHeader( new GridHeader( i18n.getString( colName ), false, true ) );
+        }
+
+        grid.addRows( rs );
+
+        return grid;
+    }
+
+    public void insertAggregateValue( String expression, String operator, Integer dataElementId, Integer optionComboId,
+        Integer deSumId, Collection<Integer> orgunitIds, Period period )
+    {
+        // Delete all data value from this period which created from DHIS-system
+        // after to run Aggregate Query Builder
+
+        String periodtypeSql = "select periodtypeid from periodtype where name='" + period.getPeriodType().getName()
+            + "'";
+        int periodTypeId = jdbcTemplate.queryForObject( periodtypeSql, Integer.class );
+
+        String periodSql = "select periodid from period where periodtypeid=" + periodTypeId + " and startdate='"
+            + DateUtils.getMediumDateString( period.getStartDate() ) + "' and enddate='"
+            + DateUtils.getMediumDateString( period.getEndDate() ) + "'";
+
+        SqlRowSet rs = jdbcTemplate.queryForRowSet( periodSql );
+
+        int periodid = 0;
+        if ( rs.next() )
+        {
+            periodid = rs.getInt( "periodid" );
+        }
+
+        if ( periodid == 0 )
+        {
+            String insertSql = "insert into period (periodtypeid,startdate,enddate) " + " VALUES " + "("
+                + period.getPeriodType().getId() + ",'" + DateUtils.getMediumDateString( period.getStartDate() )
+                + "','" + DateUtils.getMediumDateString( period.getEndDate() ) + "' )";
+            jdbcTemplate.execute( insertSql );
+
+            period.setId( jdbcTemplate.queryForObject( insertSql, Integer.class ) );
+        }
+        else
+        {
+            period.setId( periodid );
+
+            String deleteDataValueSql = "delete from datavalue where dataelementid=" + dataElementId
+                + " and categoryoptioncomboid=" + optionComboId + " and sourceid in ("
+                + TextUtils.getCommaDelimitedString( orgunitIds ) + ") and periodid=" + periodid + "";
+
+            jdbcTemplate.execute( deleteDataValueSql );
+        }
+
+        // insert data elements into database directly
+
+        String sql = parseExpressionToSql( true, expression, operator, dataElementId, "dataelementname", optionComboId,
+            "optionComboname", deSumId, orgunitIds, period );
+
+        jdbcTemplate.execute( sql );
+    }
+
+    @Override
+    public String parseExpressionToSql( boolean isInsert, String caseExpression, String operator,
+        Integer aggregateDeId, String aggregateDeName, Integer optionComboId, String optionComboName, Integer deSumId,
+        Collection<Integer> orgunitIds, Period period )
+    {
+        String sql = "SELECT '" + aggregateDeId + "' as dataelementid, '" + optionComboId
+            + "' as categoryoptioncomboid, ou.organisationunitid as sourceid, '" + period.getId() + "' as periodid,'"
+            + CaseAggregationCondition.AUTO_STORED_BY + "' as comment, ";
+
+        if ( isInsert )
+        {
+            sql = "INSERT INTO datavalue (dataelementid, categoryoptioncomboid, sourceid, periodid, comment, value)"
+                + sql;
+        }
+        else
+        {
+            sql += "'" + period.getIsoDate() + "' as periodIsoDate,'" + aggregateDeName + "' as dataelementname, '"
+                + optionComboName + "' as categoryoptioncomboname, ou.name as organisationunitname, ";
+        }
+
+        if ( operator.equals( CaseAggregationCondition.AGGRERATION_COUNT )
+            || operator.equals( CaseAggregationCondition.AGGRERATION_SUM ) )
+        {
+            if ( hasOrgunitProgramStageCompleted( caseExpression ) )
+            {
+                sql += createSQL( caseExpression, operator, orgunitIds,
+                    DateUtils.getMediumDateString( period.getStartDate() ),
+                    DateUtils.getMediumDateString( period.getEndDate() ) );
+            }
+            else
+            {
+                if ( operator.equals( CaseAggregationCondition.AGGRERATION_COUNT ) )
+                {
+                    sql += " count (distinct(pi.patientid) ) as value ";
+                }
+                else
+                {
+                    sql += " count (psi.programinstanceid ) as value ";
+                }
+
+                sql += "FROM ";
+                boolean hasDataelement = hasDataelementCriteria( caseExpression );
+
+                if ( hasDataelement )
+                {
+                    sql += " programinstance as pi ";
+                    sql += " INNER JOIN patient p on p.patientid=pi.patientid ";
+                    sql += " INNER JOIN programstageinstance psi ON pi.programinstanceid=psi.programinstanceid ";
+                    sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=psi.organisationunitid ";
+                }
+                else
+                {
+                    sql += " programinstance as pi INNER JOIN patient p on p.patientid=pi.patientid ";
+                    sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=p.organisationunitid ";
+                }
+
+                sql += " WHERE "
+                    + createSQL( caseExpression, operator, orgunitIds,
+                        DateUtils.getMediumDateString( period.getStartDate() ),
+                        DateUtils.getMediumDateString( period.getEndDate() ) );
+
+                sql += "GROUP BY ou.organisationunitid, ou.name";
+            }
+        }
+        else
+        {
+            sql += " " + operator + "( cast( pdv.value as DOUBLE PRECISION ) ) ";
+            sql += "FROM patientdatavalue pdv ";
+            sql += "    INNER JOIN programstageinstance psi  ";
+            sql += "            ON psi.programstageinstanceid = pdv.programstageinstanceid ";
+            sql += "    INNER JOIN organisationunit ou ";
+            sql += "            ON ou.organisationunitid=psi.organisationunitid ";
+            sql += "WHERE executiondate >='" + DateUtils.getMediumDateString( period.getStartDate() ) + "'  ";
+            sql += "    AND executiondate <='" + DateUtils.getMediumDateString( period.getEndDate() )
+                + "' AND pdv.dataelementid=" + deSumId;
+
+            if ( caseExpression != null && !caseExpression.isEmpty() )
+            {
+                sql += " AND "
+                    + createSQL( caseExpression, operator, orgunitIds,
+                        DateUtils.getMediumDateString( period.getStartDate() ),
+                        DateUtils.getMediumDateString( period.getEndDate() ) );
+            }
+
+            sql += "GROUP BY ou.organisationunitid, ou.name";
+
+        }
+
+        sql = sql.replaceAll( "COMBINE", "" );
+
+        return sql;
+    }
+
+    @Override
+    public void runAggregate( Collection<Integer> orgunitIds, CaseAggregateSchedule dataSet, Collection<Period> periods )
+    {
+        String sql = "select caseaggregationconditionid, aggregationdataelementid, optioncomboid, "
+            + " cagg.aggregationexpression as caseexpression, cagg.operator as caseoperator, cagg.desum as desumid "
+            + "     from caseaggregationcondition cagg inner join datasetmembers dm "
+            + "             on cagg.aggregationdataelementid=dm.dataelementid inner join dataset ds "
+            + "             on ds.datasetid = dm.datasetid inner join periodtype pt "
+            + "             on pt.periodtypeid=ds.periodtypeid inner join dataelement de "
+            + "             on de.dataelementid=dm.dataelementid where ds.datasetid = " + dataSet.getDataSetId();
+
+        SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
+
+        while ( rs.next() )
+        {
+            for ( Period period : periods )
+            {
+                // -------------------------------------------------------------
+                // Get formula, agg-dataelement and option-combo
+                // -------------------------------------------------------------
+
+                int dataelementId = rs.getInt( "aggregationdataelementid" );
+                int optionComboId = rs.getInt( "optioncomboid" );
+                String caseExpression = rs.getString( "caseexpression" );
+                String caseOperator = rs.getString( "caseoperator" );
+                int deSumId = rs.getInt( "desumid" );
+
+                Collection<Integer> _orgunitIds = getServiceOrgunit(
+                    DateUtils.getMediumDateString( period.getStartDate() ),
+                    DateUtils.getMediumDateString( period.getEndDate() ) );
+
+                if ( orgunitIds == null )
+                {
+                    orgunitIds = new HashSet<Integer>();
+                    orgunitIds.addAll( _orgunitIds );
+                }
+                else
+                {
+                    orgunitIds.retainAll( _orgunitIds );
+                }
+
+                // ---------------------------------------------------------------------
+                // Aggregation
+                // ---------------------------------------------------------------------
+
+                if ( !orgunitIds.isEmpty() )
+                {
+                    insertAggregateValue( caseExpression, caseOperator, dataelementId, optionComboId, deSumId,
+                        orgunitIds, period );
+                }
+            }
+
+        }
+    }
+
+    /**
+     * Return standard SQL from query builder formula
+     * 
+     * @param caseExpression The query builder expression
+     * @param operator There are six operators, includes Number of persons,
+     *        Number of visits, Sum, Average, Minimum and Maximum of data
+     *        element values.
+     * @param deType Aggregate Data element type
+     * @param orgunitIds The ids of organisation units where to aggregate data
+     *        value
+     * @param startDate Start date
+     * @param endDate End date
+     */
+    private String createSQL( String caseExpression, String operator, Collection<Integer> orgunitIds, String startDate,
+        String endDate )
+    {
+        boolean orgunitCompletedProgramStage = false;
+
+        StringBuffer sqlResult = new StringBuffer();
+
+        String sqlOrgunitCompleted = "";
+
+        // Get minus(date dataelement, date dataelement) out from the expression
+        // and run them later
+
+        Map<Integer, String> minus2SQLMap = new HashMap<Integer, String>();
+        int idx2 = 0;
+        Pattern patternMinus2 = Pattern.compile( CaseAggregationCondition.minusDataelementRegExp );
+        Matcher matcherMinus2 = patternMinus2.matcher( caseExpression );
+        while ( matcherMinus2.find() )
+        {
+            String[] ids1 = matcherMinus2.group( 2 ).split( SEPARATOR_ID );
+            String[] ids2 = matcherMinus2.group( 5 ).split( SEPARATOR_ID );
+
+            minus2SQLMap.put(
+                idx2,
+                getConditionForMisus2DataElement( orgunitIds, ids1[1], ids1[2], ids2[1], ids2[2],
+                    matcherMinus2.group( 6 ) + matcherMinus2.group( 7 ), startDate, endDate ) );
+
+            caseExpression = caseExpression.replace( matcherMinus2.group( 0 ),
+                CaseAggregationCondition.MINUS_DATAELEMENT_OPERATOR + "_" + idx2 );
+
+            idx2++;
+        }
+
+        // Get minus(date dataelement, date) out from the expression and run
+        // them later
+
+        Map<Integer, String> minusSQLMap = new HashMap<Integer, String>();
+        int idx = 0;
+        Pattern patternMinus = Pattern.compile( CaseAggregationCondition.dataelementRegExp );
+        Matcher matcherMinus = patternMinus.matcher( caseExpression );
+        while ( matcherMinus.find() )
+        {
+            String[] ids = matcherMinus.group( 2 ).split( SEPARATOR_ID );
+
+            minusSQLMap.put(
+                idx,
+                getConditionForMinusDataElement( orgunitIds, Integer.parseInt( ids[1] ), Integer.parseInt( ids[2] ),
+                    matcherMinus.group( 4 ), startDate, endDate ) );
+
+            caseExpression = caseExpression.replace( matcherMinus.group( 0 ), CaseAggregationCondition.MINUS_OPERATOR
+                + "_" + idx );
+
+            idx++;
+        }
+
+        // Run nornal expression
+        String[] expression = caseExpression.split( "(AND|OR)" );
+        caseExpression = caseExpression.replaceAll( "AND", " ) AND " );
+        caseExpression = caseExpression.replaceAll( "OR", " ) OR " );
+
+        // ---------------------------------------------------------------------
+        // parse expressions
+        // ---------------------------------------------------------------------
+
+        Pattern patternCondition = Pattern.compile( CaseAggregationCondition.regExp );
+
+        Matcher matcherCondition = patternCondition.matcher( caseExpression );
+
+        String condition = "";
+
+        int index = 0;
+        while ( matcherCondition.find() )
+        {
+            String match = matcherCondition.group();
+
+            match = match.replaceAll( "[\\[\\]]", "" );
+
+            String[] info = match.split( SEPARATOR_OBJECT );
+            if ( info[0].equalsIgnoreCase( OBJECT_PATIENT ) )
+            {
+                condition = getConditionForPatient( orgunitIds, operator, startDate, endDate );
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_PROPERTY ) )
+            {
+                String propertyName = info[1];
+                condition = getConditionForPatientProperty( propertyName, operator, startDate, endDate );
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_ATTRIBUTE ) )
+            {
+                int attributeId = Integer.parseInt( info[1] );
+
+                String compareValue = expression[index].replace( "[" + match + "]", "" ).trim();
+
+                boolean isExist = compareValue.equals( IS_NULL ) ? false : true;
+                condition = getConditionForPatientAttribute( attributeId, orgunitIds, isExist );
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE_DATAELEMENT ) )
+            {
+                String[] ids = info[1].split( SEPARATOR_ID );
+
+                int programId = Integer.parseInt( ids[0] );
+                String programStageId = ids[1];
+                int dataElementId = Integer.parseInt( ids[2] );
+
+                String compareValue = expression[index].replace( "[" + match + "]", "" ).trim();
+
+                boolean isExist = compareValue.equals( IS_NULL ) ? false : true;
+                condition = getConditionForDataElement( isExist, programId, programStageId, dataElementId, orgunitIds,
+                    startDate, endDate );
+            }
+
+            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_PROPERTY ) )
+            {
+                condition = getConditionForProgramProperty( operator, startDate, endDate, info[1] );
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM ) )
+            {
+                String[] ids = info[1].split( SEPARATOR_ID );
+                condition = getConditionForProgram( ids[0], operator, orgunitIds, startDate, endDate );
+                if ( ids.length > 1 )
+                {
+                    condition += ids[1];
+                }
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE ) )
+            {
+                String[] ids = info[1].split( SEPARATOR_ID );
+                if ( ids.length == 2 && ids[1].equals( IN_CONDITION_COUNT_X_TIMES ) )
+                {
+                    condition = getConditionForCountProgramStage( ids[0], operator, orgunitIds, startDate, endDate );
+                }
+                else
+                {
+                    condition = getConditionForProgramStage( ids[0], operator, orgunitIds, startDate, endDate );
+                }
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE_PROPERTY ) )
+            {
+                condition = getConditionForProgramStageProperty( info[1], operator, orgunitIds, startDate, endDate );
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY ) )
+            {
+                condition = getConditionForPatientProgramStageProperty( info[1], operator, startDate, endDate );
+            }
+            else if ( info[0].equalsIgnoreCase( OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE ) )
+            {
+                sqlOrgunitCompleted += getConditionForOrgunitProgramStageCompleted( info[1], operator, orgunitIds,
+                    startDate, endDate, orgunitCompletedProgramStage );
+                orgunitCompletedProgramStage = true;
+            }
+
+            matcherCondition.appendReplacement( sqlResult, condition );
+
+            index++;
+        }
+
+        matcherCondition.appendTail( sqlResult );
+
+        if ( !sqlOrgunitCompleted.isEmpty() )
+        {
+            sqlOrgunitCompleted = sqlOrgunitCompleted.substring( 0, sqlOrgunitCompleted.length() - 2 );
+        }
+
+        sqlResult.append( sqlOrgunitCompleted );
+
+        String sql = sqlResult.toString();
+
+        sql = sql.replaceAll( IN_CONDITION_START_SIGN, "(" );
+        sql = sql.replaceAll( IN_CONDITION_END_SIGN, ")" );
+        sql = sql.replaceAll( IS_NULL, " " );
+
+        for ( int key = 0; key < idx; key++ )
+        {
+            sql = sql.replace( CaseAggregationCondition.MINUS_OPERATOR + "_" + key, minusSQLMap.get( key ) );
+        }
+
+        for ( int key = 0; key < idx2; key++ )
+        {
+            sql = sql
+                .replace( CaseAggregationCondition.MINUS_DATAELEMENT_OPERATOR + "_" + key, minus2SQLMap.get( key ) );
+        }
+
+        return sql + " ) ";
+    }
+
+    /**
+     * Return standard SQL of the expression to compare data value as null
+     * 
+     */
+    private String getConditionForDataElement( boolean isExist, int programId, String programStageId,
+        int dataElementId, Collection<Integer> orgunitIds, String startDate, String endDate )
+    {
+        String keyExist = (isExist == true) ? "EXISTS" : "NOT EXISTS";
+
+        String sql = " " + keyExist + " ( SELECT * "
+            + "FROM patientdatavalue _pdv inner join programstageinstance _psi "
+            + "ON _pdv.programstageinstanceid=_psi.programstageinstanceid JOIN programinstance _pi "
+            + "ON _pi.programinstanceid=_psi.programinstanceid "
+            + "WHERE psi.programstageinstanceid=_pdv.programstageinstanceid AND _pdv.dataelementid=" + dataElementId
+            + "  AND _psi.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds ) + ")  "
+            + "  AND _pi.programid = " + programId + " AND _psi.executionDate>='" + startDate
+            + "' AND _psi.executionDate <= '" + endDate + "' ";
+
+        if ( !programStageId.equals( IN_CONDITION_GET_ALL ) )
+        {
+            sql += " AND _psi.programstageid = " + programStageId;
+        }
+
+        if ( isExist )
+        {
+            DataElement dataElement = dataElementService.getDataElement( dataElementId );
+            if ( dataElement.getType().equals( DataElement.VALUE_TYPE_INT ) )
+            {
+                sql += " AND ( cast( _pdv.value as " + statementBuilder.getDoubleColumnType() + " )  ) ";
+            }
+            else
+            {
+                sql += " AND _pdv.value ";
+            }
+        }
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL of a dynamic patient-attribute expression. E.g [CA:1]
+     * 
+     */
+    private String getConditionForPatientAttribute( int attributeId, Collection<Integer> orgunitIds, boolean isExist )
+    {
+        String sql = " EXISTS ( SELECT * FROM patientattributevalue _pav "
+            + " WHERE _pav.patientid=pi.patientid AND _pav.patientattributeid=" + attributeId;
+
+        if ( isExist )
+        {
+            sql += "  AND _pav.value ";
+        }
+        else
+        {
+            sql = " NOT " + sql;
+        }
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL of the expression which is used for calculating total
+     * of person registration
+     * 
+     */
+    private String getConditionForPatient( Collection<Integer> orgunitIds, String operator, String startDate,
+        String endDate )
+    {
+        String sql = " EXISTS ( SELECT * " + "FROM patient _p " + "WHERE _p.patientid = pi.patientid "
+            + "AND _p.registrationdate>='" + startDate + "' AND _p.registrationdate<='" + endDate + "' "
+            + "AND p.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds ) + ") ";
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL of the patient-fixed-attribute expression. E.g
+     * [CP:gender]
+     * 
+     */
+    private String getConditionForPatientProperty( String propertyName, String operator, String startDate,
+        String endDate )
+    {
+        String sql = " EXISTS (SELECT _p.patientid FROM patient _p WHERE _p.patientid = pi.patientid AND ";
+
+        if ( propertyName.equals( PROPERTY_AGE ) )
+        {
+            sql += "DATE(registrationdate) - DATE(birthdate) ";
+        }
+        else
+        {
+            sql += propertyName + " ";
+        }
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL of the program-property expression. E.g
+     * [PC:executionDate]
+     * 
+     */
+    private String getConditionForPatientProgramStageProperty( String propertyName, String operator, String startDate,
+        String endDate )
+    {
+        String sql = " EXISTS ( SELECT _psi.programstageinstanceid from programstageinstance _psi "
+            + "WHERE _psi.programstageinstanceid=psi.programstageinstanceid AND ( _psi.executionDate BETWEEN '"
+            + startDate + "' AND '" + endDate + "') AND " + propertyName;
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL of the program expression. E.g
+     * [PP:DATE@enrollmentdate#-DATE@dateofincident#] for geting the number of
+     * days between date of enrollment and date of incident.
+     * 
+     */
+    private String getConditionForProgramProperty( String operator, String startDate, String endDate, String property )
+    {
+        String sql = " EXISTS ( SELECT _pi.programinstanceid FROM programinstance as _pi WHERE _pi.programinstanceid=pi.programinstanceid AND "
+            + "pi.enrollmentdate >= '"
+            + startDate
+            + "' AND pi.enrollmentdate <= '"
+            + endDate
+            + "' AND "
+            + property
+            + " ";
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL to retrieve the number of persons enrolled into the
+     * program. E.g [PG:1]
+     * 
+     */
+    private String getConditionForProgram( String programId, String operator, Collection<Integer> orgunitIds,
+        String startDate, String endDate )
+    {
+        String sql = " EXISTS ( SELECT * FROM programinstance as _pi inner join patient _p on _p.patientid=_pi.patientid "
+            + "WHERE _pi.patientid=pi.patientid AND _pi.programid="
+            + programId
+            + " AND _p.organisationunitid in ("
+            + TextUtils.getCommaDelimitedString( orgunitIds )
+            + ") AND _pi.enrollmentdate >= '"
+            + startDate
+            + "' AND _pi.enrollmentdate <= '" + endDate + "' ";
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL to retrieve the number of visits a program-stage. E.g
+     * [PS:1]
+     * 
+     */
+    private String getConditionForProgramStage( String programStageId, String operator, Collection<Integer> orgunitIds,
+        String startDate, String endDate )
+    {
+        String sql = " EXISTS ( SELECT _psi.programstageinstanceid FROM programstageinstance _psi "
+            + "WHERE _psi.programstageinstanceid=psi.programstageinstanceid " + "AND _psi.programstageid="
+            + programStageId + "  AND _psi.executiondate >= '" + startDate + "' AND _psi.executiondate <= '" + endDate
+            + "' AND _psi.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds ) + ")  ";
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL to retrieve the x-time of a person visited one
+     * program-stage. E.g a mother came to a hospital 3th time for third
+     * trimester.
+     * 
+     */
+    private String getConditionForCountProgramStage( String programStageId, String operator,
+        Collection<Integer> orgunitIds, String startDate, String endDate )
+    {
+        String sql = " EXISTS ( SELECT _psi.programstageinstanceid FROM programstageinstance as _psi "
+            + "WHERE psi.programstageinstanceid=_psi.programstageinstanceid AND _psi.organisationunitid in ("
+            + TextUtils.getCommaDelimitedString( orgunitIds ) + ") and _psi.programstageid = " + programStageId + " "
+            + "AND _psi.executionDate >= '" + startDate + "' AND _psi.executionDate <= '" + endDate + "' "
+            + "GROUP BY _psi.programinstanceid,_psi.programstageinstanceid "
+            + "HAVING count(_psi.programstageinstanceid) ";
+
+        return sql;
+
+    }
+
+    /**
+     * Return standard SQL to retrieve the number of days between report-date
+     * and due-date. E.g [PSP:DATE@executionDate#-DATE@dueDate#]
+     * 
+     */
+    private String getConditionForProgramStageProperty( String property, String operator,
+        Collection<Integer> orgunitIds, String startDate, String endDate )
+    {
+        String sql = " EXISTS ( SELECT * FROM programstageinstance _psi "
+            + "WHERE psi.programstageinstanceid=_psi.programstageinstanceid AND _psi.executiondate >= '" + startDate
+            + "' AND _psi.executiondate <= '" + endDate + "' AND _psi.organisationunitid in ("
+            + TextUtils.getCommaDelimitedString( orgunitIds ) + ") AND " + property + " ";
+
+        return sql;
+    }
+
+    /**
+     * Return standard SQL to retrieve the number of children orgunits has all
+     * program-stage-instance completed and due-date. E.g [PSIC:1]
+     * 
+     * @flag True if there are many stages in the expression
+     * 
+     */
+    private String getConditionForOrgunitProgramStageCompleted( String programStageId, String operator,
+        Collection<Integer> orgunitIds, String startDate, String endDate, boolean flag )
+    {
+        String sql = "";
+        if ( !flag )
+        {
+            sql = " '1' FROM organisationunit ou WHERE ou.organisationunitid in ("
+                + TextUtils.getCommaDelimitedString( orgunitIds ) + ")  ";
+        }
+
+        sql += " AND EXISTS ( SELECT programstageinstanceid FROM programstageinstance _psi "
+            + " WHERE _psi.organisationunitid=ou.organisationunitid AND _psi.programstageid = " + programStageId
+            + " AND _psi.completed=true AND _psi.executiondate >= '" + startDate + "' AND _psi.executiondate <= '"
+            + endDate + "' ) ";
+
+        return sql;
+    }
+
+    private String getConditionForMinusDataElement( Collection<Integer> orgunitIds, Integer programStageId,
+        Integer dataElementId, String compareSide, String startDate, String endDate )
+    {
+        return " EXISTS ( SELECT _pdv.value FROM patientdatavalue _pdv inner join programstageinstance _psi "
+            + "                         ON _pdv.programstageinstanceid=_psi.programstageinstanceid "
+            + "                 JOIN programinstance _pi ON _pi.programinstanceid=_psi.programinstanceid "
+            + "           WHERE psi.programstageinstanceid=_pdv.programstageinstanceid "
+            + "                  AND _pdv.dataelementid=" + dataElementId
+            + "                 AND _psi.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds )
+            + ") " + "                 AND _psi.programstageid = " + programStageId
+            + " AND ( _psi.executionDate BETWEEN '" + startDate + "' AND '" + endDate + "') "
+            + "                 AND ( DATE(_pdv.value) - DATE(" + compareSide + ") ) ";
+    }
+
+    private String getConditionForMisus2DataElement( Collection<Integer> orgunitIds, String programStageId1,
+        String dataElementId1, String programStageId2, String dataElementId2, String compareSide, String startDate,
+        String endDate )
+    {
+        return " EXISTS ( SELECT * FROM ( SELECT _pdv.value FROM patientdatavalue _pdv "
+            + "                 INNER JOIN programstageinstance _psi ON _pdv.programstageinstanceid=_psi.programstageinstanceid "
+            + "                 JOIN programinstance _pi ON _pi.programinstanceid=_psi.programinstanceid "
+            + "           WHERE psi.programstageinstanceid=_pdv.programstageinstanceid AND _pdv.dataelementid= "
+            + dataElementId1
+            + "                 AND _psi.organisationunitid in ("
+            + TextUtils.getCommaDelimitedString( orgunitIds )
+            + ") "
+            + "                 AND _psi.programstageid = "
+            + programStageId1
+            + "                 AND _psi.executionDate>='"
+            + startDate
+            + "'  "
+            + "                 AND _psi.executionDate <= '"
+            + endDate
+            + "' ) AS d1 cross join "
+            + "         (  SELECT _pdv.value FROM patientdatavalue _pdv INNER JOIN programstageinstance _psi "
+            + "                        ON _pdv.programstageinstanceid=_psi.programstageinstanceid "
+            + "                  JOIN programinstance _pi ON _pi.programinstanceid=_psi.programinstanceid "
+            + "           WHERE psi.programstageinstanceid=_pdv.programstageinstanceid and _pdv.dataelementid= "
+            + dataElementId2
+            + "                 AND _psi.organisationunitid in ("
+            + TextUtils.getCommaDelimitedString( orgunitIds )
+            + ") "
+            + "                 AND _psi.programstageid =  "
+            + programStageId2
+            + "                 AND _psi.executionDate>='"
+            + startDate
+            + "'  "
+            + "                 AND _psi.executionDate <= '"
+            + endDate
+            + "' ) AS d2 WHERE DATE(d1.value ) - DATE(d2.value) " + compareSide;
+    }
+
+    /**
+     * Return the Ids of organisation units which patients registered or events
+     * happened.
+     * 
+     */
+    private Collection<Integer> getServiceOrgunit( String startDate, String endDate )
+    {
+        String sql = "(select organisationunitid from programstageinstance where executiondate>= '" + startDate
+            + "' and executiondate<='" + endDate + "')";
+        sql += " UNION ";
+        sql += "( select distinct organisationunitid from patient where registrationdate BETWEEN '" + startDate
+            + "' AND '" + endDate + "')";
+        sql += " UNION ";
+        sql += "( select distinct organisationunitid from patient p INNER JOIN programinstance pi ON p.patientid=pi.patientid "
+            + "  where pi.enrollmentdate BETWEEN '" + startDate + "' AND '" + endDate + "')";
+        sql += " UNION ";
+        sql += "( select distinct organisationunitid from patient p INNER JOIN programinstance pi ON p.patientid=pi.patientid "
+            + "  where pi.enrollmentdate BETWEEN '" + startDate + "' AND '" + endDate + "')";
+
+        Collection<Integer> orgunitIds = new HashSet<Integer>();
+        orgunitIds = jdbcTemplate.query( sql, new RowMapper<Integer>()
+        {
+            public Integer mapRow( ResultSet rs, int rowNum )
+                throws SQLException
+            {
+                return rs.getInt( 1 );
+            }
+        } );
+
+        return orgunitIds;
+    }
+
+    @Override
+    public String parseExpressionDetailsToSql( String caseExpression, String operator, Integer orgunitId, Period period )
+    {
+        String sql = "SELECT ";
+
+        boolean hasPatients = hasPatientCriteria( caseExpression );
+        boolean hasDataelement = hasDataelementCriteria( caseExpression );
+
+        Collection<Integer> orgunitIds = new HashSet<Integer>();
+        orgunitIds.add( orgunitId );
+
+        if ( hasOrgunitProgramStageCompleted( caseExpression ) )
+        {
+            sql += "ou.name "
+                + createSQL( caseExpression, operator, orgunitIds,
+                    DateUtils.getMediumDateString( period.getStartDate() ),
+                    DateUtils.getMediumDateString( period.getEndDate() ) );
+        }
+        else
+        {
+            if ( hasPatients || operator.equals( CaseAggregationCondition.AGGRERATION_COUNT ) )
+            {
+                sql += "p.name, p.gender, p.birthDate, p.phoneNumber,";
+            }
+
+            if ( hasDataelement )
+            {
+                sql += "pdv.value,pgs.name as program_stage, psi.executiondate as report_date,";
+            }
+        }
+
+        sql = sql.substring( 0, sql.length() - 1 );
+        sql += " FROM ";
+
+        if ( hasDataelement )
+        {
+            sql += " programinstance as pi INNER JOIN patient p on p.patientid=pi.patientid";
+            sql += " INNER JOIN programstageinstance psi ON pi.programinstanceid=psi.programinstanceid ";
+            sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=psi.organisationunitid ";
+            sql += " INNER JOIN patientdatavalue pdv ON pdv.programstageinstanceid=psi.programstageinstanceid ";
+            sql += " INNER JOIN program pg ON pg.programid=pi.programid ";
+            sql += " INNER JOIN programstage pgs ON pgs.programid=pg.programid ";
+        }
+        else
+        {
+            sql += " programinstance as pi INNER JOIN patient p on p.patientid=pi.patientid";
+            sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=p.organisationunitid ";
+        }
+
+        sql += " WHERE "
+            + createSQL( caseExpression, operator, orgunitIds, DateUtils.getMediumDateString( period.getStartDate() ),
+                DateUtils.getMediumDateString( period.getEndDate() ) );
+
+        sql = sql.replaceAll( "COMBINE", "" );
+
+        return sql;
+    }
+
+    @Override
+    public List<Integer> executeSQL( String sql )
+    {
+        try
+        {
+            List<Integer> patientIds = jdbcTemplate.query( sql, new RowMapper<Integer>()
+            {
+                public Integer mapRow( ResultSet rs, int rowNum )
+                    throws SQLException
+                {
+                    return rs.getInt( 1 );
+                }
+            } );
+
+            return patientIds;
+        }
+        catch ( Exception ex )
+        {
+            ex.printStackTrace();
+            return null;
+        }
+    }
+
+    @Override
+    public Collection<Period> getPeriods( String periodTypeName, String taskStrategy )
+    {
+        Calendar calStartDate = Calendar.getInstance();
+
+        if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_MONTH.equals( taskStrategy ) )
+        {
+            calStartDate.add( Calendar.MONTH, -1 );
+        }
+        else if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_3_MONTH.equals( taskStrategy ) )
+        {
+            calStartDate.add( Calendar.MONTH, -3 );
+        }
+        else if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_6_MONTH.equals( taskStrategy ) )
+        {
+            calStartDate.add( Calendar.MONTH, -6 );
+        }
+        else if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_12_MONTH.equals( taskStrategy ) )
+        {
+            calStartDate.add( Calendar.MONTH, -12 );
+        }
+
+        Date startDate = calStartDate.getTime();
+
+        Calendar calEndDate = Calendar.getInstance();
+
+        Date endDate = calEndDate.getTime();
+
+        CalendarPeriodType periodType = (CalendarPeriodType) PeriodType.getPeriodTypeByName( periodTypeName );
+        String sql = "select periodtypeid from periodtype where name='" + periodTypeName + "'";
+        int periodTypeId = jdbcTemplate.queryForObject( sql, Integer.class );
+
+        Collection<Period> periods = periodType.generatePeriods( startDate, endDate );
+
+        for ( Period period : periods )
+        {
+            String start = DateUtils.getMediumDateString( period.getStartDate() );
+            String end = DateUtils.getMediumDateString( period.getEndDate() );
+
+            sql = "select periodid from period where periodtypeid=" + periodTypeId + " and startdate='" + start
+                + "' and enddate='" + end + "'";
+            Integer periodid = null;
+            SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
+            if ( rs.next() )
+            {
+                periodid = rs.getInt( "periodid" );
+            }
+
+            if ( periodid == null )
+            {
+                String insertSql = "insert into period (periodtypeid,startdate,enddate) " + " VALUES " + "("
+                    + periodTypeId + ",'" + start + "','" + end + "' )";
+                jdbcTemplate.execute( insertSql );
+
+                period.setId( jdbcTemplate.queryForObject( sql, Integer.class ) );
+            }
+            else
+            {
+                period.setId( periodid );
+            }
+        }
+
+        return periods;
+    }
+
+    private boolean hasOrgunitProgramStageCompleted( String expresstion )
+    {
+        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
+        Matcher matcher = pattern.matcher( expresstion );
+        while ( matcher.find() )
+        {
+            String match = matcher.group();
+
+            match = match.replaceAll( "[\\[\\]]", "" );
+
+            String[] info = match.split( SEPARATOR_OBJECT );
+
+            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    private boolean hasPatientCriteria( String expresstion )
+    {
+        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
+        Matcher matcher = pattern.matcher( expresstion );
+        while ( matcher.find() )
+        {
+            String match = matcher.group();
+
+            match = match.replaceAll( "[\\[\\]]", "" );
+
+            String[] info = match.split( SEPARATOR_OBJECT );
+
+            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT )
+                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT_PROPERTY )
+                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT_ATTRIBUTE ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    // private boolean hasProgramInstanceCriteria( String expresstion )
+    // {
+    // Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
+    // Matcher matcher = pattern.matcher( expresstion );
+    // while ( matcher.find() )
+    // {
+    // String match = matcher.group();
+    //
+    // match = match.replaceAll( "[\\[\\]]", "" );
+    //
+    // String[] info = match.split( SEPARATOR_OBJECT );
+    //
+    // if ( info[0].equalsIgnoreCase(
+    // CaseAggregationCondition.OBJECT_PROGRAM_PROPERTY )
+    // || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM )
+    // || info[0].equalsIgnoreCase(
+    // CaseAggregationCondition.OBJECT_PROGRAM_STAGE ) )
+    // {
+    // return true;
+    // }
+    // }
+    //
+    // return false;
+    // }
+
+    private boolean hasDataelementCriteria( String expresstion )
+    {
+        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
+        Matcher matcher = pattern.matcher( expresstion );
+        while ( matcher.find() )
+        {
+            String match = matcher.group();
+
+            match = match.replaceAll( "[\\[\\]]", "" );
+            String[] info = match.split( SEPARATOR_OBJECT );
+
+            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE_DATAELEMENT )
+                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE )
+                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE_PROPERTY )
+                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY )
+                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE ) )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
 }

=== removed directory 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/jdbc'
=== removed file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionManager.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionManager.java	2013-10-18 07:38:06 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionManager.java	1970-01-01 00:00:00 +0000
@@ -1,1191 +0,0 @@
-package org.hisp.dhis.caseaggregation.jdbc;
-
-/*
- * Copyright (c) 2004-2013, 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 static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_ATTRIBUTE;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_PROPERTY;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_PROPERTY;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_STAGE;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_STAGE_DATAELEMENT;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PROGRAM_STAGE_PROPERTY;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_ID;
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_OBJECT;
-import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_12_MONTH;
-import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_3_MONTH;
-import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_6_MONTH;
-import static org.hisp.dhis.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_MONTH;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.Future;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.hisp.dhis.caseaggregation.CaseAggregateSchedule;
-import org.hisp.dhis.caseaggregation.CaseAggregationCondition;
-import org.hisp.dhis.caseaggregation.CaseAggregationConditionManager;
-import org.hisp.dhis.common.Grid;
-import org.hisp.dhis.common.GridHeader;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementService;
-import org.hisp.dhis.i18n.I18n;
-import org.hisp.dhis.i18n.I18nFormat;
-import org.hisp.dhis.jdbc.StatementBuilder;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.period.CalendarPeriodType;
-import org.hisp.dhis.period.Period;
-import org.hisp.dhis.period.PeriodType;
-import org.hisp.dhis.system.grid.ListGrid;
-import org.hisp.dhis.system.util.DateUtils;
-import org.hisp.dhis.system.util.TextUtils;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.core.RowMapper;
-import org.springframework.jdbc.support.rowset.SqlRowSet;
-import org.springframework.scheduling.annotation.Async;
-
-/**
- * @author Chau Thu Tran
- */
-public class JdbcCaseAggregationConditionManager
-    implements CaseAggregationConditionManager
-{
-    private final String IS_NULL = "is null";
-
-    private final String PROPERTY_AGE = "age";
-
-    private final String IN_CONDITION_GET_ALL = "*";
-
-    private final String IN_CONDITION_START_SIGN = "@";
-
-    private final String IN_CONDITION_END_SIGN = "#";
-
-    private final String IN_CONDITION_COUNT_X_TIMES = "COUNT";
-
-    public static final String STORED_BY_DHIS_SYSTEM = "DHIS-System";
-
-    // -------------------------------------------------------------------------
-    // Dependency
-    // -------------------------------------------------------------------------
-
-    private JdbcTemplate jdbcTemplate;
-
-    public void setJdbcTemplate( JdbcTemplate jdbcTemplate )
-    {
-        this.jdbcTemplate = jdbcTemplate;
-    }
-
-    private StatementBuilder statementBuilder;
-
-    public void setStatementBuilder( StatementBuilder statementBuilder )
-    {
-        this.statementBuilder = statementBuilder;
-    }
-
-    private DataElementService dataElementService;
-
-    public void setDataElementService( DataElementService dataElementService )
-    {
-        this.dataElementService = dataElementService;
-    }
-
-    // -------------------------------------------------------------------------
-    // Implementation Methods
-    // -------------------------------------------------------------------------
-
-    @Override
-    public List<Integer> executeSQL( String sql )
-    {
-        try
-        {
-            List<Integer> patientIds = jdbcTemplate.query( sql, new RowMapper<Integer>()
-            {
-                public Integer mapRow( ResultSet rs, int rowNum )
-                    throws SQLException
-                {
-                    return rs.getInt( 1 );
-                }
-            } );
-
-            return patientIds;
-        }
-        catch ( Exception ex )
-        {
-            ex.printStackTrace();
-            return null;
-        }
-    }
-
-    @Async
-    public Future<?> aggregate( ConcurrentLinkedQueue<CaseAggregateSchedule> caseAggregateSchedule, String taskStrategy )
-    {
-        taskLoop: while ( true )
-        {
-            CaseAggregateSchedule dataSet = caseAggregateSchedule.poll();
-
-            if ( dataSet == null )
-            {
-                break taskLoop;
-            }
-
-            Collection<Period> periods = getPeriods( dataSet.getPeriodTypeName(), taskStrategy );
-
-            runAggregate( null, dataSet, periods );
-        }
-
-        return null;
-    }
-
-    public Grid getAggregateValue( CaseAggregationCondition caseAggregationCondition, Collection<Integer> orgunitIds,
-        Period period, I18nFormat format, I18n i18n )
-    {
-        Collection<Integer> _orgunitIds = getServiceOrgunit( DateUtils.getMediumDateString( period.getStartDate() ),
-            DateUtils.getMediumDateString( period.getEndDate() ) );
-        _orgunitIds.retainAll( orgunitIds );
-
-        if ( _orgunitIds.size() > 0 )
-        {
-            Grid grid = new ListGrid();
-            grid.setTitle( caseAggregationCondition.getDisplayName() );
-            grid.setSubtitle( format.formatPeriod( period ) );
-
-            grid.addHeader( new GridHeader( i18n.getString( "dataelementid" ), true, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "categoryoptioncomboid" ), true, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "periodid" ), true, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "organisationunitid" ), true, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "comment" ), true, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "dataelementname" ), false, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "categoryoptioncomboname" ), false, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "organisationunitname" ), false, true ) );
-            grid.addHeader( new GridHeader( i18n.getString( "value" ), false, true ) );
-
-            Integer deSumId = (caseAggregationCondition.getDeSum() == null) ? null : caseAggregationCondition
-                .getDeSum().getId();
-            String sql = parseExpressionToSql( false, caseAggregationCondition.getAggregationExpression(),
-                caseAggregationCondition.getOperator(), caseAggregationCondition.getAggregationDataElement().getId(),
-                caseAggregationCondition.getAggregationDataElement().getDisplayName(), caseAggregationCondition
-                    .getOptionCombo().getId(), caseAggregationCondition.getOptionCombo().getDisplayName(), deSumId,
-                _orgunitIds, period );
-
-            SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
-            grid.addRows( rs );
-
-            return grid;
-        }
-
-        return null;
-    }
-
-    @Override
-    public Grid getAggregateValueDetails( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
-        Period period, I18nFormat format, I18n i18n )
-    {
-        Grid grid = new ListGrid();
-        grid.setTitle( orgunit.getName() + " - " + aggregationCondition.getDisplayName() );
-        grid.setSubtitle( format.formatPeriod( period ) );
-
-        String sql = parseExpressionDetailsToSql( aggregationCondition.getAggregationExpression(),
-            aggregationCondition.getOperator(), orgunit.getId(), period );
-
-        SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
-
-        for ( String colName : rs.getMetaData().getColumnNames() )
-        {
-            grid.addHeader( new GridHeader( i18n.getString( colName ), false, true ) );
-        }
-
-        grid.addRows( rs );
-
-        return grid;
-    }
-
-    /**
-     * Insert data elements into database directly
-     * 
-     */
-    public void insertAggregateValue( CaseAggregationCondition caseAggregationCondition,
-        Collection<Integer> orgunitIds, Period period )
-    {
-        Integer deSumId = (caseAggregationCondition.getDeSum() == null) ? null : caseAggregationCondition.getDeSum()
-            .getId();
-
-        insertAggregateValue( caseAggregationCondition.getAggregationExpression(),
-            caseAggregationCondition.getOperator(), caseAggregationCondition.getAggregationDataElement().getId(),
-            caseAggregationCondition.getOptionCombo().getId(), deSumId, orgunitIds, period );
-    }
-
-    private void insertAggregateValue( String expression, String operator, Integer dataElementId,
-        Integer optionComboId, Integer deSumId, Collection<Integer> orgunitIds, Period period )
-    {
-        // Delete all data value from this period which created from DHIS-system
-        // after to run Aggregate Query Builder
-
-        String periodtypeSql = "select periodtypeid from periodtype where name='" + period.getPeriodType().getName()
-            + "'";
-        int periodTypeId = jdbcTemplate.queryForObject( periodtypeSql, Integer.class );
-
-        String periodSql = "select periodid from period where periodtypeid=" + periodTypeId + " and startdate='"
-            + DateUtils.getMediumDateString( period.getStartDate() ) + "' and enddate='"
-            + DateUtils.getMediumDateString( period.getEndDate() ) + "'";
-
-        SqlRowSet rs = jdbcTemplate.queryForRowSet( periodSql );
-
-        int periodid = 0;
-        if ( rs.next() )
-        {
-            periodid = rs.getInt( "periodid" );
-        }
-
-        if ( periodid == 0 )
-        {
-            String insertSql = "insert into period (periodtypeid,startdate,enddate) " + " VALUES " + "("
-                + period.getPeriodType().getId() + ",'" + DateUtils.getMediumDateString( period.getStartDate() )
-                + "','" + DateUtils.getMediumDateString( period.getEndDate() ) + "' )";
-            jdbcTemplate.execute( insertSql );
-
-            period.setId( jdbcTemplate.queryForObject( insertSql, Integer.class ) );
-        }
-        else
-        {
-            period.setId( periodid );
-
-            String deleteDataValueSql = "delete from datavalue where dataelementid=" + dataElementId
-                + " and categoryoptioncomboid=" + optionComboId + " and sourceid in ("
-                + TextUtils.getCommaDelimitedString( orgunitIds ) + ") and periodid=" + periodid + "";
-
-            jdbcTemplate.execute( deleteDataValueSql );
-        }
-
-        // insert data elements into database directly
-
-        String sql = parseExpressionToSql( true, expression, operator, dataElementId, "dataelementname", optionComboId,
-            "optionComboname", deSumId, orgunitIds, period );
-
-        jdbcTemplate.execute( sql );
-    }
-
-    public String parseExpressionToSql( boolean isInsert, String caseExpression, String operator,
-        Integer aggregateDeId, String aggregateDeName, Integer optionComboId, String optionComboName, Integer deSumId,
-        Collection<Integer> orgunitIds, Period period )
-    {
-        String sql = "SELECT '" + aggregateDeId + "' as dataelementid, '" + optionComboId
-            + "' as categoryoptioncomboid, ou.organisationunitid as sourceid, '" + period.getId() + "' as periodid,'"
-            + CaseAggregationCondition.AUTO_STORED_BY + "' as comment, ";
-
-        if ( isInsert )
-        {
-            sql = "INSERT INTO datavalue (dataelementid, categoryoptioncomboid, sourceid, periodid, comment, value)"
-                + sql;
-        }
-        else
-        {
-            sql += "'" + period.getIsoDate() + "' as periodIsoDate,'" + aggregateDeName + "' as dataelementname, '"
-                + optionComboName + "' as categoryoptioncomboname, ou.name as organisationunitname, ";
-        }
-
-        if ( operator.equals( CaseAggregationCondition.AGGRERATION_COUNT )
-            || operator.equals( CaseAggregationCondition.AGGRERATION_SUM ) )
-        {
-            if ( hasOrgunitProgramStageCompleted( caseExpression ) )
-            {
-                sql += createSQL( caseExpression, operator, orgunitIds,
-                    DateUtils.getMediumDateString( period.getStartDate() ),
-                    DateUtils.getMediumDateString( period.getEndDate() ) );
-            }
-            else
-            {
-                if ( operator.equals( CaseAggregationCondition.AGGRERATION_COUNT ) )
-                {
-                    sql += " count (distinct(pi.patientid) ) as value ";
-                }
-                else
-                {
-                    sql += " count (psi.programinstanceid ) as value ";
-                }
-
-                sql += "FROM ";
-                boolean hasDataelement = hasDataelementCriteria( caseExpression );
-
-                if ( hasDataelement )
-                {
-                    sql += " programinstance as pi ";
-                    sql += " INNER JOIN patient p on p.patientid=pi.patientid ";
-                    sql += " INNER JOIN programstageinstance psi ON pi.programinstanceid=psi.programinstanceid ";
-                    sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=psi.organisationunitid ";
-                }
-                else
-                {
-                    sql += " programinstance as pi INNER JOIN patient p on p.patientid=pi.patientid ";
-                    sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=p.organisationunitid ";
-                }
-
-                sql += " WHERE "
-                    + createSQL( caseExpression, operator, orgunitIds,
-                        DateUtils.getMediumDateString( period.getStartDate() ),
-                        DateUtils.getMediumDateString( period.getEndDate() ) );
-
-                sql += "GROUP BY ou.organisationunitid, ou.name";
-            }
-        }
-        else
-        {
-            sql += " " + operator + "( cast( pdv.value as DOUBLE PRECISION ) ) ";
-            sql += "FROM patientdatavalue pdv ";
-            sql += "    INNER JOIN programstageinstance psi  ";
-            sql += "            ON psi.programstageinstanceid = pdv.programstageinstanceid ";
-            sql += "    INNER JOIN organisationunit ou ";
-            sql += "            ON ou.organisationunitid=psi.organisationunitid ";
-            sql += "WHERE executiondate >='" + DateUtils.getMediumDateString( period.getStartDate() ) + "'  ";
-            sql += "    AND executiondate <='" + DateUtils.getMediumDateString( period.getEndDate() )
-                + "' AND pdv.dataelementid=" + deSumId;
-
-            if ( caseExpression != null && !caseExpression.isEmpty() )
-            {
-                sql += " AND "
-                    + createSQL( caseExpression, operator, orgunitIds,
-                        DateUtils.getMediumDateString( period.getStartDate() ),
-                        DateUtils.getMediumDateString( period.getEndDate() ) );
-            }
-
-            sql += "GROUP BY ou.organisationunitid, ou.name";
-
-        }
-
-        sql = sql.replaceAll( "COMBINE", "" );
-        
-        return sql;
-    }
-
-    @Override
-    public String parseExpressionDetailsToSql( String caseExpression, String operator, Integer orgunitId, Period period )
-    {
-        String sql = "SELECT ";
-
-        boolean hasPatients = hasPatientCriteria( caseExpression );
-        boolean hasDataelement = hasDataelementCriteria( caseExpression );
-
-        Collection<Integer> orgunitIds = new HashSet<Integer>();
-        orgunitIds.add( orgunitId );
-
-        if ( hasOrgunitProgramStageCompleted( caseExpression ) )
-        {
-            sql += "ou.name "
-                + createSQL( caseExpression, operator, orgunitIds,
-                    DateUtils.getMediumDateString( period.getStartDate() ),
-                    DateUtils.getMediumDateString( period.getEndDate() ) );
-        }
-        else
-        {
-            if ( hasPatients || operator.equals( CaseAggregationCondition.AGGRERATION_COUNT ) )
-            {
-                sql += "p.name, p.gender, p.birthDate, p.phoneNumber,";
-            }
-
-            if ( hasDataelement )
-            {
-                sql += "pdv.value,pgs.name as program_stage, psi.executiondate as report_date,";
-            }
-        }
-
-        sql = sql.substring( 0, sql.length() - 1 );
-        sql += " FROM ";
-
-        if ( hasDataelement )
-        {
-            sql += " programinstance as pi INNER JOIN patient p on p.patientid=pi.patientid";
-            sql += " INNER JOIN programstageinstance psi ON pi.programinstanceid=psi.programinstanceid ";
-            sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=psi.organisationunitid ";
-            sql += " INNER JOIN patientdatavalue pdv ON pdv.programstageinstanceid=psi.programstageinstanceid ";
-            sql += " INNER JOIN program pg ON pg.programid=pi.programid ";
-            sql += " INNER JOIN programstage pgs ON pgs.programid=pg.programid ";
-        }
-        else
-        {
-            sql += " programinstance as pi INNER JOIN patient p on p.patientid=pi.patientid";
-            sql += " INNER JOIN organisationunit ou ON ou.organisationunitid=p.organisationunitid ";
-        }
-
-        sql += " WHERE "
-            + createSQL( caseExpression, operator, orgunitIds, DateUtils.getMediumDateString( period.getStartDate() ),
-                DateUtils.getMediumDateString( period.getEndDate() ) );
-
-        sql = sql.replaceAll( "COMBINE", "" );
-
-        return sql;
-    }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    /**
-     * Aggregate data values for the dataset by periods with a organisation unit
-     * list
-     * 
-     */
-    private void runAggregate( Collection<Integer> orgunitIds, CaseAggregateSchedule dataSet, Collection<Period> periods )
-    {
-        String sql = "select caseaggregationconditionid, aggregationdataelementid, optioncomboid, "
-            + " cagg.aggregationexpression as caseexpression, cagg.operator as caseoperator, cagg.desum as desumid "
-            + "     from caseaggregationcondition cagg inner join datasetmembers dm "
-            + "             on cagg.aggregationdataelementid=dm.dataelementid inner join dataset ds "
-            + "             on ds.datasetid = dm.datasetid inner join periodtype pt "
-            + "             on pt.periodtypeid=ds.periodtypeid inner join dataelement de "
-            + "             on de.dataelementid=dm.dataelementid where ds.datasetid = " + dataSet.getDataSetId();
-
-        SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
-
-        while ( rs.next() )
-        {
-            for ( Period period : periods )
-            {
-                // -------------------------------------------------------------
-                // Get formula, agg-dataelement and option-combo
-                // -------------------------------------------------------------
-
-                int dataelementId = rs.getInt( "aggregationdataelementid" );
-                int optionComboId = rs.getInt( "optioncomboid" );
-                String caseExpression = rs.getString( "caseexpression" );
-                String caseOperator = rs.getString( "caseoperator" );
-                int deSumId = rs.getInt( "desumid" );
-
-                Collection<Integer> _orgunitIds = getServiceOrgunit(
-                    DateUtils.getMediumDateString( period.getStartDate() ),
-                    DateUtils.getMediumDateString( period.getEndDate() ) );
-
-                if ( orgunitIds == null )
-                {
-                    orgunitIds = new HashSet<Integer>();
-                    orgunitIds.addAll( _orgunitIds );
-                }
-                else
-                {
-                    orgunitIds.retainAll( _orgunitIds );
-                }
-
-                // ---------------------------------------------------------------------
-                // Aggregation
-                // ---------------------------------------------------------------------
-
-                if ( !orgunitIds.isEmpty() )
-                {
-                    insertAggregateValue( caseExpression, caseOperator, dataelementId, optionComboId, deSumId,
-                        orgunitIds, period );
-                }
-            }
-
-        }
-    }
-
-    /**
-     * Generate period list based on period Type and taskStrategy option
-     * 
-     * @param periodTypeName The name of period type
-     * @param taskStrategy Specify how to get period list based on period type
-     *        of each dataset. There are four options, include last month, last
-     *        3 month, last 6 month and last 12 month
-     * 
-     */
-    private Collection<Period> getPeriods( String periodTypeName, String taskStrategy )
-    {
-        Calendar calStartDate = Calendar.getInstance();
-
-        if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_MONTH.equals( taskStrategy ) )
-        {
-            calStartDate.add( Calendar.MONTH, -1 );
-        }
-        else if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_3_MONTH.equals( taskStrategy ) )
-        {
-            calStartDate.add( Calendar.MONTH, -3 );
-        }
-        else if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_6_MONTH.equals( taskStrategy ) )
-        {
-            calStartDate.add( Calendar.MONTH, -6 );
-        }
-        else if ( TASK_AGGREGATE_QUERY_BUILDER_LAST_12_MONTH.equals( taskStrategy ) )
-        {
-            calStartDate.add( Calendar.MONTH, -12 );
-        }
-
-        Date startDate = calStartDate.getTime();
-
-        Calendar calEndDate = Calendar.getInstance();
-
-        Date endDate = calEndDate.getTime();
-
-        CalendarPeriodType periodType = (CalendarPeriodType) PeriodType.getPeriodTypeByName( periodTypeName );
-        String sql = "select periodtypeid from periodtype where name='" + periodTypeName + "'";
-        int periodTypeId = jdbcTemplate.queryForObject( sql, Integer.class );
-
-        Collection<Period> periods = periodType.generatePeriods( startDate, endDate );
-
-        for ( Period period : periods )
-        {
-            String start = DateUtils.getMediumDateString( period.getStartDate() );
-            String end = DateUtils.getMediumDateString( period.getEndDate() );
-
-            sql = "select periodid from period where periodtypeid=" + periodTypeId + " and startdate='" + start
-                + "' and enddate='" + end + "'";
-            Integer periodid = null;
-            SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
-            if ( rs.next() )
-            {
-                periodid = rs.getInt( "periodid" );
-            }
-
-            if ( periodid == null )
-            {
-                String insertSql = "insert into period (periodtypeid,startdate,enddate) " + " VALUES " + "("
-                    + periodTypeId + ",'" + start + "','" + end + "' )";
-                jdbcTemplate.execute( insertSql );
-
-                period.setId( jdbcTemplate.queryForObject( sql, Integer.class ) );
-            }
-            else
-            {
-                period.setId( periodid );
-            }
-        }
-
-        return periods;
-    }
-
-    /**
-     * Return standard SQL from query builder formula
-     * 
-     * @param caseExpression The query builder expression
-     * @param operator There are six operators, includes Number of persons,
-     *        Number of visits, Sum, Average, Minimum and Maximum of data
-     *        element values.
-     * @param deType Aggregate Data element type
-     * @param orgunitIds The ids of organisation units where to aggregate data
-     *        value
-     * @param startDate Start date
-     * @param endDate End date
-     */
-    private String createSQL( String caseExpression, String operator, Collection<Integer> orgunitIds, String startDate,
-        String endDate )
-    {
-        boolean orgunitCompletedProgramStage = false;
-
-        StringBuffer sqlResult = new StringBuffer();
-
-        String sqlOrgunitCompleted = "";
-
-        // Get minus(date dataelement, date dataelement) out from the expression
-        // and run them later
-
-        Map<Integer, String> minus2SQLMap = new HashMap<Integer, String>();
-        int idx2 = 0;
-        Pattern patternMinus2 = Pattern.compile( CaseAggregationCondition.minusDataelementRegExp );
-        Matcher matcherMinus2 = patternMinus2.matcher( caseExpression );
-        while ( matcherMinus2.find() )
-        {
-            String[] ids1 = matcherMinus2.group( 2 ).split( SEPARATOR_ID );
-            String[] ids2 = matcherMinus2.group( 5 ).split( SEPARATOR_ID );
-
-            minus2SQLMap.put(
-                idx2,
-                getConditionForMisus2DataElement( orgunitIds, ids1[1], ids1[2], ids2[1], ids2[2],
-                    matcherMinus2.group( 6 ) + matcherMinus2.group( 7 ), startDate, endDate ) );
-
-            caseExpression = caseExpression.replace( matcherMinus2.group( 0 ),
-                CaseAggregationCondition.MINUS_DATAELEMENT_OPERATOR + "_" + idx2 );
-
-            idx2++;
-        }
-
-        // Get minus(date dataelement, date) out from the expression and run
-        // them later
-
-        Map<Integer, String> minusSQLMap = new HashMap<Integer, String>();
-        int idx = 0;
-        Pattern patternMinus = Pattern.compile( CaseAggregationCondition.dataelementRegExp );
-        Matcher matcherMinus = patternMinus.matcher( caseExpression );
-        while ( matcherMinus.find() )
-        {
-            String[] ids = matcherMinus.group( 2 ).split( SEPARATOR_ID );
-
-            minusSQLMap.put(
-                idx,
-                getConditionForMinusDataElement( orgunitIds, Integer.parseInt( ids[1] ), Integer.parseInt( ids[2] ),
-                    matcherMinus.group( 4 ), startDate, endDate ) );
-
-            caseExpression = caseExpression.replace( matcherMinus.group( 0 ), CaseAggregationCondition.MINUS_OPERATOR
-                + "_" + idx );
-
-            idx++;
-        }
-
-        // Run nornal expression
-        String[] expression = caseExpression.split( "(AND|OR)" );
-        caseExpression = caseExpression.replaceAll( "AND", " ) AND " );
-        caseExpression = caseExpression.replaceAll( "OR", " ) OR " );
-
-        // ---------------------------------------------------------------------
-        // parse expressions
-        // ---------------------------------------------------------------------
-
-        Pattern patternCondition = Pattern.compile( CaseAggregationCondition.regExp );
-
-        Matcher matcherCondition = patternCondition.matcher( caseExpression );
-
-        String condition = "";
-
-        int index = 0;
-        while ( matcherCondition.find() )
-        {
-            String match = matcherCondition.group();
-
-            match = match.replaceAll( "[\\[\\]]", "" );
-
-            String[] info = match.split( SEPARATOR_OBJECT );
-            if ( info[0].equalsIgnoreCase( OBJECT_PATIENT ) )
-            {
-                condition = getConditionForPatient( orgunitIds, operator, startDate, endDate );
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_PROPERTY ) )
-            {
-                String propertyName = info[1];
-                condition = getConditionForPatientProperty( propertyName, operator, startDate, endDate );
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_ATTRIBUTE ) )
-            {
-                int attributeId = Integer.parseInt( info[1] );
-
-                String compareValue = expression[index].replace( "[" + match + "]", "" ).trim();
-
-                boolean isExist = compareValue.equals( IS_NULL ) ? false : true;
-                condition = getConditionForPatientAttribute( attributeId, orgunitIds, isExist );
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE_DATAELEMENT ) )
-            {
-                String[] ids = info[1].split( SEPARATOR_ID );
-
-                int programId = Integer.parseInt( ids[0] );
-                String programStageId = ids[1];
-                int dataElementId = Integer.parseInt( ids[2] );
-
-                String compareValue = expression[index].replace( "[" + match + "]", "" ).trim();
-
-                boolean isExist = compareValue.equals( IS_NULL ) ? false : true;
-                condition = getConditionForDataElement( isExist, programId, programStageId, dataElementId, orgunitIds,
-                    startDate, endDate );
-            }
-
-            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_PROPERTY ) )
-            {
-                condition = getConditionForProgramProperty( operator, startDate, endDate, info[1] );
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM ) )
-            {
-                String[] ids = info[1].split( SEPARATOR_ID );
-                condition = getConditionForProgram( ids[0], operator, orgunitIds, startDate, endDate );
-                if ( ids.length > 1 )
-                {
-                    condition += ids[1];
-                }
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE ) )
-            {
-                String[] ids = info[1].split( SEPARATOR_ID );
-                if ( ids.length == 2 && ids[1].equals( IN_CONDITION_COUNT_X_TIMES ) )
-                {
-                    condition = getConditionForCountProgramStage( ids[0], operator, orgunitIds, startDate, endDate );
-                }
-                else
-                {
-                    condition = getConditionForProgramStage( ids[0], operator, orgunitIds, startDate, endDate );
-                }
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE_PROPERTY ) )
-            {
-                condition = getConditionForProgramStageProperty( info[1], operator, orgunitIds, startDate, endDate );
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY ) )
-            {
-                condition = getConditionForPatientProgramStageProperty( info[1], operator, startDate, endDate );
-            }
-            else if ( info[0].equalsIgnoreCase( OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE ) )
-            {
-                sqlOrgunitCompleted += getConditionForOrgunitProgramStageCompleted( info[1], operator, orgunitIds,
-                    startDate, endDate, orgunitCompletedProgramStage );
-                orgunitCompletedProgramStage = true;
-            }
-
-            matcherCondition.appendReplacement( sqlResult, condition );
-
-            index++;
-        }
-
-        matcherCondition.appendTail( sqlResult );
-
-        if ( !sqlOrgunitCompleted.isEmpty() )
-        {
-            sqlOrgunitCompleted = sqlOrgunitCompleted.substring( 0, sqlOrgunitCompleted.length() - 2 );
-        }
-
-        sqlResult.append( sqlOrgunitCompleted );
-
-        String sql = sqlResult.toString();
-
-        sql = sql.replaceAll( IN_CONDITION_START_SIGN, "(" );
-        sql = sql.replaceAll( IN_CONDITION_END_SIGN, ")" );
-        sql = sql.replaceAll( IS_NULL, " " );
-
-        for ( int key = 0; key < idx; key++ )
-        {
-            sql = sql.replace( CaseAggregationCondition.MINUS_OPERATOR + "_" + key, minusSQLMap.get( key ) );
-        }
-
-        for ( int key = 0; key < idx2; key++ )
-        {
-            sql = sql
-                .replace( CaseAggregationCondition.MINUS_DATAELEMENT_OPERATOR + "_" + key, minus2SQLMap.get( key ) );
-        }
-
-        return sql + " ) ";
-    }
-
-    /**
-     * Return standard SQL of the expression to compare data value as null
-     * 
-     */
-    private String getConditionForDataElement( boolean isExist, int programId, String programStageId,
-        int dataElementId, Collection<Integer> orgunitIds, String startDate, String endDate )
-    {
-        String keyExist = (isExist == true) ? "EXISTS" : "NOT EXISTS";
-
-        String sql = " " + keyExist + " ( SELECT * "
-            + "FROM patientdatavalue _pdv inner join programstageinstance _psi "
-            + "ON _pdv.programstageinstanceid=_psi.programstageinstanceid JOIN programinstance _pi "
-            + "ON _pi.programinstanceid=_psi.programinstanceid "
-            + "WHERE psi.programstageinstanceid=_pdv.programstageinstanceid AND _pdv.dataelementid=" + dataElementId
-            + "  AND _psi.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds ) + ")  "
-            + "  AND _pi.programid = " + programId + " AND _psi.executionDate>='" + startDate
-            + "' AND _psi.executionDate <= '" + endDate + "' ";
-
-        if ( !programStageId.equals( IN_CONDITION_GET_ALL ) )
-        {
-            sql += " AND _psi.programstageid = " + programStageId;
-        }
-
-        if ( isExist )
-        {
-            DataElement dataElement = dataElementService.getDataElement( dataElementId );
-            if ( dataElement.getType().equals( DataElement.VALUE_TYPE_INT ) )
-            {
-                sql += " AND ( cast( _pdv.value as " + statementBuilder.getDoubleColumnType() + " )  ) ";
-            }
-            else
-            {
-                sql += " AND _pdv.value ";
-            }
-        }
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL of a dynamic patient-attribute expression. E.g [CA:1]
-     * 
-     */
-    private String getConditionForPatientAttribute( int attributeId, Collection<Integer> orgunitIds, boolean isExist )
-    {
-        String sql = " EXISTS ( SELECT * FROM patientattributevalue _pav "
-            + " WHERE _pav.patientid=pi.patientid AND _pav.patientattributeid=" + attributeId;
-
-        if ( isExist )
-        {
-            sql += "  AND _pav.value ";
-        }
-        else
-        {
-            sql = " NOT " + sql;
-        }
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL of the expression which is used for calculating total
-     * of person registration
-     * 
-     */
-    private String getConditionForPatient( Collection<Integer> orgunitIds, String operator, String startDate,
-        String endDate )
-    {
-        String sql = " EXISTS ( SELECT * " + "FROM patient _p " + "WHERE _p.patientid = pi.patientid "
-            + "AND _p.registrationdate>='" + startDate + "' AND _p.registrationdate<='" + endDate + "' "
-            + "AND p.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds ) + ") ";
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL of the patient-fixed-attribute expression. E.g
-     * [CP:gender]
-     * 
-     */
-    private String getConditionForPatientProperty( String propertyName, String operator, String startDate,
-        String endDate )
-    {
-        String sql = " EXISTS (SELECT _p.patientid FROM patient _p WHERE _p.patientid = pi.patientid AND ";
-
-        if ( propertyName.equals( PROPERTY_AGE ) )
-        {
-            sql += "DATE(registrationdate) - DATE(birthdate) ";
-        }
-        else
-        {
-            sql += propertyName + " ";
-        }
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL of the program-property expression. E.g
-     * [PC:executionDate]
-     * 
-     */
-    private String getConditionForPatientProgramStageProperty( String propertyName, String operator, String startDate,
-        String endDate )
-    {
-        String sql = " EXISTS ( SELECT _psi.programstageinstanceid from programstageinstance _psi "
-            + "WHERE _psi.programstageinstanceid=psi.programstageinstanceid AND ( _psi.executionDate BETWEEN '"
-            + startDate + "' AND '" + endDate + "') AND " + propertyName;
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL of the program expression. E.g
-     * [PP:DATE@enrollmentdate#-DATE@dateofincident#] for geting the number of
-     * days between date of enrollment and date of incident.
-     * 
-     */
-    private String getConditionForProgramProperty( String operator, String startDate, String endDate, String property )
-    {
-        String sql = " EXISTS ( SELECT _pi.programinstanceid FROM programinstance as _pi WHERE _pi.programinstanceid=pi.programinstanceid AND "
-            + "pi.enrollmentdate >= '"
-            + startDate
-            + "' AND pi.enrollmentdate <= '"
-            + endDate
-            + "' AND "
-            + property
-            + " ";
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL to retrieve the number of persons enrolled into the
-     * program. E.g [PG:1]
-     * 
-     */
-    private String getConditionForProgram( String programId, String operator, Collection<Integer> orgunitIds,
-        String startDate, String endDate )
-    {
-        String sql = " EXISTS ( SELECT * FROM programinstance as _pi inner join patient _p on _p.patientid=_pi.patientid "
-            + "WHERE _pi.patientid=pi.patientid AND _pi.programid="
-            + programId
-            + " AND _p.organisationunitid in ("
-            + TextUtils.getCommaDelimitedString( orgunitIds )
-            + ") AND _pi.enrollmentdate >= '"
-            + startDate
-            + "' AND _pi.enrollmentdate <= '" + endDate + "' ";
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL to retrieve the number of visits a program-stage. E.g
-     * [PS:1]
-     * 
-     */
-    private String getConditionForProgramStage( String programStageId, String operator, Collection<Integer> orgunitIds,
-        String startDate, String endDate )
-    {
-        String sql = " EXISTS ( SELECT _psi.programstageinstanceid FROM programstageinstance _psi "
-            + "WHERE _psi.programstageinstanceid=psi.programstageinstanceid " + "AND _psi.programstageid="
-            + programStageId + "  AND _psi.executiondate >= '" + startDate + "' AND _psi.executiondate <= '" + endDate
-            + "' AND _psi.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds ) + ")  ";
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL to retrieve the x-time of a person visited one
-     * program-stage. E.g a mother came to a hospital 3th time for third
-     * trimester.
-     * 
-     */
-    private String getConditionForCountProgramStage( String programStageId, String operator,
-        Collection<Integer> orgunitIds, String startDate, String endDate )
-    {
-        String sql = " EXISTS ( SELECT _psi.programstageinstanceid FROM programstageinstance as _psi "
-            + "WHERE psi.programstageinstanceid=_psi.programstageinstanceid AND _psi.organisationunitid in ("
-            + TextUtils.getCommaDelimitedString( orgunitIds ) + ") and _psi.programstageid = " + programStageId + " "
-            + "AND _psi.executionDate >= '" + startDate + "' AND _psi.executionDate <= '" + endDate + "' "
-            + "GROUP BY _psi.programinstanceid,_psi.programstageinstanceid "
-            + "HAVING count(_psi.programstageinstanceid) ";
-
-        return sql;
-
-    }
-
-    /**
-     * Return standard SQL to retrieve the number of days between report-date
-     * and due-date. E.g [PSP:DATE@executionDate#-DATE@dueDate#]
-     * 
-     */
-    private String getConditionForProgramStageProperty( String property, String operator,
-        Collection<Integer> orgunitIds, String startDate, String endDate )
-    {
-        String sql = " EXISTS ( SELECT * FROM programstageinstance _psi "
-            + "WHERE psi.programstageinstanceid=_psi.programstageinstanceid AND _psi.executiondate >= '" + startDate
-            + "' AND _psi.executiondate <= '" + endDate + "' AND _psi.organisationunitid in ("
-            + TextUtils.getCommaDelimitedString( orgunitIds ) + ") AND " + property + " ";
-
-        return sql;
-    }
-
-    /**
-     * Return standard SQL to retrieve the number of children orgunits has all
-     * program-stage-instance completed and due-date. E.g [PSIC:1]
-     * 
-     * @flag True if there are many stages in the expression
-     * 
-     */
-    private String getConditionForOrgunitProgramStageCompleted( String programStageId, String operator,
-        Collection<Integer> orgunitIds, String startDate, String endDate, boolean flag )
-    {
-        String sql = "";
-        if ( !flag )
-        {
-            sql = " '1' FROM organisationunit ou WHERE ou.organisationunitid in ("
-                + TextUtils.getCommaDelimitedString( orgunitIds ) + ")  ";
-        }
-
-        sql += " AND EXISTS ( SELECT programstageinstanceid FROM programstageinstance _psi "
-            + " WHERE _psi.organisationunitid=ou.organisationunitid AND _psi.programstageid = " + programStageId
-            + " AND _psi.completed=true AND _psi.executiondate >= '" + startDate + "' AND _psi.executiondate <= '"
-            + endDate + "' ) ";
-
-        return sql;
-    }
-
-    private String getConditionForMinusDataElement( Collection<Integer> orgunitIds, Integer programStageId,
-        Integer dataElementId, String compareSide, String startDate, String endDate )
-    {
-        return " EXISTS ( SELECT _pdv.value FROM patientdatavalue _pdv inner join programstageinstance _psi "
-            + "                         ON _pdv.programstageinstanceid=_psi.programstageinstanceid "
-            + "                 JOIN programinstance _pi ON _pi.programinstanceid=_psi.programinstanceid "
-            + "           WHERE psi.programstageinstanceid=_pdv.programstageinstanceid "
-            + "                  AND _pdv.dataelementid=" + dataElementId
-            + "                 AND _psi.organisationunitid in (" + TextUtils.getCommaDelimitedString( orgunitIds )
-            + ") " + "                 AND _psi.programstageid = " + programStageId
-            + " AND ( _psi.executionDate BETWEEN '" + startDate + "' AND '" + endDate + "') "
-            + "                 AND ( DATE(_pdv.value) - DATE(" + compareSide + ") ) ";
-    }
-
-    private String getConditionForMisus2DataElement( Collection<Integer> orgunitIds, String programStageId1,
-        String dataElementId1, String programStageId2, String dataElementId2, String compareSide, String startDate,
-        String endDate )
-    {
-        return " EXISTS ( SELECT * FROM ( SELECT _pdv.value FROM patientdatavalue _pdv "
-            + "                 INNER JOIN programstageinstance _psi ON _pdv.programstageinstanceid=_psi.programstageinstanceid "
-            + "                 JOIN programinstance _pi ON _pi.programinstanceid=_psi.programinstanceid "
-            + "           WHERE psi.programstageinstanceid=_pdv.programstageinstanceid AND _pdv.dataelementid= "
-            + dataElementId1
-            + "                 AND _psi.organisationunitid in ("
-            + TextUtils.getCommaDelimitedString( orgunitIds )
-            + ") "
-            + "                 AND _psi.programstageid = "
-            + programStageId1
-            + "                 AND _psi.executionDate>='"
-            + startDate
-            + "'  "
-            + "                 AND _psi.executionDate <= '"
-            + endDate
-            + "' ) AS d1 cross join "
-            + "         (  SELECT _pdv.value FROM patientdatavalue _pdv INNER JOIN programstageinstance _psi "
-            + "                        ON _pdv.programstageinstanceid=_psi.programstageinstanceid "
-            + "                  JOIN programinstance _pi ON _pi.programinstanceid=_psi.programinstanceid "
-            + "           WHERE psi.programstageinstanceid=_pdv.programstageinstanceid and _pdv.dataelementid= "
-            + dataElementId2
-            + "                 AND _psi.organisationunitid in ("
-            + TextUtils.getCommaDelimitedString( orgunitIds )
-            + ") "
-            + "                 AND _psi.programstageid =  "
-            + programStageId2
-            + "                 AND _psi.executionDate>='"
-            + startDate
-            + "'  "
-            + "                 AND _psi.executionDate <= '"
-            + endDate
-            + "' ) AS d2 WHERE DATE(d1.value ) - DATE(d2.value) " + compareSide;
-    }
-
-    /**
-     * Return the Ids of organisation units which patients registered or events
-     * happened.
-     * 
-     */
-    private Collection<Integer> getServiceOrgunit( String startDate, String endDate )
-    {
-        String sql = "(select organisationunitid from programstageinstance where executiondate>= '" + startDate
-            + "' and executiondate<='" + endDate + "')";
-        sql += " UNION ";
-        sql += "( select distinct organisationunitid from patient where registrationdate BETWEEN '" + startDate
-            + "' AND '" + endDate + "')";
-        sql += " UNION ";
-        sql += "( select distinct organisationunitid from patient p INNER JOIN programinstance pi ON p.patientid=pi.patientid "
-            + "  where pi.enrollmentdate BETWEEN '" + startDate + "' AND '" + endDate + "')";
-        sql += " UNION ";
-        sql += "( select distinct organisationunitid from patient p INNER JOIN programinstance pi ON p.patientid=pi.patientid "
-            + "  where pi.enrollmentdate BETWEEN '" + startDate + "' AND '" + endDate + "')";
-
-        Collection<Integer> orgunitIds = new HashSet<Integer>();
-        orgunitIds = jdbcTemplate.query( sql, new RowMapper<Integer>()
-        {
-            public Integer mapRow( ResultSet rs, int rowNum )
-                throws SQLException
-            {
-                return rs.getInt( 1 );
-            }
-        } );
-
-        return orgunitIds;
-    }
-
-    public boolean hasOrgunitProgramStageCompleted( String expresstion )
-    {
-        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
-        Matcher matcher = pattern.matcher( expresstion );
-        while ( matcher.find() )
-        {
-            String match = matcher.group();
-
-            match = match.replaceAll( "[\\[\\]]", "" );
-
-            String[] info = match.split( SEPARATOR_OBJECT );
-
-            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE ) )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean hasPatientCriteria( String expresstion )
-    {
-        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
-        Matcher matcher = pattern.matcher( expresstion );
-        while ( matcher.find() )
-        {
-            String match = matcher.group();
-
-            match = match.replaceAll( "[\\[\\]]", "" );
-
-            String[] info = match.split( SEPARATOR_OBJECT );
-
-            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT_PROPERTY )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT_ATTRIBUTE ) )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean hasProgramInstanceCriteria( String expresstion )
-    {
-        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
-        Matcher matcher = pattern.matcher( expresstion );
-        while ( matcher.find() )
-        {
-            String match = matcher.group();
-
-            match = match.replaceAll( "[\\[\\]]", "" );
-
-            String[] info = match.split( SEPARATOR_OBJECT );
-
-            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_PROPERTY )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE ) )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean hasDataelementCriteria( String expresstion )
-    {
-        Pattern pattern = Pattern.compile( CaseAggregationCondition.regExp );
-        Matcher matcher = pattern.matcher( expresstion );
-        while ( matcher.find() )
-        {
-            String match = matcher.group();
-
-            match = match.replaceAll( "[\\[\\]]", "" );
-            String[] info = match.split( SEPARATOR_OBJECT );
-
-            if ( info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE_DATAELEMENT )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PROGRAM_STAGE_PROPERTY )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY )
-                || info[0].equalsIgnoreCase( CaseAggregationCondition.OBJECT_ORGUNIT_COMPLETE_PROGRAM_STAGE ) )
-            {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-}

=== modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/patientreport/hibernate/HibernatePatientAggregateReportStore.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/patientreport/hibernate/HibernatePatientAggregateReportStore.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/java/org/hisp/dhis/patientreport/hibernate/HibernatePatientAggregateReportStore.java	2013-11-28 06:19:32 +0000
@@ -59,24 +59,29 @@
         Collection<PatientAggregateReport> reports = criteria.list();
 
         for ( PatientAggregateReport report : reports )
-        {
+        { 
             if ( SharingUtils.canRead( user, report ) )
             {
-                result.add( report );
-            }
-        }
-
-        if ( min > result.size() )
-        {
-            min = result.size();
-        }
-
-        if ( max > result.size() )
-        {
-            max = result.size();
-        }
-
-        return result.subList( min, max );
+                result.add( report ); 
+            }
+        }
+
+        if ( min != null && max != null )
+        {
+            if ( min > result.size() )
+            {
+                min = result.size();
+            }
+
+            if ( max > result.size() )
+            {
+                max = result.size();
+            }
+
+            return result.subList( min, max );
+        }
+        
+        return result;
     }
 
     @SuppressWarnings( "unchecked" )

=== modified file 'dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml	2013-08-21 12:29:12 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/main/resources/META-INF/dhis/beans.xml	2013-11-28 06:19:32 +0000
@@ -5,14 +5,7 @@
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd";>
 
 	<!-- Store definitions -->
-
-	<bean id="org.hisp.dhis.caseaggregation.CaseAggregationConditionManager"
-		class="org.hisp.dhis.caseaggregation.jdbc.JdbcCaseAggregationConditionManager">
-		<property name="jdbcTemplate" ref="jdbcTemplate" />
-		<property name="statementBuilder" ref="statementBuilder" />
-		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
-	</bean>
-
+	
 	<bean id="org.hisp.dhis.caseaggregation.CaseAggregationConditionStore"
 		class="org.hisp.dhis.caseaggregation.hibernate.HibernateCaseAggregationConditionStore">
 		<property name="clazz"
@@ -40,8 +33,6 @@
 		class="org.hisp.dhis.caseaggregation.DefaultCaseAggregationConditionService">
 		<property name="aggregationConditionStore"
 			ref="org.hisp.dhis.caseaggregation.CaseAggregationConditionStore" />
-		<property name="aggregationConditionManager"
-			ref="org.hisp.dhis.caseaggregation.CaseAggregationConditionManager" />
 		<property name="dataElementService" ref="org.hisp.dhis.dataelement.DataElementService" />
 		<property name="programStageService" ref="org.hisp.dhis.program.ProgramStageService" />
 		<property name="programService" ref="org.hisp.dhis.program.ProgramService" />

=== added directory 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org'
=== added directory 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp'
=== added directory 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis'
=== added directory 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport'
=== added file 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportServiceTest.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportServiceTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportServiceTest.java	2013-11-28 06:19:32 +0000
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+package org.hisp.dhis.patientreport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.user.User;
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserCredentials;
+import org.hisp.dhis.user.UserService;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ PatientAggregateReportServiceTest.java Nov 28, 2013 11:21:05 AM $
+ */
+public class PatientAggregateReportServiceTest
+    extends DhisSpringTest
+{
+    @Autowired
+    private PatientAggregateReportService patientAggregateReportService;
+
+    @Autowired
+    private OrganisationUnitService organisationUnitService;
+
+    @Autowired
+    private UserService userService;
+
+    private User user;
+
+    private PatientAggregateReport aggregateReportA;
+
+    private PatientAggregateReport aggregateReportB;
+
+    @Override
+    public void setUpTest()
+    {
+        OrganisationUnit organisationUnit = createOrganisationUnit( 'A' );
+        organisationUnitService.addOrganisationUnit( organisationUnit );
+
+        Set<OrganisationUnit> orgUnits = new HashSet<OrganisationUnit>();
+        orgUnits.add( organisationUnit );
+
+        user = new User();
+        user.setSurname( "A" );
+        user.setFirstName( "B" );
+        user.setPhoneNumber( "111-222-333" );
+        user.updateOrganisationUnits( orgUnits );
+
+        UserCredentials userCredentials = new UserCredentials();
+        userCredentials.setUser( user );
+        userCredentials.setUsername( "A" );
+        userCredentials.setPassword( "A" );
+        userCredentials.setUser( user );
+        user.setUserCredentials( userCredentials );
+
+        UserAuthorityGroup group = new UserAuthorityGroup();
+        group.setName( "A" );
+        group.setDescription( "A" );
+
+        Collection<String> authorityMember = new ArrayList<String>();
+        authorityMember.add( "ALL" );
+        group.getAuthorities().addAll( authorityMember );
+        userService.addUserAuthorityGroup( group );
+
+        userCredentials.getUserAuthorityGroups().add( group );
+        userService.addUser( user );
+        userService.addUserCredentials( userCredentials );
+
+        aggregateReportA = new PatientAggregateReport( "A" );
+        aggregateReportA.setUid( "UID-A" );
+        aggregateReportA.setUser( user );
+        aggregateReportB = new PatientAggregateReport( "B" );
+        aggregateReportB.setUid( "UID-B" );
+        aggregateReportB.setUser( user );
+    }
+
+    @Test
+    public void testAddPatientAggregateReport()
+    {
+        int idA = patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        int idB = patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idA ) );
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idB ) );
+    }
+
+    @Test
+    public void testDeletePatientAggregateReport()
+    {
+        int idA = patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        int idB = patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idA ) );
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idB ) );
+
+        patientAggregateReportService.deletePatientAggregateReport( aggregateReportA );
+
+        assertNull( patientAggregateReportService.getPatientAggregateReport( idA ) );
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idB ) );
+
+        patientAggregateReportService.deletePatientAggregateReport( aggregateReportB );
+
+        assertNull( patientAggregateReportService.getPatientAggregateReport( idA ) );
+        assertNull( patientAggregateReportService.getPatientAggregateReport( idB ) );
+    }
+
+    @Test
+    public void testUpdatePatientAggregateReport()
+    {
+        int idA = patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idA ) );
+
+        aggregateReportA.setName( "B" );
+        patientAggregateReportService.updatePatientAggregateReport( aggregateReportA );
+
+        assertEquals( "B", patientAggregateReportService.getPatientAggregateReport( idA ).getName() );
+    }
+
+    @Test
+    public void testGetPatientAggregateReportById()
+    {
+        int idA = patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        int idB = patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+
+        assertEquals( aggregateReportA, patientAggregateReportService.getPatientAggregateReport( idA ) );
+        assertEquals( aggregateReportB, patientAggregateReportService.getPatientAggregateReport( idB ) );
+    }
+
+    @Test
+    public void testGetPatientAggregateReportByUid()
+    {
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+
+        assertEquals( aggregateReportA, patientAggregateReportService.getPatientAggregateReportByUid( "UID-A" ) );
+        assertEquals( aggregateReportB, patientAggregateReportService.getPatientAggregateReportByUid( "UID-B" ) );
+    }
+
+    @Test
+    public void testGetPatientAggregateReportByName()
+    {
+        int idA = patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+
+        assertNotNull( patientAggregateReportService.getPatientAggregateReport( idA ) );
+        assertEquals( aggregateReportA.getName(), patientAggregateReportService.getPatientAggregateReport( "A" )
+            .getName() );
+    }
+
+    @Test
+    public void testGetAllPatientAggregateReports()
+    {
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+
+        assertTrue( equals( patientAggregateReportService.getAllPatientAggregateReports(), aggregateReportA,
+            aggregateReportB ) );
+    }
+
+    @Test
+    public void testGetPatientAggregateReports()
+    {
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+        
+        assertTrue( equals( patientAggregateReportService.getPatientAggregateReports( user, "a", null, null ),
+            aggregateReportA ) );
+    }
+
+    @Test
+    public void testCountPatientAggregateReportList()
+    {
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportA );
+        patientAggregateReportService.addPatientAggregateReport( aggregateReportB );
+
+        assertEquals( 1, patientAggregateReportService.countPatientAggregateReportList( user, "a" ) );
+    }
+}
\ No newline at end of file

=== added file 'dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportStoreTest.java'
--- dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportStoreTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-eventreporting/src/test/java/org/hisp/dhis/patientreport/PatientAggregateReportStoreTest.java	2013-11-28 06:19:32 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2004-2013, 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.
+ */
+
+package org.hisp.dhis.patientreport;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.user.User;
+import org.hisp.dhis.user.UserAuthorityGroup;
+import org.hisp.dhis.user.UserCredentials;
+import org.hisp.dhis.user.UserService;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author Chau Thu Tran
+ * 
+ * @version $ patientAggregateReportStoreTest.java Nov 28, 2013 11:21:05 AM $
+ */
+public class PatientAggregateReportStoreTest
+    extends DhisSpringTest
+{
+    @Autowired
+    private PatientAggregateReportStore patientAggregateReportStore;
+
+    @Autowired
+    private OrganisationUnitService organisationUnitService;
+
+    @Autowired
+    private UserService userService;
+
+    private User user;
+
+    private PatientAggregateReport aggregateReportA;
+
+    private PatientAggregateReport aggregateReportB;
+
+    @Override
+    public void setUpTest()
+    {
+        OrganisationUnit organisationUnit = createOrganisationUnit( 'A' );
+        organisationUnitService.addOrganisationUnit( organisationUnit );
+
+        Set<OrganisationUnit> orgUnits = new HashSet<OrganisationUnit>();
+        orgUnits.add( organisationUnit );
+
+        user = new User();
+        user.setSurname( "A" );
+        user.setFirstName( "B" );
+        user.setPhoneNumber( "111-222-333" );
+        user.updateOrganisationUnits( orgUnits );
+
+        UserCredentials userCredentials = new UserCredentials();
+        userCredentials.setUser( user );
+        userCredentials.setUsername( "A" );
+        userCredentials.setPassword( "A" );
+        userCredentials.setUser( user );
+        user.setUserCredentials( userCredentials );
+
+        UserAuthorityGroup group = new UserAuthorityGroup();
+        group.setName( "A" );
+        group.setDescription( "A" );
+
+        Collection<String> authorityMember = new ArrayList<String>();
+        authorityMember.add( "ALL" );
+        group.getAuthorities().addAll( authorityMember );
+        userService.addUserAuthorityGroup( group );
+
+        userCredentials.getUserAuthorityGroups().add( group );
+        userService.addUser( user );
+        userService.addUserCredentials( userCredentials );
+
+        aggregateReportA = new PatientAggregateReport( "A" );
+        aggregateReportA.setUid( "UID-A" );
+        aggregateReportA.setUser( user );
+        aggregateReportB = new PatientAggregateReport( "B" );
+        aggregateReportB.setUid( "UID-B" );
+        aggregateReportB.setUser( user );
+    }
+
+    @Test
+    public void testGetPatientAggregateReports()
+    {
+        patientAggregateReportStore.save( aggregateReportA );
+        patientAggregateReportStore.save( aggregateReportB );
+
+        assertTrue( equals( patientAggregateReportStore.get( user, "a", null, null ),
+            aggregateReportA ) );
+    }
+
+    @Test
+    public void testCountPatientAggregateReportList()
+    {
+        patientAggregateReportStore.save( aggregateReportA );
+        patientAggregateReportStore.save( aggregateReportB );
+
+        assertEquals( 1, patientAggregateReportStore.countList( user, "a" ) );
+    }
+}
\ No newline at end of file

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/test/java/org/hisp/dhis/patient/PatientStoreTest.java'
--- dhis-2/dhis-services/dhis-service-patient/src/test/java/org/hisp/dhis/patient/PatientStoreTest.java	2013-11-26 08:29:22 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/test/java/org/hisp/dhis/patient/PatientStoreTest.java	2013-11-28 06:19:32 +0000
@@ -114,7 +114,7 @@
 
         OrganisationUnit organisationUnitB = createOrganisationUnit( 'B' );
         organisationUnitService.addOrganisationUnit( organisationUnitB );
-        
+
         PatientIdentifierType patientIdentifierType = createPatientIdentifierType( 'A' );
         identifierTypeService.savePatientIdentifierType( patientIdentifierType );
 
@@ -340,7 +340,7 @@
         searchKeys.add( Patient.PREFIX_IDENTIFIER_TYPE + Patient.SEARCH_SAPERATE + "a" + Patient.SEARCH_SAPERATE
             + organisationUnit.getId() );
         searchKeys.add( Patient.PREFIX_PATIENT_ATTRIBUTE + Patient.SEARCH_SAPERATE + attributeId
-            + Patient.SEARCH_SAPERATE + "a" );
+            + Patient.SEARCH_SAPERATE + "a" + Patient.SEARCH_SAPERATE + organisationUnit.getId() );
         searchKeys.add( Patient.PREFIX_PROGRAM + Patient.SEARCH_SAPERATE + idA );
 
         Collection<OrganisationUnit> orgunits = new HashSet<OrganisationUnit>();

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/TestCaseAggregationConditionAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/TestCaseAggregationConditionAction.java	2013-08-23 16:05:01 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/java/org/hisp/dhis/patient/action/caseaggregation/TestCaseAggregationConditionAction.java	2013-11-28 06:19:32 +0000
@@ -33,7 +33,7 @@
 import java.util.HashSet;
 import java.util.List;
 
-import org.hisp.dhis.caseaggregation.CaseAggregationConditionManager;
+import org.hisp.dhis.caseaggregation.CaseAggregationConditionService;
 import org.hisp.dhis.period.MonthlyPeriodType;
 import org.hisp.dhis.period.Period;
 
@@ -49,11 +49,11 @@
     // Dependency
     // -------------------------------------------------------------------------
 
-    private CaseAggregationConditionManager caseAggregationConditionManager;
+    private CaseAggregationConditionService caseAggregationConditionService;
 
-    public void setCaseAggregationConditionManager( CaseAggregationConditionManager caseAggregationConditionManager )
+    public void setCaseAggregationConditionService( CaseAggregationConditionService caseAggregationConditionService )
     {
-        this.caseAggregationConditionManager = caseAggregationConditionManager;
+        this.caseAggregationConditionService = caseAggregationConditionService;
     }
 
     // -------------------------------------------------------------------------
@@ -105,11 +105,11 @@
         period.setEndDate( new Date() );
         period.setPeriodType( periodType );
 
-        String sql = caseAggregationConditionManager.parseExpressionToSql( false, condition, operator, 0,
+        String sql = caseAggregationConditionService.parseExpressionToSql( false, condition, operator, 0,
             "dataelementname", 0, "optioncomboid", deSumId, orgunitIds, period );
 
-        List<Integer> ids = caseAggregationConditionManager.executeSQL( sql );
-        
+        List<Integer> ids = caseAggregationConditionService.executeSQL( sql );
+
         return (ids == null) ? INPUT : SUCCESS;
     }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2013-10-16 09:32:44 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-patient/src/main/resources/META-INF/dhis/beans.xml	2013-11-28 06:19:32 +0000
@@ -898,8 +898,8 @@
     id="org.hisp.dhis.patient.action.caseaggregation.TestCaseAggregationConditionAction"
     class="org.hisp.dhis.patient.action.caseaggregation.TestCaseAggregationConditionAction"
     scope="prototype">
-    <property name="caseAggregationConditionManager">
-      <ref bean="org.hisp.dhis.caseaggregation.CaseAggregationConditionManager" />
+    <property name="caseAggregationConditionService">
+      <ref bean="org.hisp.dhis.caseaggregation.CaseAggregationConditionService" />
     </property>
   </bean>