← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 10442: Use of multiple CPUs for runing aggregate query builder formulas

 

------------------------------------------------------------
revno: 10442
committer: Tran Chau <tran.hispvietnam@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2013-04-01 12:56:41 +0700
message:
  Use of multiple CPUs for runing aggregate query builder formulas
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-patient/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionStore.java
  dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/scheduling/CaseAggregateConditionTask.java
  dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseaggregation/CaseAggregationResultAction.java


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java	2013-01-24 06:30:16 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionService.java	2013-04-01 05:56:41 +0000
@@ -28,6 +28,7 @@
 package org.hisp.dhis.caseaggregation;
 
 import java.util.Collection;
+import java.util.List;
 
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
@@ -62,7 +63,7 @@
     
     Collection<CaseAggregationCondition> getCaseAggregationCondition( Collection<DataElement> dataElements );
     
-    Integer parseConditition( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit, Period period );
+    Double getAggregateValue( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit, Period period );
         
     Collection<PatientDataValue> getPatientDataValues( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit, Period period );
     
@@ -77,4 +78,7 @@
     Collection<PatientAttribute> getPatientAttributesInCondition( String aggregationExpression );
     
     String getConditionDescription( String condition );
+    
+    void aggregate( List<CaseAggregateSchedule> caseAggregateSchedules, String taskStrategy );
+    
 }

=== 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-01-07 05:07:05 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/caseaggregation/CaseAggregationConditionStore.java	2013-04-01 05:56:41 +0000
@@ -29,10 +29,13 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Future;
 
 import org.hisp.dhis.common.GenericNameableObjectStore;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.period.Period;
 
 /**
  * @author Chau Thu Tran
@@ -43,12 +46,20 @@
     extends GenericNameableObjectStore<CaseAggregationCondition>
 {
     String ID = CaseAggregationConditionStore.class.getName();
-   
+
     Collection<CaseAggregationCondition> get( DataElement dataElement );
 
     CaseAggregationCondition get( DataElement dataElement, DataElementCategoryOptionCombo optionCombo );
-    
+
     Collection<CaseAggregationCondition> get( Collection<DataElement> dataElements );
-    
+
     List<Integer> executeSQL( String sql );
+    
+    String parseExpressionToSql( String aggregationExpression, String operator, String deType, Integer deSumId,
+        Integer orgunitId, String startDate, String endDate );
+    
+    Double getAggregateValue( String caseExpression, String operator, String deType, Integer deSumId,
+        Integer orgunitId, Period period );
+    
+    Future<?> aggregate( ConcurrentLinkedQueue<CaseAggregateSchedule> dataSetIds, String taskStrategy );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java	2013-02-20 13:46:42 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/DefaultCaseAggregationConditionService.java	2013-04-01 05:56:41 +0000
@@ -27,7 +27,6 @@
 
 package org.hisp.dhis.caseaggregation;
 
-import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.AGGRERATION_COUNT;
 import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.AGGRERATION_SUM;
 import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT;
 import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.OBJECT_PATIENT_ATTRIBUTE;
@@ -38,7 +37,6 @@
 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.OPERATOR_AND;
 import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_ID;
 import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_OBJECT;
 import static org.hisp.dhis.i18n.I18nUtils.i18n;
@@ -47,6 +45,8 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Future;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -54,7 +54,6 @@
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.i18n.I18nService;
-import org.hisp.dhis.jdbc.StatementBuilder;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.patient.Patient;
 import org.hisp.dhis.patient.PatientAttribute;
@@ -69,8 +68,9 @@
 import org.hisp.dhis.program.ProgramStageInstance;
 import org.hisp.dhis.program.ProgramStageInstanceService;
 import org.hisp.dhis.program.ProgramStageService;
+import org.hisp.dhis.system.util.ConcurrentUtils;
 import org.hisp.dhis.system.util.DateUtils;
-import org.nfunk.jep.JEP;
+import org.hisp.dhis.system.util.SystemUtils;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -89,22 +89,12 @@
         + OBJECT_PROGRAM_PROPERTY + ")" + SEPARATOR_OBJECT + "([a-zA-Z0-9@#\\- ]+[" + SEPARATOR_ID + "[a-zA-Z0-9]*]*)"
         + "\\]";
 
-    private final String IS_NULL = "is null";
-
-    private final String PROPERTY_AGE = "age";
-
     private final String INVALID_CONDITION = "Invalid condition";
 
     private final String TOTAL_OF_PATIENTS_REGISTERED = "Total of patient registration";
 
     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";
-
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
@@ -125,19 +115,12 @@
 
     private ProgramStageInstanceService programStageInstanceService;
 
-    private StatementBuilder statementBuilder;
-
     private I18nService i18nService;
 
     // -------------------------------------------------------------------------
     // Getters && Setters
     // -------------------------------------------------------------------------
 
-    public void setStatementBuilder( StatementBuilder statementBuilder )
-    {
-        this.statementBuilder = statementBuilder;
-    }
-
     public void setAggregationConditionStore( CaseAggregationConditionStore aggregationConditionStore )
     {
         this.aggregationConditionStore = aggregationConditionStore;
@@ -232,36 +215,15 @@
     }
 
     @Override
-    public Integer parseConditition( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
+    public Double getAggregateValue( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
         Period period )
     {
-        String operator = aggregationCondition.getOperator();
-
-        if ( operator.equals( CaseAggregationCondition.AGGRERATION_COUNT )
-            || operator.equals( CaseAggregationCondition.AGGRERATION_SUM ) )
-        {
-            String sql = convertCondition( aggregationCondition, orgunit, period );
-            Collection<Integer> ids = aggregationConditionStore.executeSQL( sql );
-            return (ids == null) ? null : ids.size();
-        }
-
-        String sql = "SELECT " + operator + "( cast( pdv.value as DOUBLE PRECISION ) ) ";
-        sql += "FROM patientdatavalue pdv ";
-        sql += "    INNER JOIN programstageinstance psi  ";
-        sql += "    ON psi.programstageinstanceid = pdv.programstageinstanceid ";
-        sql += "WHERE executiondate >='" + DateUtils.getMediumDateString( period.getStartDate() ) + "'  ";
-        sql += "    AND executiondate <='" + DateUtils.getMediumDateString( period.getEndDate() )
-            + "' AND pdv.dataelementid=" + aggregationCondition.getDeSum().getId();
-
-        if ( aggregationCondition.getAggregationExpression() != null
-            && !aggregationCondition.getAggregationExpression().isEmpty() )
-        {
-            sql = sql + " AND pdv.programstageinstanceid in ( "
-                + convertCondition( aggregationCondition, orgunit, period ) + " ) ";
-        }
-
-        Collection<Integer> ids = aggregationConditionStore.executeSQL( sql );
-        return (ids == null) ? null : ids.iterator().next();
+        DataElement aggDataElement = aggregationCondition.getAggregationDataElement();
+        DataElement deSum = aggregationCondition.getDeSum();
+        Integer deSumId = (deSum == null) ? null : deSum.getId();
+
+        return aggregationConditionStore.getAggregateValue( aggregationCondition.getAggregationExpression(),
+            aggregationCondition.getOperator(), aggDataElement.getType(), deSumId, orgunit.getId(), period );
     }
 
     @Override
@@ -269,14 +231,18 @@
         OrganisationUnit orgunit, Period period )
     {
         // get params
+
         int orgunitId = orgunit.getId();
         String startDate = DateUtils.getMediumDateString( period.getStartDate() );
         String endDate = DateUtils.getMediumDateString( period.getEndDate() );
+        DataElement aggDataElement = aggregationCondition.getAggregationDataElement();
+        DataElement deSum = aggregationCondition.getDeSum();
+        Integer deSumId = (deSum == null) ? null : deSum.getId();
 
         Collection<PatientDataValue> result = new HashSet<PatientDataValue>();
 
-        String sql = createSQL( aggregationCondition.getAggregationExpression(), aggregationCondition.getOperator(),
-            orgunitId, startDate, endDate );
+        String sql = aggregationConditionStore.parseExpressionToSql( aggregationCondition.getAggregationExpression(),
+            aggregationCondition.getOperator(), aggDataElement.getType(), deSumId, orgunitId, startDate, endDate );
 
         Collection<DataElement> dataElements = getDataElementsInCondition( aggregationCondition
             .getAggregationExpression() );
@@ -302,10 +268,18 @@
     public Collection<Patient> getPatients( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
         Period period )
     {
+        DataElement aggDataElement = aggregationCondition.getAggregationDataElement();
+        DataElement deSum = aggregationCondition.getDeSum();
+        Integer deSumId = (deSum == null) ? null : deSum.getId();
+
+        String sql = aggregationConditionStore
+            .parseExpressionToSql( aggregationCondition.getAggregationExpression(), aggregationCondition.getOperator(),
+                aggDataElement.getType(), deSumId, orgunit.getId(),
+                DateUtils.getMediumDateString( period.getStartDate() ),
+                DateUtils.getMediumDateString( period.getEndDate() ) );
+
         Collection<Patient> result = new HashSet<Patient>();
 
-        String sql = convertCondition( aggregationCondition, orgunit, period );
-
         Collection<Integer> patientIds = aggregationConditionStore.executeSQL( sql );
 
         if ( patientIds != null )
@@ -335,8 +309,15 @@
             || operator.equals( CaseAggregationCondition.AGGRERATION_SUM ) )
         {
             aggregationCondition.setOperator( AGGRERATION_SUM );
-            sql = createSQL( aggregationCondition.getAggregationExpression(), aggregationCondition.getOperator(),
-                orgunitId, startDate, endDate );
+            
+            // get params
+            
+            DataElement aggDataElement = aggregationCondition.getAggregationDataElement();
+            DataElement deSum = aggregationCondition.getDeSum();
+            Integer deSumId = (deSum == null) ? null : deSum.getId();
+
+            sql = aggregationConditionStore.parseExpressionToSql( aggregationCondition.getAggregationExpression(),
+                aggregationCondition.getOperator(), aggDataElement.getType(), deSumId, orgunitId, startDate, endDate );
         }
         else
         {
@@ -351,8 +332,21 @@
             if ( aggregationCondition.getAggregationExpression() != null
                 && !aggregationCondition.getAggregationExpression().isEmpty() )
             {
-                sql = sql + " AND pdv.programstageinstanceid in ( "
-                    + convertCondition( aggregationCondition, orgunit, period ) + " ) ";
+                sql = sql + " AND pdv.programstageinstanceid in ( ";
+
+                // Get params
+                
+                DataElement aggDataElement = aggregationCondition.getAggregationDataElement();
+                DataElement deSum = aggregationCondition.getDeSum();
+                Integer deSumId = (deSum == null) ? null : deSum.getId();
+
+                String conditionSql = aggregationConditionStore.parseExpressionToSql(
+                    aggregationCondition.getAggregationExpression(), aggregationCondition.getOperator(),
+                    aggDataElement.getType(), deSumId, orgunit.getId(),
+                    DateUtils.getMediumDateString( period.getStartDate() ),
+                    DateUtils.getMediumDateString( period.getEndDate() ) );
+
+                sql += conditionSql + " ) ";
             }
         }
 
@@ -567,491 +561,28 @@
         return i18n( i18nService, aggregationConditionStore.get( dataElements ) );
     }
 
+    public void aggregate( List<CaseAggregateSchedule> caseAggregateSchedules, String taskStrategy )
+    {
+        ConcurrentLinkedQueue<CaseAggregateSchedule> datasetQ = new ConcurrentLinkedQueue<CaseAggregateSchedule>(
+            caseAggregateSchedules );
+
+        List<Future<?>> futures = new ArrayList<Future<?>>();
+
+        for ( int i = 0; i < getProcessNo(); i++ )
+        {
+            futures.add( aggregationConditionStore.aggregate( datasetQ, taskStrategy ) );
+        }
+
+        ConcurrentUtils.waitForCompletion( futures );
+    }
+
     // -------------------------------------------------------------------------
     // Support Methods
     // -------------------------------------------------------------------------
 
-    private String convertCondition( CaseAggregationCondition aggregationCondition, OrganisationUnit orgunit,
-        Period period )
-    {
-        // get params
-        int orgunitId = orgunit.getId();
-        String startDate = DateUtils.getMediumDateString( period.getStartDate() );
-        String endDate = DateUtils.getMediumDateString( period.getEndDate() );
-
-        // Get operators between ( )
-        Pattern patternOperator = Pattern.compile( "(\\)\\s*(OR|AND)\\s*\\( )" );
-
-        Matcher matcherOperator = patternOperator.matcher( aggregationCondition.getAggregationExpression() );
-
-        List<String> operators = new ArrayList<String>();
-
-        while ( matcherOperator.find() )
-        {
-            operators.add( matcherOperator.group( 2 ) );
-        }
-
-        List<String> subSQL = new ArrayList<String>();
-
-        String[] conditions = aggregationCondition.getAggregationExpression().split( "(\\)\\s*(OR|AND)\\s*\\()" );
-
-        // Create SQL statement for the first condition
-        String condition = conditions[0].replace( "(", "" ).replace( ")", "" );
-
-        String sql = createSQL( condition, aggregationCondition.getOperator(), orgunitId, startDate, endDate );
-
-        subSQL.add( sql );
-
-        // Create SQL statement for others
-        for ( int index = 1; index < conditions.length; index++ )
-        {
-            condition = conditions[index].replace( "(", "" ).replace( ")", "" );
-
-            sql = "(" + createSQL( condition, aggregationCondition.getOperator(), orgunitId, startDate, endDate ) + ")";
-
-            subSQL.add( sql );
-        }
-
-        sql = getSQL( aggregationCondition.getOperator(), subSQL, operators ).replace( IN_CONDITION_START_SIGN, "(" )
-            .replaceAll( IN_CONDITION_END_SIGN, ")" );
-        return sql;
-    }
-
-    private String createSQL( String aggregationExpression, String operator, int orgunitId, String startDate,
-        String endDate )
-    {
-        // ---------------------------------------------------------------------
-        // get operators
-        // ---------------------------------------------------------------------
-
-        Pattern patternOperator = Pattern.compile( "(AND|OR)" );
-
-        Matcher matcherOperator = patternOperator.matcher( aggregationExpression );
-
-        List<String> operators = new ArrayList<String>();
-
-        while ( matcherOperator.find() )
-        {
-            operators.add( matcherOperator.group() );
-        }
-
-        String[] expression = aggregationExpression.split( "(AND|OR)" );
-
-        // ---------------------------------------------------------------------
-        // parse expressions
-        // ---------------------------------------------------------------------
-
-        Pattern patternCondition = Pattern.compile( regExp );
-
-        List<String> conditions = new ArrayList<String>();
-        double value = 0.0;
-
-        for ( int i = 0; i < expression.length; i++ )
-        {
-            String subExp = expression[i];
-            List<String> subConditions = new ArrayList<String>();
-
-            Matcher matcherCondition = patternCondition.matcher( expression[i] );
-
-            String condition = "";
-
-            while ( matcherCondition.find() )
-            {
-                String match = matcherCondition.group();
-                subExp = subExp.replace( match, "~" );
-                match = match.replaceAll( "[\\[\\]]", "" );
-
-                String[] info = match.split( SEPARATOR_OBJECT );
-
-                if ( info[0].equalsIgnoreCase( OBJECT_PATIENT ) )
-                {
-                    condition = getConditionForPatient( orgunitId, 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] );
-                    condition = getConditionForPatientAttribute( attributeId, operator );
-                }
-                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 valueToCompare = expression[i].replace( "[" + match + "]", "" ).trim();
-
-                    if ( valueToCompare.equalsIgnoreCase( IS_NULL ) )
-                    {
-                        condition = getConditionForNotDataElement( programId, programStageId, operator, dataElementId,
-                            orgunitId, startDate, endDate );
-
-                        expression[i] = expression[i].replace( valueToCompare, "" );
-                    }
-                    else
-                    {
-                        condition = getConditionForDataElement( programId, programStageId, operator, dataElementId,
-                            orgunitId, startDate, endDate );
-                        DataElement dataElement = dataElementService.getDataElement( dataElementId );
-                        if ( !expression[i].contains( "+" ) )
-                        {
-                            if ( dataElement.getType().equals( DataElement.VALUE_TYPE_INT ) )
-                            {
-                                condition += " AND cast( pd.value as " + statementBuilder.getDoubleColumnType() + ") ";
-                            }
-                            else
-                            {
-                                condition += " AND pd.value ";
-                            }
-                        }
-                        else
-                        {
-                            subConditions.add( condition );
-                        }
-                    }
-                }
-
-                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, orgunitId, 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, orgunitId, startDate, endDate );
-                    }
-                    else
-                    {
-                        condition = getConditionForProgramStage( ids[0], operator, orgunitId, startDate, endDate );
-                    }
-                }
-                else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE_PROPERTY ) )
-                {
-                    condition = getConditionForProgramStageProperty( info[1], operator, orgunitId, startDate, endDate );
-                }
-                else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY ) )
-                {
-                    condition = getConditionForPatientProgramStageProperty( info[1], operator, startDate, endDate );
-                }
-
-                // -------------------------------------------------------------
-                // Replacing the operand with 1 in order to later be able to
-                // verify
-                // that the formula is mathematically valid
-                // -------------------------------------------------------------
-
-                if ( expression[i].contains( "+" ) )
-                {
-                    Collection<Integer> patientIds = aggregationConditionStore.executeSQL( condition );
-                    value = calValue( patientIds, AGGRERATION_SUM );
-
-                    subExp = subExp.replace( "~", value + "" );
-                }
-
-                condition = expression[i].replace( match, condition ).replaceAll( "[\\[\\]]", "" );
-            }
-
-            if ( expression[i].contains( "+" ) )
-            {
-                final JEP parser = new JEP();
-
-                parser.parseExpression( subExp );
-
-                String _subExp = (parser.getValue() == 1.0) ? " AND 1 = 1 " : " AND 0 = 1 ";
-
-                int noPlus = expression[i].split( "\\+" ).length - 1;
-                List<String> subOperators = new ArrayList<String>();
-                for ( int j = 0; j < noPlus; j++ )
-                {
-                    subOperators.add( "AND" );
-                }
-
-                condition = getSQL( operator, subConditions, subOperators ) + _subExp;
-            }
-
-            conditions.add( condition );
-        }
-
-        return getSQL( operator, conditions, operators );
-    }
-
-    private String getConditionForNotDataElement( int programId, String programStageId, String operator,
-        int dataElementId, int orgunitId, String startDate, String endDate )
-    {
-        String sql = "SELECT distinct(pi.patientid) ";
-        String from = "FROM programstageinstance as psi "
-            + "INNER JOIN programinstance as pi ON pi.programinstanceid = psi.programinstanceid ";
-
-        String condition = "pi.patientid ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid ";
-            condition = "psi.programstageinstanceid ";
-        }
-
-        sql += from
-            + "LEFT OUTER JOIN patientdatavalue as pd ON psi.programstageinstanceid = pd.programstageinstanceid "
-            + "WHERE psi.executionDate >= '" + startDate + "' AND psi.executionDate <= '" + endDate + "' "
-            + "AND pd.value IS NULL AND " + condition + " NOT IN  ( " + "SELECT " + condition + from
-            + "WHERE psi.organisationunitid = " + orgunitId + " AND pi.programid = " + programId + " "
-            + "AND psi.executionDate >= '" + startDate + "' AND psi.executionDate <= '" + endDate + "' "
-            + "AND pd.dataelementid = " + dataElementId + " ";
-
-        if ( !programStageId.equals( IN_CONDITION_GET_ALL ) )
-        {
-            sql += " AND psi.programstageid = " + programStageId;
-        }
-
-        return sql + "  ) ";
-    }
-
-    private String getConditionForDataElement( int programId, String programStageId, String operator,
-        int dataElementId, int orgunitId, String startDate, String endDate )
-    {
-        String sql = "SELECT distinct(pi.patientid) ";
-        String from = "FROM programstageinstance as psi "
-            + "INNER JOIN patientdatavalue as pd ON psi.programstageinstanceid = pd.programstageinstanceid "
-            + "INNER JOIN programinstance as pi ON pi.programinstanceid = psi.programinstanceid ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid ";
-            from = "FROM programstageinstance as psi "
-                + "INNER JOIN patientdatavalue as pd ON psi.programstageinstanceid = pd.programstageinstanceid ";
-        }
-
-        sql += from + " WHERE pd.dataelementid=" + dataElementId + "  AND psi.organisationunitid=" + orgunitId
-            + "             AND psi.executionDate>='" + startDate + "' AND psi.executionDate <= '" + endDate + "'";
-
-        if ( !programStageId.equals( IN_CONDITION_GET_ALL ) )
-        {
-            sql += " AND psi.programstageid = " + programStageId;
-        }
-
-        return sql;
-    }
-
-    private String getConditionForPatientAttribute( int attributeId, String operator )
-    {
-        String sql = "SELECT distinct(pi.patientid) ";
-        String from = "FROM patientattributevalue pi ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid ";
-            from = "FROM programstageinstance psi inner join programinstance pi "
-                + "on psi.programinstanceid=pi.programinstanceid " + "inner join patientattributevalue pav "
-                + "on pav.patientid=pi.patientid ";
-        }
-
-        return sql + from + "WHERE patientattributeid=" + attributeId + " AND value ";
-    }
-
-    private String getConditionForPatient( int orgunitId, String operator, String startDate, String endDate )
-    {
-        String sql = "SELECT pi.patientid ";
-        String from = "FROM patient pi ";
-        String where = "WHERE pi.organisationunitid=" + orgunitId + "  AND pi.registrationdate>= '" + startDate + "' "
-            + "AND pi.registrationdate <= '" + endDate + "'";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid ";
-            from = "FROM programstageinstance psi inner join programinstance pi "
-                + "on psi.programinstanceid=pi.programinstanceid "
-                + "inner join patient p on p.patientid=pi.patientid ";
-            where = "WHERE p.organisationunitid=" + orgunitId + "  AND p.registrationdate>= '" + startDate + "' "
-                + "AND p.registrationdate <= '" + endDate + "'";
-        }
-
-        return sql + from + where;
-    }
-
-    private String getConditionForPatientProperty( String propertyName, String operator, String startDate,
-        String endDate )
-    {
-        String sql = "SELECT distinct(pi.patientid) FROM patient pi WHERE ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid " + "FROM programstageinstance psi inner join programinstance pi "
-                + "on psi.programinstanceid=pi.programinstanceid "
-                + "inner join patient p on p.patientid=pi.patientid WHERE ";
-        }
-
-        if ( propertyName.equals( PROPERTY_AGE ) )
-        {
-            sql += "DATE(registrationdate) - DATE(birthdate) ";
-        }
-        else
-        {
-            sql += propertyName + " ";
-        }
-
-        return sql;
-    }
-
-    private String getConditionForPatientProgramStageProperty( String propertyName, String operator, String startDate,
-        String endDate )
-    {
-        String sql = "SELECT distinct(pi.patientid) ";
-        String from = "FROM programinstance pi INNER JOIN programstageinstance psi "
-            + "ON psi.programinstanceid=pi.programinstanceid ";
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstance ";
-            from = "FROM programstageinstance psi ";
-        }
-
-        from += "inner join patient p on p.patientid=pi.patientid ";
-
-        sql += from + "WHERE executionDate>='" + startDate + "' and executionDate<='" + endDate + "' and "
-            + propertyName;
-
-        return sql;
-    }
-
-    private String getConditionForProgramProperty( String operator, String startDate, String endDate, String property )
-    {
-        String sql = "SELECT pi.patientid FROM programinstance as pi ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid FROM programinstance as pi "
-                + "INNER JOIN programstageinstance psi ON psi.programinstanceid=pi.programinstanceid ";
-        }
-
-        return sql + "WHERE pi.enrollmentdate>='" + startDate + "' " + "AND pi.enrollmentdate<='" + endDate + "'  AND "
-            + property;
-    }
-
-    private String getConditionForProgram( String programId, String operator, int orgunitId, String startDate,
-        String endDate )
-    {
-        String sql = "SELECT distinct(pi.patientid) FROM programinstance as pi "
-            + "inner join patient psi on psi.patientid=pi.patientid ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            sql = "SELECT psi.programstageinstanceid FROM programinstance as pi "
-                + "INNER JOIN programstageinstance psi ON pi.programinstanceid=psi.programinstanceid ";
-        }
-
-        return sql + "WHERE pi.programid=" + programId + " " + " AND psi.organisationunitid = " + orgunitId
-            + " AND pi.enrollmentdate >= '" + startDate + "' AND pi.enrollmentdate <= '" + endDate + "' ";
-    }
-
-    private String getConditionForProgramStage( String programStageId, String operator, int orgunitId,
-        String startDate, String endDate )
-    {
-        String select = "SELECT distinct(pi.patientid) ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            select = "SELECT psi.programstageinstanceid ";
-        }
-
-        return select + "FROM programinstance as pi INNER JOIN programstageinstance psi "
-            + "ON pi.programinstanceid = psi.programinstanceid WHERE psi.programstageid=" + programStageId + " "
-            + "AND psi.executiondate >= '" + startDate + "' AND psi.executiondate <= '" + endDate
-            + "' AND psi.organisationunitid = " + orgunitId + " ";
-    }
-
-    private String getConditionForCountProgramStage( String programStageId, String operator, int orgunitId,
-        String startDate, String endDate )
-    {
-        String select = "SELECT distinct(pi.patientid) ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            select = "SELECT psi.programstageinstanceid ";
-        }
-
-        select += "FROM programstageinstance as psi "
-            + "INNER JOIN programinstance as pi ON pi.programinstanceid = psi.programinstanceid "
-            + "WHERE psi.organisationunitid = " + orgunitId + " and psi.programstageid = " + programStageId + " "
-            + "AND psi.executionDate >= '" + startDate + "' AND psi.executionDate <= '" + endDate + "' "
-            + "GROUP BY psi.programinstanceid ";
-
-        if ( operator.equals( AGGRERATION_COUNT ) )
-        {
-            select += ",pi.patientid ";
-        }
-
-        select += "HAVING count(psi.programstageinstanceid) ";
-
-        return select;
-
-    }
-
-    private String getConditionForProgramStageProperty( String property, String operator, int orgunitId,
-        String startDate, String endDate )
-    {
-        String select = "SELECT distinct(pi.patientid) ";
-
-        if ( !operator.equals( AGGRERATION_COUNT ) )
-        {
-            select = "SELECT psi.programstageinstanceid ";
-        }
-
-        return select + "FROM programinstance as pi INNER JOIN programstageinstance psi "
-            + "ON pi.programinstanceid = psi.programinstanceid WHERE " + " psi.executiondate >= '" + startDate
-            + "' AND psi.executiondate <= '" + endDate + "' AND psi.organisationunitid = " + orgunitId + " AND "
-            + property;
-    }
-
-    private String getSQL( String aggregateOperator, List<String> conditions, List<String> operators )
-    {
-        String sql = conditions.get( 0 );
-
-        String sqlAnd = "";
-
-        int index = 0;
-
-        for ( index = 0; index < operators.size(); index++ )
-        {
-            if ( operators.get( index ).equalsIgnoreCase( OPERATOR_AND ) )
-            {
-                if ( aggregateOperator.equals( AGGRERATION_COUNT ) )
-                {
-                    sql += " AND pi.patientid IN ( " + conditions.get( index + 1 );
-                }
-                else
-                {
-                    sql += " AND psi.programstageinstanceid IN ( " + conditions.get( index + 1 );
-                }
-                sqlAnd += ")";
-            }
-            else
-            {
-                sql += sqlAnd;
-                sql += " UNION ( " + conditions.get( index + 1 ) + " ) ";
-                sqlAnd = "";
-            }
-        }
-
-        sql += sqlAnd;
-
-        return sql;
+    private int getProcessNo()
+    {
+        return Math.max( (SystemUtils.getCpuCores() - 1), 1 );
     }
 
     public Integer calValue( Collection<Integer> patientIds, String operator )

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionStore.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionStore.java	2013-01-15 10:28:17 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/caseaggregation/jdbc/JdbcCaseAggregationConditionStore.java	2013-04-01 05:56:41 +0000
@@ -27,19 +27,55 @@
 
 package org.hisp.dhis.caseaggregation.jdbc;
 
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.AGGRERATION_COUNT;
+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.OPERATOR_AND;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_ID;
+import static org.hisp.dhis.caseaggregation.CaseAggregationCondition.SEPARATOR_OBJECT;
+import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_12_MONTH;
+import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_3_MONTH;
+import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_6_MONTH;
+import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_MONTH;
+
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
 import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Future;
+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.hibernate.HibernateIdentifiableObjectStore;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.jdbc.StatementBuilder;
+import org.hisp.dhis.period.CalendarPeriodType;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodService;
+import org.hisp.dhis.program.ProgramStageInstanceService;
+import org.hisp.dhis.system.util.DateUtils;
+import org.nfunk.jep.JEP;
 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
@@ -50,21 +86,56 @@
     extends HibernateIdentifiableObjectStore<CaseAggregationCondition>
     implements CaseAggregationConditionStore
 {
+    private final String regExp = "\\[(" + OBJECT_PATIENT + "|" + OBJECT_PROGRAM + "|" + OBJECT_PROGRAM_STAGE + "|"
+        + OBJECT_PROGRAM_STAGE_PROPERTY + "|" + OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY + "|"
+        + OBJECT_PROGRAM_STAGE_DATAELEMENT + "|" + OBJECT_PATIENT_ATTRIBUTE + "|" + OBJECT_PATIENT_PROPERTY + "|"
+        + OBJECT_PROGRAM_PROPERTY + ")" + SEPARATOR_OBJECT + "([a-zA-Z0-9@#\\- ]+[" + SEPARATOR_ID + "[a-zA-Z0-9]*]*)"
+        + "\\]";
+
+    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";
+
     // -------------------------------------------------------------------------
     // Dependency
     // -------------------------------------------------------------------------
 
     private JdbcTemplate jdbcTemplate;
 
-    // -------------------------------------------------------------------------
-    // Setters
-    // -------------------------------------------------------------------------
-
     public void setJdbcTemplate( JdbcTemplate jdbcTemplate )
     {
         this.jdbcTemplate = jdbcTemplate;
     }
 
+    private StatementBuilder statementBuilder;
+
+    public void setStatementBuilder( StatementBuilder statementBuilder )
+    {
+        this.statementBuilder = statementBuilder;
+    }
+
+    private ProgramStageInstanceService programStageInstanceService;
+
+    public void setProgramStageInstanceService( ProgramStageInstanceService programStageInstanceService )
+    {
+        this.programStageInstanceService = programStageInstanceService;
+    }
+
+    private PeriodService periodService;
+
+    public void setPeriodService( PeriodService periodService )
+    {
+        this.periodService = periodService;
+    }
+
     // -------------------------------------------------------------------------
     // Implementation Methods
     // -------------------------------------------------------------------------
@@ -82,7 +153,7 @@
                     return rs.getInt( 1 );
                 }
             } );
-            
+
             return patientIds;
         }
         catch ( Exception ex )
@@ -112,4 +183,700 @@
     {
         return getCriteria( Restrictions.in( "aggregationDataElement", dataElements ) ).list();
     }
+
+    public static final String STORED_BY_DHIS_SYSTEM = "DHIS-System";
+
+    @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 Double getAggregateValue( String caseExpression, String operator, String deType, Integer deSumId,
+        Integer orgunitId, Period period )
+    {
+        String startDate = DateUtils.getMediumDateString( period.getStartDate() );
+        String endDate = DateUtils.getMediumDateString( period.getEndDate() );
+
+        if ( operator.equals( CaseAggregationCondition.AGGRERATION_COUNT )
+            || operator.equals( CaseAggregationCondition.AGGRERATION_SUM ) )
+        {
+            String sql =  parseExpressionToSql( caseExpression, operator, deType, deSumId, orgunitId, startDate, endDate );
+            Collection<Integer> ids = this.executeSQL( sql );
+            return (ids == null) ? null : ids.size() + 0.0;
+        }
+
+        String sql = "SELECT " + operator + "( cast( pdv.value as DOUBLE PRECISION ) ) ";
+        sql += "FROM patientdatavalue pdv ";
+        sql += "    INNER JOIN programstageinstance psi  ";
+        sql += "    ON psi.programstageinstanceid = pdv.programstageinstanceid ";
+        sql += "WHERE executiondate >='" + DateUtils.getMediumDateString( period.getStartDate() ) + "'  ";
+        sql += "    AND executiondate <='" + DateUtils.getMediumDateString( period.getEndDate() )
+            + "' AND pdv.dataelementid=" + deSumId;
+
+        if ( caseExpression != null && !caseExpression.isEmpty() )
+        {
+            sql = sql + " AND pdv.programstageinstanceid in ( "
+                + parseExpressionToSql( caseExpression, operator, deType, deSumId, orgunitId, startDate, endDate ) + " ) ";
+        }
+
+        Collection<Integer> ids = this.executeSQL( sql );
+        return (ids == null) ? null : ids.iterator().next() + 0.0;
+    }
+    
+    public String parseExpressionToSql( String aggregationExpression, String operator, String deType, Integer deSumId,
+        Integer orgunitId, String startDate, String endDate )
+    {
+        // Get operators between ( )
+        Pattern patternOperator = Pattern.compile( "(\\)\\s*(OR|AND)\\s*\\( )" );
+
+        Matcher matcherOperator = patternOperator.matcher( aggregationExpression );
+
+        List<String> operators = new ArrayList<String>();
+
+        while ( matcherOperator.find() )
+        {
+            operators.add( matcherOperator.group( 2 ) );
+        }
+
+        List<String> subSQL = new ArrayList<String>();
+
+        String[] conditions = aggregationExpression.split( "(\\)\\s*(OR|AND)\\s*\\()" );
+
+        // Create SQL statement for the first condition
+        String condition = conditions[0].replace( "(", "" ).replace( ")", "" );
+
+        String sql = createSQL( condition, operator, deType, orgunitId, startDate, endDate );
+
+        subSQL.add( sql );
+
+        // Create SQL statement for others
+        for ( int index = 1; index < conditions.length; index++ )
+        {
+            condition = conditions[index].replace( "(", "" ).replace( ")", "" );
+
+            sql = "(" + createSQL( condition, operator, deType, orgunitId, startDate, endDate ) + ")";
+
+            subSQL.add( sql );
+        }
+
+        sql = getSQL( operator, subSQL, operators ).replace( IN_CONDITION_START_SIGN, "(" ).replaceAll(
+            IN_CONDITION_END_SIGN, ")" );
+        return sql;
+    }
+    
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private void runAggregate( Collection<Integer> orgunitIds, CaseAggregateSchedule dataSet, Collection<Period> periods )
+    {
+        String sql = "select caseaggregationconditionid, aggregationdataelementid, optioncomboid, de.valuetype as deType, "
+            + " 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" );
+                String deType = rs.getString( "deType" );
+                int deSumId = rs.getInt( "desumid" );
+
+                Collection<Integer> _orgunitIds = programStageInstanceService.getOrganisationUnitIds(
+                    period.getStartDate(), period.getEndDate() );
+                if ( orgunitIds == null )
+                {
+                    orgunitIds = new HashSet<Integer>();
+                    orgunitIds.addAll( _orgunitIds );
+                }
+                else
+                {
+                    orgunitIds.retainAll( _orgunitIds );
+                }
+                // ---------------------------------------------------------------------
+                // Aggregation
+                // ---------------------------------------------------------------------
+
+                for ( Integer orgunitId : orgunitIds )
+                {
+                    String dataValueSql = "select * from datavalue where dataelementid=" + dataelementId
+                        + " and categoryoptioncomboid=" + optionComboId + " and sourceid=" + orgunitId
+                        + " and periodid=" + period.getId() + "";
+
+                    boolean hasValue = jdbcTemplate.queryForRowSet( dataValueSql ).next();
+
+                    Double resultValue = getAggregateValue( caseExpression, caseOperator, deType, deSumId, orgunitId,
+                        period );
+
+                    if ( resultValue != null && resultValue != 0 )
+                    {
+                        // -----------------------------------------------------
+                        // Add dataValue
+                        // -----------------------------------------------------
+
+                        if ( !hasValue )
+                        {
+                            String insertValueSql = "INSERT INTO datavalue ( dataelementid, periodid, sourceid, categoryoptioncomboid, value, storedby, lastupdated, followup ) "
+                                + "VALUES ( "
+                                + dataelementId
+                                + ", "
+                                + period.getId()
+                                + ", "
+                                + orgunitId
+                                + ", "
+                                + optionComboId
+                                + ", "
+                                + resultValue
+                                + ", '"
+                                + STORED_BY_DHIS_SYSTEM
+                                + "', '"
+                                + DateUtils.getMediumDateString( new Date() ) + "', false )";
+                            jdbcTemplate.execute( insertValueSql );
+                        }
+
+                        // -----------------------------------------------------
+                        // Update dataValue
+                        // -----------------------------------------------------
+                        else
+                        {
+                            sql = "UPDATE datavalue" + " SET value='" + resultValue + "',lastupdated='" + new Date()
+                                + "' where dataelementId=" + dataelementId + " and periodid=" + period.getId()
+                                + " and sourceid=" + orgunitId + " and categoryoptioncomboid=" + optionComboId
+                                + " and storedby='" + STORED_BY_DHIS_SYSTEM + "'";
+                            jdbcTemplate.execute( sql );
+                        }
+                    }
+
+                    // ---------------------------------------------------------
+                    // Delete dataValue
+                    // ---------------------------------------------------------
+                    else if ( hasValue )
+                    {
+                        String deleteSql = "DELETE from datavalue where dataelementid=dataelementid and periodid=periodid and sourceid=sourceid and categoryoptioncomboid=categoryoptioncomboid";
+                        jdbcTemplate.execute( deleteSql );
+                    }
+                }
+            }
+
+        }
+    }
+
+    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) CalendarPeriodType.getPeriodTypeByName( periodTypeName );
+
+        Collection<Period> periods = periodType.generatePeriods( startDate, endDate );
+
+        for ( Period period : periods )
+        {
+            Period _period = periodService.getPeriod( period.getStartDate(), period.getEndDate(), periodType );
+            if ( _period == null )
+            {
+                int id = periodService.addPeriod( period );
+                period.setId( id );
+            }
+            else
+            {
+                period.setId( _period.getId() );
+            }
+        }
+
+        return periods;
+    }
+
+    private String createSQL( String aggregationExpression, String operator, String deType, int orgunitId,
+        String startDate, String endDate )
+    {
+        // ---------------------------------------------------------------------
+        // get operators
+        // ---------------------------------------------------------------------
+
+        Pattern patternOperator = Pattern.compile( "(AND|OR)" );
+
+        Matcher matcherOperator = patternOperator.matcher( aggregationExpression );
+
+        List<String> operators = new ArrayList<String>();
+
+        while ( matcherOperator.find() )
+        {
+            operators.add( matcherOperator.group() );
+        }
+
+        String[] expression = aggregationExpression.split( "(AND|OR)" );
+
+        // ---------------------------------------------------------------------
+        // parse expressions
+        // ---------------------------------------------------------------------
+
+        Pattern patternCondition = Pattern.compile( regExp );
+
+        List<String> conditions = new ArrayList<String>();
+        double value = 0.0;
+
+        for ( int i = 0; i < expression.length; i++ )
+        {
+            String subExp = expression[i];
+            List<String> subConditions = new ArrayList<String>();
+
+            Matcher matcherCondition = patternCondition.matcher( expression[i] );
+
+            String condition = "";
+
+            while ( matcherCondition.find() )
+            {
+                String match = matcherCondition.group();
+                subExp = subExp.replace( match, "~" );
+                match = match.replaceAll( "[\\[\\]]", "" );
+
+                String[] info = match.split( SEPARATOR_OBJECT );
+
+                if ( info[0].equalsIgnoreCase( OBJECT_PATIENT ) )
+                {
+                    condition = getConditionForPatient( orgunitId, 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] );
+                    condition = getConditionForPatientAttribute( attributeId, operator );
+                }
+                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 valueToCompare = expression[i].replace( "[" + match + "]", "" ).trim();
+
+                    if ( valueToCompare.equalsIgnoreCase( IS_NULL ) )
+                    {
+                        condition = getConditionForNotDataElement( programId, programStageId, operator, dataElementId,
+                            orgunitId, startDate, endDate );
+
+                        expression[i] = expression[i].replace( valueToCompare, "" );
+                    }
+                    else
+                    {
+                        condition = getConditionForDataElement( programId, programStageId, operator, dataElementId,
+                            orgunitId, startDate, endDate );
+
+                        if ( !expression[i].contains( "+" ) )
+                        {
+                            if ( deType.equals( DataElement.VALUE_TYPE_INT ) )
+                            {
+                                condition += " AND cast( pd.value as " + statementBuilder.getDoubleColumnType() + ") ";
+                            }
+                            else
+                            {
+                                condition += " AND pd.value ";
+                            }
+                        }
+                        else
+                        {
+                            subConditions.add( condition );
+                        }
+                    }
+                }
+
+                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, orgunitId, 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, orgunitId, startDate, endDate );
+                    }
+                    else
+                    {
+                        condition = getConditionForProgramStage( ids[0], operator, orgunitId, startDate, endDate );
+                    }
+                }
+                else if ( info[0].equalsIgnoreCase( OBJECT_PROGRAM_STAGE_PROPERTY ) )
+                {
+                    condition = getConditionForProgramStageProperty( info[1], operator, orgunitId, startDate, endDate );
+                }
+                else if ( info[0].equalsIgnoreCase( OBJECT_PATIENT_PROGRAM_STAGE_PROPERTY ) )
+                {
+                    condition = getConditionForPatientProgramStageProperty( info[1], operator, startDate, endDate );
+                }
+
+                // -------------------------------------------------------------
+                // Replacing the operand with 1 in order to later be able to
+                // verify
+                // that the formula is mathematically valid
+                // -------------------------------------------------------------
+
+                if ( expression[i].contains( "+" ) )
+                {
+                    Collection<Integer> patientIds = executeSQL( condition );
+                    value = patientIds.size();
+
+                    subExp = subExp.replace( "~", value + "" );
+                }
+
+                condition = expression[i].replace( match, condition ).replaceAll( "[\\[\\]]", "" );
+            }
+
+            if ( expression[i].contains( "+" ) )
+            {
+                final JEP parser = new JEP();
+
+                parser.parseExpression( subExp );
+
+                String _subExp = (parser.getValue() == 1.0) ? " AND 1 = 1 " : " AND 0 = 1 ";
+
+                int noPlus = expression[i].split( "\\+" ).length - 1;
+                List<String> subOperators = new ArrayList<String>();
+                for ( int j = 0; j < noPlus; j++ )
+                {
+                    subOperators.add( "AND" );
+                }
+
+                condition = getSQL( operator, subConditions, subOperators ) + _subExp;
+            }
+
+            conditions.add( condition );
+        }
+
+        return getSQL( operator, conditions, operators );
+    }
+
+    private String getConditionForNotDataElement( int programId, String programStageId, String operator,
+        int dataElementId, int orgunitId, String startDate, String endDate )
+    {
+        String sql = "SELECT distinct(pi.patientid) ";
+        String from = "FROM programstageinstance as psi "
+            + "INNER JOIN programinstance as pi ON pi.programinstanceid = psi.programinstanceid ";
+
+        String condition = "pi.patientid ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid ";
+            condition = "psi.programstageinstanceid ";
+        }
+
+        sql += from
+            + "LEFT OUTER JOIN patientdatavalue as pd ON psi.programstageinstanceid = pd.programstageinstanceid "
+            + "WHERE psi.executionDate >= '" + startDate + "' AND psi.executionDate <= '" + endDate + "' "
+            + "AND pd.value IS NULL AND " + condition + " NOT IN  ( " + "SELECT " + condition + from
+            + "WHERE psi.organisationunitid = " + orgunitId + " AND pi.programid = " + programId + " "
+            + "AND psi.executionDate >= '" + startDate + "' AND psi.executionDate <= '" + endDate + "' "
+            + "AND pd.dataelementid = " + dataElementId + " ";
+
+        if ( !programStageId.equals( IN_CONDITION_GET_ALL ) )
+        {
+            sql += " AND psi.programstageid = " + programStageId;
+        }
+
+        return sql + "  ) ";
+    }
+
+    private String getConditionForDataElement( int programId, String programStageId, String operator,
+        int dataElementId, int orgunitId, String startDate, String endDate )
+    {
+        String sql = "SELECT distinct(pi.patientid) ";
+        String from = "FROM programstageinstance as psi "
+            + "INNER JOIN patientdatavalue as pd ON psi.programstageinstanceid = pd.programstageinstanceid "
+            + "INNER JOIN programinstance as pi ON pi.programinstanceid = psi.programinstanceid ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid ";
+            from = "FROM programstageinstance as psi "
+                + "INNER JOIN patientdatavalue as pd ON psi.programstageinstanceid = pd.programstageinstanceid ";
+        }
+
+        sql += from + " WHERE pd.dataelementid=" + dataElementId + "  AND psi.organisationunitid=" + orgunitId
+            + "             AND psi.executionDate>='" + startDate + "' AND psi.executionDate <= '" + endDate + "'";
+
+        if ( !programStageId.equals( IN_CONDITION_GET_ALL ) )
+        {
+            sql += " AND psi.programstageid = " + programStageId;
+        }
+
+        return sql;
+    }
+
+    private String getConditionForPatientAttribute( int attributeId, String operator )
+    {
+        String sql = "SELECT distinct(pi.patientid) ";
+        String from = "FROM patientattributevalue pi ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid ";
+            from = "FROM programstageinstance psi inner join programinstance pi "
+                + "on psi.programinstanceid=pi.programinstanceid " + "inner join patientattributevalue pav "
+                + "on pav.patientid=pi.patientid ";
+        }
+
+        return sql + from + "WHERE patientattributeid=" + attributeId + " AND value ";
+    }
+
+    private String getConditionForPatient( int orgunitId, String operator, String startDate, String endDate )
+    {
+        String sql = "SELECT pi.patientid ";
+        String from = "FROM patient pi ";
+        String where = "WHERE pi.organisationunitid=" + orgunitId + "  AND pi.registrationdate>= '" + startDate + "' "
+            + "AND pi.registrationdate <= '" + endDate + "'";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid ";
+            from = "FROM programstageinstance psi inner join programinstance pi "
+                + "on psi.programinstanceid=pi.programinstanceid "
+                + "inner join patient p on p.patientid=pi.patientid ";
+            where = "WHERE p.organisationunitid=" + orgunitId + "  AND p.registrationdate>= '" + startDate + "' "
+                + "AND p.registrationdate <= '" + endDate + "'";
+        }
+
+        return sql + from + where;
+    }
+
+    private String getConditionForPatientProperty( String propertyName, String operator, String startDate,
+        String endDate )
+    {
+        String sql = "SELECT distinct(pi.patientid) FROM patient pi WHERE ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid " + "FROM programstageinstance psi inner join programinstance pi "
+                + "on psi.programinstanceid=pi.programinstanceid "
+                + "inner join patient p on p.patientid=pi.patientid WHERE ";
+        }
+
+        if ( propertyName.equals( PROPERTY_AGE ) )
+        {
+            sql += "DATE(registrationdate) - DATE(birthdate) ";
+        }
+        else
+        {
+            sql += propertyName + " ";
+        }
+
+        return sql;
+    }
+
+    private String getConditionForPatientProgramStageProperty( String propertyName, String operator, String startDate,
+        String endDate )
+    {
+        String sql = "SELECT distinct(pi.patientid) ";
+        String from = "FROM programinstance pi INNER JOIN programstageinstance psi "
+            + "ON psi.programinstanceid=pi.programinstanceid ";
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstance ";
+            from = "FROM programstageinstance psi ";
+        }
+
+        from += "inner join patient p on p.patientid=pi.patientid ";
+
+        sql += from + "WHERE executionDate>='" + startDate + "' and executionDate<='" + endDate + "' and "
+            + propertyName;
+
+        return sql;
+    }
+
+    private String getConditionForProgramProperty( String operator, String startDate, String endDate, String property )
+    {
+        String sql = "SELECT pi.patientid FROM programinstance as pi ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid FROM programinstance as pi "
+                + "INNER JOIN programstageinstance psi ON psi.programinstanceid=pi.programinstanceid ";
+        }
+
+        return sql + "WHERE pi.enrollmentdate>='" + startDate + "' " + "AND pi.enrollmentdate<='" + endDate + "'  AND "
+            + property;
+    }
+
+    private String getConditionForProgram( String programId, String operator, int orgunitId, String startDate,
+        String endDate )
+    {
+        String sql = "SELECT distinct(pi.patientid) FROM programinstance as pi "
+            + "inner join patient psi on psi.patientid=pi.patientid ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            sql = "SELECT psi.programstageinstanceid FROM programinstance as pi "
+                + "INNER JOIN programstageinstance psi ON pi.programinstanceid=psi.programinstanceid ";
+        }
+
+        return sql + "WHERE pi.programid=" + programId + " " + " AND psi.organisationunitid = " + orgunitId
+            + " AND pi.enrollmentdate >= '" + startDate + "' AND pi.enrollmentdate <= '" + endDate + "' ";
+    }
+
+    private String getConditionForProgramStage( String programStageId, String operator, int orgunitId,
+        String startDate, String endDate )
+    {
+        String select = "SELECT distinct(pi.patientid) ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            select = "SELECT psi.programstageinstanceid ";
+        }
+
+        return select + "FROM programinstance as pi INNER JOIN programstageinstance psi "
+            + "ON pi.programinstanceid = psi.programinstanceid WHERE psi.programstageid=" + programStageId + " "
+            + "AND psi.executiondate >= '" + startDate + "' AND psi.executiondate <= '" + endDate
+            + "' AND psi.organisationunitid = " + orgunitId + " ";
+    }
+
+    private String getConditionForCountProgramStage( String programStageId, String operator, int orgunitId,
+        String startDate, String endDate )
+    {
+        String select = "SELECT distinct(pi.patientid) ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            select = "SELECT psi.programstageinstanceid ";
+        }
+
+        select += "FROM programstageinstance as psi "
+            + "INNER JOIN programinstance as pi ON pi.programinstanceid = psi.programinstanceid "
+            + "WHERE psi.organisationunitid = " + orgunitId + " and psi.programstageid = " + programStageId + " "
+            + "AND psi.executionDate >= '" + startDate + "' AND psi.executionDate <= '" + endDate + "' "
+            + "GROUP BY psi.programinstanceid ";
+
+        if ( operator.equals( AGGRERATION_COUNT ) )
+        {
+            select += ",pi.patientid ";
+        }
+
+        select += "HAVING count(psi.programstageinstanceid) ";
+
+        return select;
+
+    }
+
+    private String getConditionForProgramStageProperty( String property, String operator, int orgunitId,
+        String startDate, String endDate )
+    {
+        String select = "SELECT distinct(pi.patientid) ";
+
+        if ( !operator.equals( AGGRERATION_COUNT ) )
+        {
+            select = "SELECT psi.programstageinstanceid ";
+        }
+
+        return select + "FROM programinstance as pi INNER JOIN programstageinstance psi "
+            + "ON pi.programinstanceid = psi.programinstanceid WHERE " + " psi.executiondate >= '" + startDate
+            + "' AND psi.executiondate <= '" + endDate + "' AND psi.organisationunitid = " + orgunitId + " AND "
+            + property;
+    }
+
+    private String getSQL( String aggregateOperator, List<String> conditions, List<String> operators )
+    {
+        String sql = conditions.get( 0 );
+
+        String sqlAnd = "";
+
+        int index = 0;
+
+        for ( index = 0; index < operators.size(); index++ )
+        {
+            if ( operators.get( index ).equalsIgnoreCase( OPERATOR_AND ) )
+            {
+                if ( aggregateOperator.equals( AGGRERATION_COUNT ) )
+                {
+                    sql += " AND pi.patientid IN ( " + conditions.get( index + 1 );
+                }
+                else
+                {
+                    sql += " AND psi.programstageinstanceid IN ( " + conditions.get( index + 1 );
+                }
+                sqlAnd += ")";
+            }
+            else
+            {
+                sql += sqlAnd;
+                sql += " UNION ( " + conditions.get( index + 1 ) + " ) ";
+                sqlAnd = "";
+            }
+        }
+
+        sql += sqlAnd;
+
+        return sql;
+    }
+
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/scheduling/CaseAggregateConditionTask.java'
--- dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/scheduling/CaseAggregateConditionTask.java	2013-03-29 04:26:45 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/java/org/hisp/dhis/patient/scheduling/CaseAggregateConditionTask.java	2013-04-01 05:56:41 +0000
@@ -27,31 +27,15 @@
 
 package org.hisp.dhis.patient.scheduling;
 
-import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_12_MONTH;
-import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_3_MONTH;
-import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_6_MONTH;
-import static org.hisp.dhis.patient.scheduling.CaseAggregateConditionSchedulingManager.TASK_AGGREGATE_QUERY_BUILDER_LAST_MONTH;
 import static org.hisp.dhis.setting.SystemSettingManager.DEFAULT_SCHEDULE_AGGREGATE_QUERY_BUILDER_TASK_STRATEGY;
 import static org.hisp.dhis.setting.SystemSettingManager.KEY_SCHEDULE_AGGREGATE_QUERY_BUILDER_TASK_STRATEGY;
 import static org.hisp.dhis.system.notification.NotificationLevel.INFO;
 
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
+import java.util.ArrayList;
+import java.util.List;
 
-import org.hisp.dhis.caseaggregation.CaseAggregationCondition;
+import org.hisp.dhis.caseaggregation.CaseAggregateSchedule;
 import org.hisp.dhis.caseaggregation.CaseAggregationConditionService;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
-import org.hisp.dhis.dataelement.DataElementCategoryService;
-import org.hisp.dhis.dataelement.DataElementService;
-import org.hisp.dhis.datavalue.DataValue;
-import org.hisp.dhis.datavalue.DataValueService;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.organisationunit.OrganisationUnitService;
-import org.hisp.dhis.period.CalendarPeriodType;
-import org.hisp.dhis.period.Period;
-import org.hisp.dhis.program.ProgramStageInstanceService;
 import org.hisp.dhis.scheduling.TaskId;
 import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.system.notification.Notifier;
@@ -68,55 +52,31 @@
 public class CaseAggregateConditionTask
     implements Runnable
 {
-    public static final String STORED_BY_DHIS_SYSTEM = "DHIS-System";
-
     private CaseAggregationConditionService aggregationConditionService;
-
-    private DataValueService dataValueService;
-
+    
     private JdbcTemplate jdbcTemplate;
-
-    private DataElementService dataElementService;
-
-    private DataElementCategoryService categoryService;
-
+    
     private SystemSettingManager systemSettingManager;
-
-    private ProgramStageInstanceService programStageInstanceService;
-    
-    private OrganisationUnitService organisationUnitService;
     
     private Notifier notifier;
 
-    public void setNotifier( Notifier notifier )
-    {
-        this.notifier = notifier;
-    }
-    
     private TaskId taskId;
 
     public void setTaskId( TaskId taskId )
     {
         this.taskId = taskId;
     }
-    
+
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
 
     public CaseAggregateConditionTask( CaseAggregationConditionService aggregationConditionService,
-        DataValueService dataValueService, JdbcTemplate jdbcTemplate, DataElementService dataElementService,
-        DataElementCategoryService categoryService, SystemSettingManager systemSettingManager,
-        ProgramStageInstanceService programStageInstanceService, OrganisationUnitService organisationUnitService, Notifier notifier )
+        JdbcTemplate jdbcTemplate, SystemSettingManager systemSettingManager, Notifier notifier )
     {
         this.aggregationConditionService = aggregationConditionService;
-        this.dataValueService = dataValueService;
         this.jdbcTemplate = jdbcTemplate;
-        this.dataElementService = dataElementService;
-        this.categoryService = categoryService;
         this.systemSettingManager = systemSettingManager;
-        this.programStageInstanceService = programStageInstanceService;
-        this.organisationUnitService = organisationUnitService;
         this.notifier = notifier;
     }
 
@@ -128,146 +88,35 @@
     public void run()
     {
         final int cpuCores = SystemUtils.getCpuCores();
-        Clock clock = new Clock().startClock().logTime( "Aggregate process started, number of CPU cores: " + cpuCores + ", " + SystemUtils.getMemoryString() );
+        Clock clock = new Clock().startClock().logTime(
+            "Aggregate process started, number of CPU cores: " + cpuCores + ", " + SystemUtils.getMemoryString() );
         notifier.clear( taskId ).notify( taskId, "Aggregate process started" );
- 
+
         String taskStrategy = (String) systemSettingManager.getSystemSetting(
             KEY_SCHEDULE_AGGREGATE_QUERY_BUILDER_TASK_STRATEGY, DEFAULT_SCHEDULE_AGGREGATE_QUERY_BUILDER_TASK_STRATEGY );
 
-        String datasetSQL = "select dm.datasetid as datasetid, pt.name as periodname, ds.name as datasetname";
+        // Get datasets which are used in case-aggregate-query-builder formula
+        
+        String datasetSQL = "select dm.datasetid as datasetid, pt.name as periodtypename, ds.name as datasetname";
         datasetSQL += "      from caseaggregationcondition cagg inner join datasetmembers dm ";
         datasetSQL += "            on cagg.aggregationdataelementid=dm.dataelementid inner join dataset ds ";
         datasetSQL += "            on ds.datasetid = dm.datasetid inner join periodtype pt ";
         datasetSQL += "            on pt.periodtypeid=ds.periodtypeid ";
 
         SqlRowSet rsDataset = jdbcTemplate.queryForRowSet( datasetSQL );
+        List<CaseAggregateSchedule> caseAggregateSchedule = new ArrayList<CaseAggregateSchedule>();
         while ( rsDataset.next() )
         {
-            int datasetId = rsDataset.getInt( "datasetid" );
-            String datasetName = rsDataset.getString( "datasetname" );
-            
-            Collection<Period> periods = getPeriod( rsDataset.getString( "periodname" ), taskStrategy );
-
-            for ( Period period : periods )
-            {
-                String sql = "select caseaggregationconditionid, aggregationdataelementid, optioncomboid "
-                    + "     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 " + "where ds.datasetid = " + datasetId;
-
-                SqlRowSet rs = jdbcTemplate.queryForRowSet( sql );
-
-                Collection<Integer> orgunitIds = programStageInstanceService.getOrganisationUnitIds(
-                    period.getStartDate(), period.getEndDate() );
-                
-                while ( rs.next() )
-                {
-                    // -------------------------------------------------------------
-                    // Get formula, agg-dataelement and option-combo
-                    // -------------------------------------------------------------
-
-                    int dataelementId = rs.getInt( "aggregationdataelementid" );
-                    int optionComboId = rs.getInt( "optioncomboid" );
-
-                    DataElement dElement = dataElementService.getDataElement( dataelementId );
-                    DataElementCategoryOptionCombo optionCombo = categoryService
-                        .getDataElementCategoryOptionCombo( optionComboId );
-
-                    CaseAggregationCondition aggCondition = aggregationConditionService.getCaseAggregationCondition( rs
-                        .getInt( "caseaggregationconditionid" ) );
-
-                    // ---------------------------------------------------------------------
-                    // Aggregation
-                    // ---------------------------------------------------------------------
-
-                    for ( Integer orgUnitId : orgunitIds )
-                    {
-                        OrganisationUnit orgUnit = organisationUnitService.getOrganisationUnit( orgUnitId );
-                        DataValue dataValue = dataValueService.getDataValue( orgUnit, dElement, period, optionCombo );
-
-                        Integer resultValue = aggregationConditionService.parseConditition( aggCondition, orgUnit,
-                            period );
-
-                        if ( resultValue != null && resultValue != 0 )
-                        {
-                            // -----------------------------------------------------
-                            // Add dataValue
-                            // -----------------------------------------------------
-
-                            if ( dataValue == null )
-                            {
-                                dataValue = new DataValue( dElement, period, orgUnit, "" + resultValue, STORED_BY_DHIS_SYSTEM, new Date(),
-                                    null, optionCombo );
-                                dataValueService.addDataValue( dataValue );
-                            }
-
-                            // -----------------------------------------------------
-                            // Update dataValue
-                            // -----------------------------------------------------
-                            else if ( (double) resultValue != Double.parseDouble( dataValue.getValue() ) )
-                            {
-                                dataValue.setValue( "" + resultValue );
-                                dataValue.setTimestamp( new Date() );
-                                sql = "UPDATE datavalue" + " SET value='" + resultValue + "',lastupdated='"
-                                    + new Date() + "' where dataelementId=" + dataelementId + " and periodid="
-                                    + period.getId() + " and sourceid=" + orgUnit.getId()
-                                    + " and categoryoptioncomboid=" + optionComboId + " and storedby='"
-                                    + STORED_BY_DHIS_SYSTEM + "'";
-                                jdbcTemplate.execute( sql );
-                            }
-                        }
-
-                        // ---------------------------------------------------------
-                        // Delete dataValue
-                        // ---------------------------------------------------------
-                        else if ( dataValue != null )
-                        {
-                            dataValueService.deleteDataValue( dataValue );
-                        }
-                    }
-                }
-
-            }
-            clock.logTime( "Improrted aggregate data completed for data set " + datasetName );
-            notifier.notify( taskId, "Improrted aggregate data completed for data set "  + datasetName );            
+            CaseAggregateSchedule dataSet = new CaseAggregateSchedule( rsDataset.getInt( "datasetid" ),
+                rsDataset.getString( "datasetname" ), rsDataset.getString( "periodtypename" ) );
+            caseAggregateSchedule.add( dataSet );
         }
+
+        aggregationConditionService.aggregate( caseAggregateSchedule, taskStrategy );
+
+        clock.logTime( "Improrted aggregate data completed " );
+
         notifier.notify( taskId, INFO, "Improrted aggregate data completed", true );
     }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    private Collection<Period> getPeriod( 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) CalendarPeriodType.getPeriodTypeByName( periodTypeName );
-
-        return periodType.generatePeriods( startDate, endDate );
-    }
+    
 }

=== modified file 'dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml	2013-03-29 04:26:45 +0000
+++ dhis-2/dhis-services/dhis-service-patient/src/main/resources/META-INF/dhis/beans.xml	2013-04-01 05:56:41 +0000
@@ -12,6 +12,8 @@
 			value="org.hisp.dhis.caseaggregation.CaseAggregationCondition" />
 		<property name="sessionFactory" ref="sessionFactory" />
 		<property name="jdbcTemplate" ref="jdbcTemplate" />
+		<property name="programStageInstanceService" ref="org.hisp.dhis.program.ProgramStageInstanceService" />
+		<property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
 	</bean>
 
 	<bean id="org.hisp.dhis.relationship.RelationshipStore"
@@ -188,7 +190,6 @@
 			ref="org.hisp.dhis.patient.PatientAttributeService" />
 		<property name="programStageInstanceService"
 			ref="org.hisp.dhis.program.ProgramStageInstanceService" />
-		<property name="statementBuilder" ref="statementBuilder" />
 		<property name="i18nService" ref="org.hisp.dhis.i18n.I18nService" />
 	</bean>
 
@@ -482,12 +483,7 @@
 	<bean id="abstractRunCaseAggregateConditionTask"
 		class="org.hisp.dhis.patient.scheduling.CaseAggregateConditionTask">
 		<constructor-arg ref="org.hisp.dhis.caseaggregation.CaseAggregationConditionService" />
-		<constructor-arg ref="org.hisp.dhis.datavalue.DataValueService" />
-		<constructor-arg ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
-		<constructor-arg ref="org.hisp.dhis.program.ProgramStageInstanceService" />
 		<constructor-arg ref="jdbcTemplate" />
-		<constructor-arg ref="org.hisp.dhis.dataelement.DataElementService" />
-		<constructor-arg ref="org.hisp.dhis.dataelement.DataElementCategoryService" />
 		<constructor-arg ref="org.hisp.dhis.setting.SystemSettingManager" />
 		<constructor-arg ref="notifier" />
 	</bean>

=== modified file 'dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseaggregation/CaseAggregationResultAction.java'
--- dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseaggregation/CaseAggregationResultAction.java	2013-03-25 04:02:33 +0000
+++ dhis-2/dhis-web/dhis-web-caseentry/src/main/java/org/hisp/dhis/caseentry/action/caseaggregation/CaseAggregationResultAction.java	2013-04-01 05:56:41 +0000
@@ -210,7 +210,6 @@
     public String execute()
         throws Exception
     {
-
         // ---------------------------------------------------------------------
         // Get CaseAggregateCondition list
         // ---------------------------------------------------------------------
@@ -277,7 +276,7 @@
 
                 for ( Period period : periods )
                 {
-                    Integer resultValue = aggregationConditionService.parseConditition( condition, orgUnit, period );
+                    Double resultValue = aggregationConditionService.getAggregateValue( condition, orgUnit, period );
                     DataValue dataValue = dataValueService.getDataValue( orgUnit, dElement, period, optionCombo );
 
                     String key = orgUnitId + "-" + format.formatPeriod( period );