← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 3835: Applied patch from Tran. Adds an explicit set of CategoryOptionCombos to the Expression class whi...

 

------------------------------------------------------------
revno: 3835
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2011-06-03 15:11:34 +0200
message:
  Applied patch from Tran. Adds an explicit set of CategoryOptionCombos to the Expression class which gives us referential integrity for updates/deletes. Good work.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/Expression.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/ExpressionService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboDeletionHandler.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/expression/hibernate/Expression.hbm.xml
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionServiceTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionStoreTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleGroupStoreTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleServiceTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleStoreTest.java
  dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/dxf/converter/ValidationRuleConverter.java
  dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java
  dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java
  dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/AddValidationRuleAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/UpdateValidationRuleAction.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/expression/Expression.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/Expression.java	2011-05-05 21:14:56 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/Expression.java	2011-06-03 13:11:34 +0000
@@ -31,6 +31,7 @@
 import java.util.Set;
 
 import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 
 /**
  * An Expression is the expression of e.g. a validation rule. It consist of a
@@ -81,6 +82,11 @@
      */
     private Set<DataElement> dataElementsInExpression;
     
+    /**
+     * A reference to the optionCombos in the Expression.
+     */
+    private Set<DataElementCategoryOptionCombo> optionCombosInExpression;
+    
     // -------------------------------------------------------------------------
     // Constructors
     // -------------------------------------------------------------------------
@@ -98,11 +104,13 @@
      * @param description A description of the Expression.
      * @param dataElementsInExpression A reference to the DataElements in the Expression.
      */
-    public Expression( String expression, String description, Set<DataElement> dataElementsInExpression )
+    public Expression( String expression, String description, Set<DataElement> dataElementsInExpression,
+        Set<DataElementCategoryOptionCombo> optionCombosInExpression )
     {
         this.expression = expression;
         this.description = description;
         this.dataElementsInExpression = dataElementsInExpression;
+        this.optionCombosInExpression = optionCombosInExpression;
     }
 
     // -------------------------------------------------------------------------
@@ -184,6 +192,16 @@
         this.dataElementsInExpression = dataElementsInExpression;
     }
 
+    public Set<DataElementCategoryOptionCombo> getOptionCombosInExpression()
+    {
+        return optionCombosInExpression;
+    }
+
+    public void setOptionCombosInExpression( Set<DataElementCategoryOptionCombo> optionCombosInExpression )
+    {
+        this.optionCombosInExpression = optionCombosInExpression;
+    }
+
     public String getDescription()
     {
         return description;

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/ExpressionService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/ExpressionService.java	2011-05-20 16:00:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/ExpressionService.java	2011-06-03 13:11:34 +0000
@@ -32,6 +32,7 @@
 import java.util.Set;
 
 import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.dataelement.DataElementOperand;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.period.Period;
@@ -123,6 +124,8 @@
      */
     Set<DataElement> getDataElementsInExpression( String expression );
     
+    Set<DataElementCategoryOptionCombo> getOptionCombosInExpression( String expression );
+    
     /**
      * Returns all operands included in an expression string. The operand is on
      * the form <data element id>.<category option combo id>.

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboDeletionHandler.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboDeletionHandler.java	2011-01-07 11:38:55 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboDeletionHandler.java	2011-06-03 13:11:34 +0000
@@ -88,6 +88,10 @@
             String sql = "SELECT COUNT(*) FROM datavalue where categoryoptioncomboid=" + eachOptionCombo.getId();
             
             if( jdbcTemplate.queryForInt( sql ) > 0) return false;
+            
+            sql = "SELECT COUNT(*) FROM expressionoptioncombo where categoryoptioncomboid=" + eachOptionCombo.getId();
+            
+            if( jdbcTemplate.queryForInt( sql ) > 0) return false;
         }
         
         return true;

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java	2011-05-31 18:41:17 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java	2011-06-03 13:11:34 +0000
@@ -56,25 +56,28 @@
 import org.springframework.transaction.annotation.Transactional;
 
 /**
- * The expression is a string describing a formula containing data element ids and
- * category option combo ids. The formula can potentially contain references to
- * category totals (also called sub-totals) and data element totals (also called
- * totals).
+ * The expression is a string describing a formula containing data element ids
+ * and category option combo ids. The formula can potentially contain references
+ * to category totals (also called sub-totals) and data element totals (also
+ * called totals).
  * 
  * @author Margrethe Store
  * @author Lars Helge Overland
- * @version $Id: DefaultExpressionService.java 6463 2008-11-24 12:05:46Z larshelg $
+ * @version $Id: DefaultExpressionService.java 6463 2008-11-24 12:05:46Z
+ *          larshelg $
  */
 @Transactional
 public class DefaultExpressionService
     implements ExpressionService
 {
     private static final Log log = LogFactory.getLog( DefaultExpressionService.class );
-    
+
     private final Pattern FORMULA_PATTERN = Pattern.compile( FORMULA_EXPRESSION );
+
     private final Pattern OPERAND_PATTERN = Pattern.compile( OPERAND_EXPRESSION );
+
     private final String DAYS_DESCRIPTION = "[Number of days]";
-    
+
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
@@ -99,7 +102,7 @@
     {
         this.dataValueService = dataValueService;
     }
-    
+
     private AggregatedDataValueService aggregatedDataValueService;
 
     public void setAggregatedDataValueService( AggregatedDataValueService aggregatedDataValueService )
@@ -113,7 +116,7 @@
     {
         this.categoryService = categoryService;
     }
-    
+
     // -------------------------------------------------------------------------
     // Expression CRUD operations
     // -------------------------------------------------------------------------
@@ -147,13 +150,15 @@
     // Business logic
     // -------------------------------------------------------------------------
 
-    public Double getExpressionValue( Expression expression, Period period, OrganisationUnit source, boolean nullIfNoValues, boolean aggregate, Integer days )
+    public Double getExpressionValue( Expression expression, Period period, OrganisationUnit source,
+        boolean nullIfNoValues, boolean aggregate, Integer days )
     {
-        final String expressionString = generateExpression( expression.getExpression(), period, source, nullIfNoValues, aggregate, days );
+        final String expressionString = generateExpression( expression.getExpression(), period, source, nullIfNoValues,
+            aggregate, days );
 
         return expressionString != null ? calculateExpression( expressionString ) : null;
-    }    
-    
+    }
+
     public Set<DataElement> getDataElementsInExpression( String expression )
     {
         Set<DataElement> dataElementsInExpression = null;
@@ -163,10 +168,11 @@
             dataElementsInExpression = new HashSet<DataElement>();
 
             final Matcher matcher = OPERAND_PATTERN.matcher( expression );
-            
+
             while ( matcher.find() )
             {
-                final DataElement dataElement = dataElementService.getDataElement( DataElementOperand.getOperand( matcher.group() ).getDataElementId() );
+                final DataElement dataElement = dataElementService.getDataElement( DataElementOperand.getOperand(
+                    matcher.group() ).getDataElementId() );
 
                 if ( dataElement != null )
                 {
@@ -177,11 +183,37 @@
 
         return dataElementsInExpression;
     }
+
+    public Set<DataElementCategoryOptionCombo> getOptionCombosInExpression( String expression )
+    {
+        Set<DataElementCategoryOptionCombo> optionCombosInExpression = null;
+
+        if ( expression != null )
+        {
+            optionCombosInExpression = new HashSet<DataElementCategoryOptionCombo>();
+
+            final Matcher matcher = OPERAND_PATTERN.matcher( expression );
+
+            while ( matcher.find() )
+            {
+                DataElementCategoryOptionCombo categoryOptionCombo = categoryService.getDataElementCategoryOptionCombo( 
+                    DataElementOperand.getOperand( matcher.group() ).getOptionComboId() );
+
+                if ( categoryOptionCombo != null )
+                {
+                    optionCombosInExpression.add( categoryOptionCombo );
+                }
+            }
+        }
+
+        return optionCombosInExpression;
+    }
     
-    public String convertExpression( String expression, Map<Object, Integer> dataElementMapping, Map<Object, Integer> categoryOptionComboMapping )
+    public String convertExpression( String expression, Map<Object, Integer> dataElementMapping,
+        Map<Object, Integer> categoryOptionComboMapping )
     {
         final StringBuffer convertedFormula = new StringBuffer();
-        
+
         if ( expression != null )
         {
             final Matcher matcher = OPERAND_PATTERN.matcher( expression );
@@ -189,35 +221,36 @@
             while ( matcher.find() )
             {
                 String match = matcher.group();
-                
+
                 final DataElementOperand operand = DataElementOperand.getOperand( match );
-                
+
                 final Integer mappedDataElementId = dataElementMapping.get( operand.getDataElementId() );
                 final Integer mappedCategoryOptionComboId = categoryOptionComboMapping.get( operand.getOptionComboId() );
-                
+
                 if ( mappedDataElementId == null )
                 {
                     log.info( "Data element identifier refers to non-existing object: " + operand.getDataElementId() );
-                    
+
                     match = NULL_REPLACEMENT;
                 }
                 else if ( !operand.isTotal() && mappedCategoryOptionComboId == null )
                 {
-                    log.info( "Category option combo identifer refers to non-existing object: " + operand.getOptionComboId() );
-                    
+                    log.info( "Category option combo identifer refers to non-existing object: "
+                        + operand.getOptionComboId() );
+
                     match = NULL_REPLACEMENT;
                 }
                 else
                 {
                     match = EXP_OPEN + mappedDataElementId + SEPARATOR + mappedCategoryOptionComboId + EXP_CLOSE;
                 }
-                
+
                 matcher.appendReplacement( convertedFormula, match );
             }
 
             matcher.appendTail( convertedFormula );
         }
-        
+
         return convertedFormula.toString();
     }
 
@@ -239,24 +272,24 @@
 
         return operandsInExpression;
     }
-    
+
     public String expressionIsValid( String formula )
     {
         if ( formula == null )
         {
             return EXPRESSION_IS_EMPTY;
         }
-        
+
         final StringBuffer buffer = new StringBuffer();
-        
+
         final Matcher matcher = FORMULA_PATTERN.matcher( formula );
 
         while ( matcher.find() )
         {
             DataElementOperand operand = null;
-            
+
             final String match = matcher.group();
-            
+
             if ( !DAYS_EXPRESSION.equals( match ) )
             {
                 try
@@ -267,32 +300,32 @@
                 {
                     return ID_NOT_NUMERIC;
                 }
-    
-                if ( !dataElementService.dataElementExists( operand.getDataElementId()  ) )
+
+                if ( !dataElementService.dataElementExists( operand.getDataElementId() ) )
                 {
                     return DATAELEMENT_DOES_NOT_EXIST;
                 }
-    
+
                 if ( !operand.isTotal() && !dataElementService.dataElementCategoryOptionComboExists( operand.getOptionComboId() ) )
                 {
                     return CATEGORYOPTIONCOMBO_DOES_NOT_EXIST;
                 }
             }
-            
+
             // -----------------------------------------------------------------
-            // Replacing the operand with 1.1 in order to later be able to verify
-            // that the formula is mathematically valid
+            // Replacing the operand with 1.1 in order to later be able to
+            // verify that the formula is mathematically valid
             // -----------------------------------------------------------------
 
             matcher.appendReplacement( buffer, "1.1" );
         }
-        
+
         matcher.appendTail( buffer );
-        
+
         if ( MathUtils.expressionHasErrors( buffer.toString() ) )
         {
             return EXPRESSION_NOT_WELL_FORMED;
-        }        
+        }
 
         return VALID;
     }
@@ -310,7 +343,7 @@
             while ( matcher.find() )
             {
                 String match = matcher.group();
-                
+
                 if ( DAYS_EXPRESSION.equals( match ) )
                 {
                     match = DAYS_DESCRIPTION;
@@ -318,26 +351,26 @@
                 else
                 {
                     final DataElementOperand operand = DataElementOperand.getOperand( match );
-                    
+
                     final DataElement dataElement = dataElementService.getDataElement( operand.getDataElementId() );
-                    final DataElementCategoryOptionCombo categoryOptionCombo = 
-                        categoryService.getDataElementCategoryOptionCombo( operand.getOptionComboId() );
-    
+                    final DataElementCategoryOptionCombo categoryOptionCombo = categoryService
+                        .getDataElementCategoryOptionCombo( operand.getOptionComboId() );
+
                     if ( dataElement == null )
                     {
                         throw new IllegalArgumentException( "Identifier does not reference a data element: "
                             + operand.getDataElementId() );
                     }
-    
+
                     if ( !operand.isTotal() && categoryOptionCombo == null )
                     {
                         throw new IllegalArgumentException( "Identifier does not reference a category option combo: "
                             + operand.getOptionComboId() );
                     }
-    
+
                     match = DataElementOperand.getPrettyName( dataElement, categoryOptionCombo );
                 }
-                
+
                 matcher.appendReplacement( buffer, match );
             }
 
@@ -350,13 +383,13 @@
     public String explodeExpression( String expression )
     {
         StringBuffer buffer = null;
-        
+
         if ( expression != null )
         {
             final Matcher matcher = OPERAND_PATTERN.matcher( expression );
-            
+
             buffer = new StringBuffer();
-            
+
             while ( matcher.find() )
             {
                 final DataElementOperand operand = DataElementOperand.getOperand( matcher.group() );
@@ -364,38 +397,40 @@
                 if ( operand.isTotal() )
                 {
                     final StringBuilder replace = new StringBuilder();
-                    
+
                     final DataElement dataElement = dataElementService.getDataElement( operand.getDataElementId() );
-                    
+
                     final DataElementCategoryCombo categoryCombo = dataElement.getCategoryCombo();
-                    
+
                     for ( DataElementCategoryOptionCombo categoryOptionCombo : categoryCombo.getOptionCombos() )
                     {
-                        replace.append( EXP_OPEN ).append( dataElement.getId() ).append( SEPARATOR ).append( categoryOptionCombo.getId() ).append( EXP_CLOSE ).append( "+" );
+                        replace.append( EXP_OPEN ).append( dataElement.getId() ).append( SEPARATOR ).append(
+                            categoryOptionCombo.getId() ).append( EXP_CLOSE ).append( "+" );
                     }
-                    
+
                     replace.deleteCharAt( replace.length() - 1 );
-                    
+
                     matcher.appendReplacement( buffer, replace.toString() );
                 }
             }
-            
+
             matcher.appendTail( buffer );
         }
-        
+
         return buffer != null ? buffer.toString() : null;
     }
-    
-    public String generateExpression( String expression, Period period, OrganisationUnit source, boolean nullIfNoValues, boolean aggregated, Integer days )
+
+    public String generateExpression( String expression, Period period, OrganisationUnit source,
+        boolean nullIfNoValues, boolean aggregated, Integer days )
     {
         StringBuffer buffer = null;
-        
+
         if ( expression != null )
         {
             buffer = new StringBuffer();
 
             final Matcher matcher = FORMULA_PATTERN.matcher( expression );
-            
+
             while ( matcher.find() )
             {
                 String match = matcher.group();
@@ -407,28 +442,30 @@
                 else // Operand
                 {
                     final DataElementOperand operand = DataElementOperand.getOperand( match );
-                    
+
                     String value = null;
-                  
+
                     if ( aggregated )
                     {
-                        final Double aggregatedValue = aggregatedDataValueService.getAggregatedDataValue( operand.getDataElementId(), operand.getOptionComboId(), period.getId(), source.getId() );
-    
+                        final Double aggregatedValue = aggregatedDataValueService.getAggregatedDataValue( operand
+                            .getDataElementId(), operand.getOptionComboId(), period.getId(), source.getId() );
+
                         value = aggregatedValue != null ? String.valueOf( aggregatedValue ) : null;
                     }
                     else
                     {
-                        value = dataValueService.getValue( operand.getDataElementId(), period.getId(), source.getId(), operand.getOptionComboId() );
+                        value = dataValueService.getValue( operand.getDataElementId(), period.getId(), source.getId(),
+                            operand.getOptionComboId() );
                     }
-                    
+
                     if ( value == null && nullIfNoValues )
                     {
                         return null;
                     }
-                    
-                    match = ( value == null ) ? NULL_REPLACEMENT : value;
+
+                    match = (value == null) ? NULL_REPLACEMENT : value;
                 }
-                
+
                 matcher.appendReplacement( buffer, match );
             }
 
@@ -437,21 +474,21 @@
 
         return buffer != null ? buffer.toString() : null;
     }
-    
+
     public String generateExpression( String expression, Map<DataElementOperand, Double> valueMap, Integer days )
-    {   
+    {
         StringBuffer buffer = null;
-        
+
         if ( expression != null )
         {
             final Matcher matcher = FORMULA_PATTERN.matcher( expression );
-            
-            buffer = new StringBuffer();            
-            
+
+            buffer = new StringBuffer();
+
             while ( matcher.find() )
             {
                 String match = matcher.group();
-                
+
                 if ( DAYS_EXPRESSION.equals( match ) ) // Days
                 {
                     match = days != null ? String.valueOf( days ) : NULL_REPLACEMENT;
@@ -459,18 +496,18 @@
                 else // Operand
                 {
                     final DataElementOperand operand = DataElementOperand.getOperand( match );
-                    
+
                     final Double aggregatedValue = valueMap.get( operand );
-                    
-                    match = ( aggregatedValue == null ) ? NULL_REPLACEMENT : String.valueOf( aggregatedValue );
+
+                    match = (aggregatedValue == null) ? NULL_REPLACEMENT : String.valueOf( aggregatedValue );
                 }
-                
+
                 matcher.appendReplacement( buffer, match );
             }
-    
+
             matcher.appendTail( buffer );
         }
-        
+
         return buffer != null ? buffer.toString() : null;
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/expression/hibernate/Expression.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/expression/hibernate/Expression.hbm.xml	2011-05-28 21:25:46 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/expression/hibernate/Expression.hbm.xml	2011-06-03 13:11:34 +0000
@@ -21,6 +21,12 @@
       <key column="expressionid" foreign-key="fk_expressiondataelement_expressionid" />
       <many-to-many class="org.hisp.dhis.dataelement.DataElement" column="dataelementid" foreign-key="fk_expression_dataelementid" />
     </set>
+    
+    <set name="optionCombosInExpression" table="expressionoptioncombo">
+      <key column="expressionid" foreign-key="fk_expressionoptioncombo_expressionid"/>
+      <many-to-many class="org.hisp.dhis.dataelement.DataElementCategoryOptionCombo" 
+          column="categoryoptioncomboid" foreign-key="fk_expression_categoryoptioncomboid"/>
+   </set>
 
   </class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionServiceTest.java	2011-05-20 16:00:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionServiceTest.java	2011-06-03 13:11:34 +0000
@@ -63,45 +63,63 @@
     extends DhisTest
 {
     private DataElementCategoryOption categoryOptionA;
+
     private DataElementCategoryOption categoryOptionB;
+
     private DataElementCategoryOption categoryOptionC;
+
     private DataElementCategoryOption categoryOptionD;
-    
+
     private DataElementCategory categoryA;
+
     private DataElementCategory categoryB;
-    
+
     private DataElementCategoryCombo categoryCombo;
-    
+
     private DataElement dataElementA;
+
     private DataElement dataElementB;
+
     private DataElement dataElementC;
+
     private DataElement dataElementD;
+
     private DataElement dataElementE;
-    
+
     private Period period;
-    
+
     private OrganisationUnit source;
-    
+
     private int dataElementIdA;
+
     private int dataElementIdB;
+
     private int dataElementIdC;
+
     private int dataElementIdD;
+
     private int dataElementIdE;
 
     private DataElementCategoryOptionCombo categoryOptionCombo;
-    
+
     private int categoryOptionComboId;
-    
+
     private String expressionA;
+
     private String expressionB;
+
     private String expressionC;
+
     private String expressionD;
-    
+
     private String descriptionA;
+
     private String descriptionB;
-    
+
     private Set<DataElement> dataElements = new HashSet<DataElement>();
-    
+
+    private Set<DataElementCategoryOptionCombo> optionCombos = new HashSet<DataElementCategoryOptionCombo>();
+
     // -------------------------------------------------------------------------
     // Fixture
     // -------------------------------------------------------------------------
@@ -111,72 +129,75 @@
         throws Exception
     {
         expressionService = (ExpressionService) getBean( ExpressionService.ID );
-        
+
         dataElementService = (DataElementService) getBean( DataElementService.ID );
 
         categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID );
-        
+
         dataValueService = (DataValueService) getBean( DataValueService.ID );
-        
+
         organisationUnitService = (OrganisationUnitService) getBean( OrganisationUnitService.ID );
-        
+
         categoryOptionA = new DataElementCategoryOption( "Under 5" );
         categoryOptionB = new DataElementCategoryOption( "Over 5" );
         categoryOptionC = new DataElementCategoryOption( "Male" );
         categoryOptionD = new DataElementCategoryOption( "Female" );
-        
+
         categoryService.addDataElementCategoryOption( categoryOptionA );
         categoryService.addDataElementCategoryOption( categoryOptionB );
         categoryService.addDataElementCategoryOption( categoryOptionC );
         categoryService.addDataElementCategoryOption( categoryOptionD );
-                
+
         categoryA = new DataElementCategory( "Age" );
         categoryB = new DataElementCategory( "Gender" );
-        
+
         categoryA.getCategoryOptions().add( categoryOptionA );
         categoryA.getCategoryOptions().add( categoryOptionB );
         categoryB.getCategoryOptions().add( categoryOptionC );
         categoryB.getCategoryOptions().add( categoryOptionD );
-        
+
         categoryService.addDataElementCategory( categoryA );
         categoryService.addDataElementCategory( categoryB );
-                
+
         categoryCombo = new DataElementCategoryCombo( "Age and gender" );
         categoryCombo.getCategories().add( categoryA );
         categoryCombo.getCategories().add( categoryB );
-        
+
         categoryService.addDataElementCategoryCombo( categoryCombo );
-        
+
         dataElementA = createDataElement( 'A' );
         dataElementB = createDataElement( 'B' );
         dataElementC = createDataElement( 'C' );
-        dataElementD = createDataElement( 'D' );  
-        dataElementE = createDataElement( 'E', categoryCombo );        
-        
+        dataElementD = createDataElement( 'D' );
+        dataElementE = createDataElement( 'E', categoryCombo );
+
         dataElementIdA = dataElementService.addDataElement( dataElementA );
         dataElementIdB = dataElementService.addDataElement( dataElementB );
         dataElementIdC = dataElementService.addDataElement( dataElementC );
         dataElementIdD = dataElementService.addDataElement( dataElementD );
         dataElementIdE = dataElementService.addDataElement( dataElementE );
-        
+
         categoryOptionCombo = categoryService.getDefaultDataElementCategoryOptionCombo();
-        
+
         categoryOptionComboId = categoryOptionCombo.getId();
-        
+        optionCombos.add( categoryOptionCombo );
+
         period = createPeriod( getDate( 2000, 1, 1 ), getDate( 2000, 2, 1 ) );
-        
+
         source = createOrganisationUnit( 'A' );
-        
+
         organisationUnitService.addOrganisationUnit( source );
-        
-        expressionA = "[" + dataElementIdA + SEPARATOR + categoryOptionComboId + "]+[" + dataElementIdB + SEPARATOR + categoryOptionComboId + "]";
-        expressionB = "[" + dataElementIdC + SEPARATOR + categoryOptionComboId + "]-[" + dataElementIdD + SEPARATOR + categoryOptionComboId + "]";
+
+        expressionA = "[" + dataElementIdA + SEPARATOR + categoryOptionComboId + "]+[" + dataElementIdB + SEPARATOR
+            + categoryOptionComboId + "]";
+        expressionB = "[" + dataElementIdC + SEPARATOR + categoryOptionComboId + "]-[" + dataElementIdD + SEPARATOR
+            + categoryOptionComboId + "]";
         expressionC = "[" + dataElementIdA + SEPARATOR + categoryOptionComboId + "]+[" + dataElementIdE + "]-10";
         expressionD = "[" + dataElementIdA + SEPARATOR + categoryOptionComboId + "]+" + DAYS_EXPRESSION;
-        
+
         descriptionA = "Expression A";
         descriptionB = "Expression B";
-                
+
         dataElements.add( dataElementA );
         dataElements.add( dataElementB );
         dataElements.add( dataElementC );
@@ -184,9 +205,9 @@
         dataElements.add( dataElementE );
 
         dataValueService.addDataValue( createDataValue( dataElementA, period, source, "10", categoryOptionCombo ) );
-        dataValueService.addDataValue( createDataValue( dataElementB, period, source, "5", categoryOptionCombo ) );        
+        dataValueService.addDataValue( createDataValue( dataElementB, period, source, "5", categoryOptionCombo ) );
     }
-    
+
     @Override
     public boolean emptyDatabaseAfterTest()
     {
@@ -201,13 +222,13 @@
     public void testExplodeExpressionA()
     {
         categoryService.generateOptionCombos( categoryCombo );
-        
+
         String actual = expressionService.explodeExpression( expressionC );
-        
+
         Set<DataElementCategoryOptionCombo> categoryOptionCombos = categoryCombo.getOptionCombos();
-        
+
         assertTrue( actual.contains( "[" + dataElementIdA + SEPARATOR + categoryOptionComboId + "]" ) );
-        
+
         for ( DataElementCategoryOptionCombo categoryOptionCombo : categoryOptionCombos )
         {
             assertTrue( actual.contains( "[" + dataElementIdE + SEPARATOR + categoryOptionCombo.getId() + "]" ) );
@@ -224,16 +245,16 @@
     @Test
     public void testGetExpressionValue()
     {
-        Expression expression = new Expression( expressionA, descriptionA, dataElements );
-        
+        Expression expression = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+
         Double value = expressionService.getExpressionValue( expression, period, source, false, false, null );
-        
+
         assertEquals( value, 15.0 );
-        
-        expression = new Expression( expressionB, descriptionB, dataElements );
+
+        expression = new Expression( expressionB, descriptionB, dataElements, optionCombos );
 
         value = expressionService.getExpressionValue( expression, period, source, false, false, null );
-        
+
         assertEquals( 0.0, value );
     }
 
@@ -241,23 +262,23 @@
     public void testGetDataElementsInExpression()
     {
         Set<DataElement> dataElements = expressionService.getDataElementsInExpression( expressionA );
-        
+
         assertTrue( dataElements.size() == 2 );
         assertTrue( dataElements.contains( dataElementA ) );
-        assertTrue( dataElements.contains( dataElementB ) );        
+        assertTrue( dataElements.contains( dataElementB ) );
     }
 
     @Test
     public void testGetOperandsInExpression()
     {
         Set<DataElementOperand> operands = expressionService.getOperandsInExpression( expressionA );
-        
+
         assertNotNull( operands );
         assertEquals( 2, operands.size() );
-        
+
         DataElementOperand operandA = new DataElementOperand( dataElementIdA, categoryOptionComboId );
         DataElementOperand operandB = new DataElementOperand( dataElementIdB, categoryOptionComboId );
-        
+
         assertTrue( operands.contains( operandA ) );
         assertTrue( operands.contains( operandB ) );
     }
@@ -268,49 +289,51 @@
         Map<Object, Integer> dataElementMapping = new HashMap<Object, Integer>();
         dataElementMapping.put( 1, 4 );
         dataElementMapping.put( 2, 5 );
-        
+
         Map<Object, Integer> categoryOptionComboMapping = new HashMap<Object, Integer>();
         categoryOptionComboMapping.put( 1, 6 );
-        categoryOptionComboMapping.put( 2, 7);
-        
+        categoryOptionComboMapping.put( 2, 7 );
+
         String expression = "[1.1]+2+[2.2]";
         String expected = "[4.6]+2+[5.7]";
-        
-        assertEquals( expected, expressionService.convertExpression( expression, dataElementMapping, categoryOptionComboMapping ) );
+
+        assertEquals( expected, expressionService.convertExpression( expression, dataElementMapping,
+            categoryOptionComboMapping ) );
     }
 
     @Test
     public void testExpressionIsValid()
     {
-    	assertEquals( ExpressionService.VALID, expressionService.expressionIsValid( expressionA ) );
-    	assertEquals( ExpressionService.VALID, expressionService.expressionIsValid( expressionB ) );
-    	
-    	expressionA = "[" + dataElementIdA + SEPARATOR + "foo" + "] + 12";
-    	
-    	assertEquals( ExpressionService.ID_NOT_NUMERIC, expressionService.expressionIsValid( expressionA ) );
-    	
-    	expressionA = "[" + 999 + SEPARATOR + categoryOptionComboId + "] + 12";
-    	
-    	assertEquals( ExpressionService.DATAELEMENT_DOES_NOT_EXIST, expressionService.expressionIsValid( expressionA ) );
-    	
-    	expressionA = "[" + dataElementIdA + SEPARATOR + 999 + "] + 12";
-    	
-    	assertEquals( ExpressionService.CATEGORYOPTIONCOMBO_DOES_NOT_EXIST, expressionService.expressionIsValid( expressionA ) );
-        
+        assertEquals( ExpressionService.VALID, expressionService.expressionIsValid( expressionA ) );
+        assertEquals( ExpressionService.VALID, expressionService.expressionIsValid( expressionB ) );
+
+        expressionA = "[" + dataElementIdA + SEPARATOR + "foo" + "] + 12";
+
+        assertEquals( ExpressionService.ID_NOT_NUMERIC, expressionService.expressionIsValid( expressionA ) );
+
+        expressionA = "[" + 999 + SEPARATOR + categoryOptionComboId + "] + 12";
+
+        assertEquals( ExpressionService.DATAELEMENT_DOES_NOT_EXIST, expressionService.expressionIsValid( expressionA ) );
+
+        expressionA = "[" + dataElementIdA + SEPARATOR + 999 + "] + 12";
+
+        assertEquals( ExpressionService.CATEGORYOPTIONCOMBO_DOES_NOT_EXIST, expressionService
+            .expressionIsValid( expressionA ) );
+
         expressionA = "[" + dataElementIdA + SEPARATOR + categoryOptionComboId + "] + ( 12";
-        
-        assertEquals( ExpressionService.EXPRESSION_NOT_WELL_FORMED, expressionService.expressionIsValid( expressionA ) );
-        
-        expressionA = "12 x 4";        
-
-        assertEquals( ExpressionService.EXPRESSION_NOT_WELL_FORMED, expressionService.expressionIsValid( expressionA ) );        
+
+        assertEquals( ExpressionService.EXPRESSION_NOT_WELL_FORMED, expressionService.expressionIsValid( expressionA ) );
+
+        expressionA = "12 x 4";
+
+        assertEquals( ExpressionService.EXPRESSION_NOT_WELL_FORMED, expressionService.expressionIsValid( expressionA ) );
     }
 
     @Test
     public void testGetExpressionDescription()
     {
-        String description = expressionService.getExpressionDescription( expressionA );        
-        
+        String description = expressionService.getExpressionDescription( expressionA );
+
         assertEquals( "DataElementA+DataElementB", description );
     }
 
@@ -321,18 +344,18 @@
         assertEquals( "0-0", expressionService.generateExpression( expressionB, period, source, false, false, null ) );
         assertEquals( "10+7", expressionService.generateExpression( expressionD, period, source, false, false, 7 ) );
     }
-    
+
     @Test
     public void testGenerateExpressionMap()
     {
         Map<DataElementOperand, Double> valueMap = new HashMap<DataElementOperand, Double>();
         valueMap.put( new DataElementOperand( dataElementIdA, categoryOptionComboId ), new Double( 12 ) );
         valueMap.put( new DataElementOperand( dataElementIdB, categoryOptionComboId ), new Double( 34 ) );
-        
-        assertEquals( "12.0+34.0", expressionService.generateExpression( expressionA, valueMap, null ) );        
+
+        assertEquals( "12.0+34.0", expressionService.generateExpression( expressionA, valueMap, null ) );
         assertEquals( "12.0+5", expressionService.generateExpression( expressionD, valueMap, 5 ) );
     }
-    
+
     // -------------------------------------------------------------------------
     // CRUD tests
     // -------------------------------------------------------------------------
@@ -340,12 +363,12 @@
     @Test
     public void testAddGetExpression()
     {
-        Expression expression = new Expression( expressionA, descriptionA, dataElements );
-        
+        Expression expression = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+
         int id = expressionService.addExpression( expression );
-        
+
         expression = expressionService.getExpression( id );
-        
+
         assertEquals( expressionA, expression.getExpression() );
         assertEquals( descriptionA, expression.getDescription() );
         assertEquals( dataElements, expression.getDataElementsInExpression() );
@@ -354,22 +377,22 @@
     @Test
     public void testUpdateExpression()
     {
-        Expression expression = new Expression( expressionA, descriptionA, dataElements );
-        
+        Expression expression = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+
         int id = expressionService.addExpression( expression );
-        
+
         expression = expressionService.getExpression( id );
-        
+
         assertEquals( expressionA, expression.getExpression() );
         assertEquals( descriptionA, expression.getDescription() );
-        
+
         expression.setExpression( expressionB );
         expression.setDescription( descriptionB );
 
         expressionService.updateExpression( expression );
 
         expression = expressionService.getExpression( id );
-        
+
         assertEquals( expressionB, expression.getExpression() );
         assertEquals( descriptionB, expression.getDescription() );
     }
@@ -377,15 +400,15 @@
     @Test
     public void testDeleteExpression()
     {
-        Expression exprA = new Expression( expressionA, descriptionA, dataElements );
-        Expression exprB = new Expression( expressionB, descriptionB, dataElements );
-        
+        Expression exprA = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+        Expression exprB = new Expression( expressionB, descriptionB, dataElements, optionCombos );
+
         int idA = expressionService.addExpression( exprA );
         int idB = expressionService.addExpression( exprB );
-        
+
         assertNotNull( expressionService.getExpression( idA ) );
         assertNotNull( expressionService.getExpression( idB ) );
-        
+
         expressionService.deleteExpression( exprA );
 
         assertNull( expressionService.getExpression( idA ) );
@@ -400,14 +423,14 @@
     @Test
     public void testGetAllExpressions()
     {
-        Expression exprA = new Expression( expressionA, descriptionA, dataElements );
-        Expression exprB = new Expression( expressionB, descriptionB, dataElements );
-        
+        Expression exprA = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+        Expression exprB = new Expression( expressionB, descriptionB, dataElements, optionCombos );
+
         expressionService.addExpression( exprA );
         expressionService.addExpression( exprB );
-        
+
         Collection<Expression> expressions = expressionService.getAllExpressions();
-                
+
         assertTrue( expressions.size() == 2 );
         assertTrue( expressions.contains( exprA ) );
         assertTrue( expressions.contains( exprB ) );

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionStoreTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionStoreTest.java	2010-04-12 21:23:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/expression/ExpressionStoreTest.java	2011-06-03 13:11:34 +0000
@@ -39,6 +39,9 @@
 import org.hisp.dhis.DhisTest;
 import org.hisp.dhis.common.GenericStore;
 import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
 import org.hisp.dhis.dataelement.DataElementService;
 import org.junit.Test;
 
@@ -51,20 +54,27 @@
     extends DhisTest
 {
     private GenericStore<Expression> expressionStore;
-    
-    private int dataElementIdA;    
-    private int dataElementIdB;    
-    private int dataElementIdC;    
+
+    private int dataElementIdA;
+
+    private int dataElementIdB;
+
+    private int dataElementIdC;
+
     private int dataElementIdD;
-    
+
     private String expressionA;
+
     private String expressionB;
-    
+
     private String descriptionA;
+
     private String descriptionB;
-    
+
     private Set<DataElement> dataElements = new HashSet<DataElement>();
-    
+
+    private Set<DataElementCategoryOptionCombo> optionCombos;
+
     // -------------------------------------------------------------------------
     // Fixture
     // -------------------------------------------------------------------------
@@ -74,25 +84,32 @@
         throws Exception
     {
         expressionStore = (GenericStore<Expression>) getBean( "org.hisp.dhis.expression.ExpressionStore" );
-        
         dataElementService = (DataElementService) getBean( DataElementService.ID );
-        
+        categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID );
+
         DataElement dataElementA = createDataElement( 'A' );
         DataElement dataElementB = createDataElement( 'B' );
         DataElement dataElementC = createDataElement( 'C' );
-        DataElement dataElementD = createDataElement( 'D' );        
-        
+        DataElement dataElementD = createDataElement( 'D' );
+
         dataElementIdA = dataElementService.addDataElement( dataElementA );
         dataElementIdB = dataElementService.addDataElement( dataElementB );
         dataElementIdC = dataElementService.addDataElement( dataElementC );
         dataElementIdD = dataElementService.addDataElement( dataElementD );
-        
+
+        DataElementCategoryCombo categoryCombo = categoryService
+            .getDataElementCategoryComboByName( DataElementCategoryCombo.DEFAULT_CATEGORY_COMBO_NAME );
+        DataElementCategoryOptionCombo categoryOptionCombo = categoryCombo.getOptionCombos().iterator().next();
+
+        optionCombos = new HashSet<DataElementCategoryOptionCombo>();
+        optionCombos.add( categoryOptionCombo );
+
         expressionA = "[" + dataElementIdA + "] + [" + dataElementIdB + "]";
         expressionB = "[" + dataElementIdC + "] - [" + dataElementIdD + "]";
-        
+
         descriptionA = "Expression A";
         descriptionB = "Expression B";
-                
+
         dataElements.add( dataElementA );
         dataElements.add( dataElementB );
         dataElements.add( dataElementC );
@@ -108,16 +125,16 @@
     // -------------------------------------------------------------------------
     // Tests
     // -------------------------------------------------------------------------
-    
+
     @Test
     public void testAddGetExpression()
     {
-        Expression expr = new Expression( expressionA, descriptionA, dataElements );
-        
+        Expression expr = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+
         int id = expressionStore.save( expr );
-        
+
         expr = expressionStore.get( id );
-        
+
         assertEquals( expr.getExpression(), expressionA );
         assertEquals( expr.getDescription(), descriptionA );
         assertEquals( expr.getDataElementsInExpression(), dataElements );
@@ -126,22 +143,22 @@
     @Test
     public void testUpdateExpression()
     {
-        Expression expr = new Expression( expressionA, descriptionA, dataElements );
-        
+        Expression expr = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+
         int id = expressionStore.save( expr );
-        
+
         expr = expressionStore.get( id );
-        
+
         assertEquals( expr.getExpression(), expressionA );
         assertEquals( expr.getDescription(), descriptionA );
-        
+
         expr.setExpression( expressionB );
         expr.setDescription( descriptionB );
 
         expressionStore.update( expr );
 
         expr = expressionStore.get( id );
-        
+
         assertEquals( expr.getExpression(), expressionB );
         assertEquals( expr.getDescription(), descriptionB );
     }
@@ -149,15 +166,15 @@
     @Test
     public void testDeleteExpression()
     {
-        Expression exprA = new Expression( expressionA, descriptionA, dataElements );
-        Expression exprB = new Expression( expressionB, descriptionB, dataElements );
-        
+        Expression exprA = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+        Expression exprB = new Expression( expressionB, descriptionB, dataElements, optionCombos );
+
         int idA = expressionStore.save( exprA );
         int idB = expressionStore.save( exprB );
-        
+
         assertNotNull( expressionStore.get( idA ) );
         assertNotNull( expressionStore.get( idB ) );
-        
+
         expressionStore.delete( exprA );
 
         assertNull( expressionStore.get( idA ) );
@@ -172,14 +189,14 @@
     @Test
     public void testGetAllExpressions()
     {
-        Expression exprA = new Expression( expressionA, descriptionA, dataElements );
-        Expression exprB = new Expression( expressionB, descriptionB, dataElements );
-        
+        Expression exprA = new Expression( expressionA, descriptionA, dataElements, optionCombos );
+        Expression exprB = new Expression( expressionB, descriptionB, dataElements, optionCombos );
+
         expressionStore.save( exprA );
         expressionStore.save( exprB );
-        
+
         Collection<Expression> expressions = expressionStore.getAll();
-                
+
         assertTrue( expressions.size() == 2 );
         assertTrue( expressions.contains( exprA ) );
         assertTrue( expressions.contains( exprB ) );

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleGroupStoreTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleGroupStoreTest.java	2010-12-29 10:06:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleGroupStoreTest.java	2011-06-03 13:11:34 +0000
@@ -31,8 +31,7 @@
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
-
-import static org.hisp.dhis.expression.Operator.*;
+import static org.hisp.dhis.expression.Operator.equal_to;
 
 import java.util.Collection;
 import java.util.HashSet;
@@ -41,6 +40,9 @@
 import org.hisp.dhis.DhisSpringTest;
 import org.hisp.dhis.common.GenericIdentifiableObjectStore;
 import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
 import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.expression.Expression;
 import org.hisp.dhis.expression.ExpressionService;
@@ -49,30 +51,37 @@
 
 /**
  * @author Lars Helge Overland
- * @version $Id: ValidationRuleStoreTest.java 3679 2007-10-22 18:25:18Z larshelg $
+ * @version $Id: ValidationRuleStoreTest.java 3679 2007-10-22 18:25:18Z larshelg
+ *          $
  */
 @SuppressWarnings( "unchecked" )
 public class ValidationRuleGroupStoreTest
     extends DhisSpringTest
 {
     private GenericIdentifiableObjectStore<ValidationRule> validationRuleStore;
-    
+
     private GenericIdentifiableObjectStore<ValidationRuleGroup> validationRuleGroupStore;
 
     private ExpressionService expressionService;
-    
+
     private DataElement dataElementA;
+
     private DataElement dataElementB;
+
     private DataElement dataElementC;
+
     private DataElement dataElementD;
 
     private Set<DataElement> dataElements;
 
+    private Set<DataElementCategoryOptionCombo> optionCombos;
+
     private Expression expressionA;
+
     private Expression expressionB;
 
     private PeriodType periodType;
-    
+
     // -------------------------------------------------------------------------
     // Fixture
     // -------------------------------------------------------------------------
@@ -80,24 +89,26 @@
     @Override
     public void setUpTest()
         throws Exception
-    {       
+    {
         validationRuleStore = (GenericIdentifiableObjectStore<ValidationRule>) getBean( "org.hisp.dhis.validation.ValidationRuleStore" );
-        
+
         validationRuleGroupStore = (GenericIdentifiableObjectStore<ValidationRuleGroup>) getBean( "org.hisp.dhis.validation.ValidationRuleGroupStore" );
 
         dataElementService = (DataElementService) getBean( DataElementService.ID );
-        
-        expressionService = (ExpressionService) getBean ( ExpressionService.ID );
-        
+
+        categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID );
+
+        expressionService = (ExpressionService) getBean( ExpressionService.ID );
+
         dataElementA = createDataElement( 'A' );
         dataElementB = createDataElement( 'B' );
         dataElementC = createDataElement( 'C' );
         dataElementD = createDataElement( 'D' );
-        
+
         dataElementService.addDataElement( dataElementA );
         dataElementService.addDataElement( dataElementB );
         dataElementService.addDataElement( dataElementC );
-        dataElementService.addDataElement( dataElementD );        
+        dataElementService.addDataElement( dataElementD );
 
         dataElements = new HashSet<DataElement>();
 
@@ -105,13 +116,20 @@
         dataElements.add( dataElementB );
         dataElements.add( dataElementC );
         dataElements.add( dataElementD );
-                
-        expressionA = new Expression( "expressionA", "descriptionA", dataElements );
-        expressionB = new Expression( "expressionB", "descriptionB", dataElements );
-        
+
+        DataElementCategoryCombo categoryCombo = categoryService
+            .getDataElementCategoryComboByName( DataElementCategoryCombo.DEFAULT_CATEGORY_COMBO_NAME );
+        DataElementCategoryOptionCombo categoryOptionCombo = categoryCombo.getOptionCombos().iterator().next();
+
+        optionCombos = new HashSet<DataElementCategoryOptionCombo>();
+        optionCombos.add( categoryOptionCombo );
+
+        expressionA = new Expression( "expressionA", "descriptionA", dataElements, optionCombos );
+        expressionB = new Expression( "expressionB", "descriptionB", dataElements, optionCombos );
+
         expressionService.addExpression( expressionB );
         expressionService.addExpression( expressionA );
-        
+
         periodType = PeriodType.getAvailablePeriodTypes().iterator().next();
     }
 
@@ -124,24 +142,24 @@
     {
         ValidationRule ruleA = createValidationRule( 'A', equal_to, null, null, periodType );
         ValidationRule ruleB = createValidationRule( 'B', equal_to, null, null, periodType );
-        
+
         validationRuleStore.save( ruleA );
         validationRuleStore.save( ruleB );
-        
+
         Set<ValidationRule> rules = new HashSet<ValidationRule>();
-        
+
         rules.add( ruleA );
         rules.add( ruleB );
-        
+
         ValidationRuleGroup groupA = createValidationRuleGroup( 'A' );
         ValidationRuleGroup groupB = createValidationRuleGroup( 'B' );
-        
+
         groupA.setMembers( rules );
         groupB.setMembers( rules );
-        
+
         int idA = validationRuleGroupStore.save( groupA );
         int idB = validationRuleGroupStore.save( groupB );
-        
+
         assertEquals( groupA, validationRuleGroupStore.get( idA ) );
         assertEquals( groupB, validationRuleGroupStore.get( idB ) );
     }
@@ -151,35 +169,35 @@
     {
         ValidationRule ruleA = createValidationRule( 'A', equal_to, null, null, periodType );
         ValidationRule ruleB = createValidationRule( 'B', equal_to, null, null, periodType );
-        
+
         validationRuleStore.save( ruleA );
         validationRuleStore.save( ruleB );
-        
+
         Set<ValidationRule> rules = new HashSet<ValidationRule>();
-        
+
         rules.add( ruleA );
         rules.add( ruleB );
-        
+
         ValidationRuleGroup groupA = createValidationRuleGroup( 'A' );
         ValidationRuleGroup groupB = createValidationRuleGroup( 'B' );
-        
+
         groupA.setMembers( rules );
         groupB.setMembers( rules );
-        
+
         int idA = validationRuleGroupStore.save( groupA );
         int idB = validationRuleGroupStore.save( groupB );
-        
+
         assertEquals( groupA, validationRuleGroupStore.get( idA ) );
         assertEquals( groupB, validationRuleGroupStore.get( idB ) );
-        
+
         ruleA.setName( "UpdatedValidationRuleA" );
         ruleB.setName( "UpdatedValidationRuleB" );
-        
+
         validationRuleGroupStore.update( groupA );
         validationRuleGroupStore.update( groupB );
 
         assertEquals( groupA, validationRuleGroupStore.get( idA ) );
-        assertEquals( groupB, validationRuleGroupStore.get( idB ) );        
+        assertEquals( groupB, validationRuleGroupStore.get( idB ) );
     }
 
     @Test
@@ -187,32 +205,32 @@
     {
         ValidationRule ruleA = createValidationRule( 'A', equal_to, null, null, periodType );
         ValidationRule ruleB = createValidationRule( 'B', equal_to, null, null, periodType );
-        
+
         validationRuleStore.save( ruleA );
         validationRuleStore.save( ruleB );
-        
+
         Set<ValidationRule> rules = new HashSet<ValidationRule>();
-        
+
         rules.add( ruleA );
         rules.add( ruleB );
-        
+
         ValidationRuleGroup groupA = createValidationRuleGroup( 'A' );
         ValidationRuleGroup groupB = createValidationRuleGroup( 'B' );
-        
+
         groupA.setMembers( rules );
         groupB.setMembers( rules );
-        
+
         int idA = validationRuleGroupStore.save( groupA );
         int idB = validationRuleGroupStore.save( groupB );
-        
+
         assertNotNull( validationRuleGroupStore.get( idA ) );
         assertNotNull( validationRuleGroupStore.get( idB ) );
-        
+
         validationRuleGroupStore.delete( groupA );
 
         assertNull( validationRuleGroupStore.get( idA ) );
         assertNotNull( validationRuleGroupStore.get( idB ) );
-        
+
         validationRuleGroupStore.delete( groupB );
 
         assertNull( validationRuleGroupStore.get( idA ) );
@@ -224,26 +242,26 @@
     {
         ValidationRule ruleA = createValidationRule( 'A', equal_to, null, null, periodType );
         ValidationRule ruleB = createValidationRule( 'B', equal_to, null, null, periodType );
-        
+
         validationRuleStore.save( ruleA );
         validationRuleStore.save( ruleB );
-        
+
         Set<ValidationRule> rules = new HashSet<ValidationRule>();
-        
+
         rules.add( ruleA );
         rules.add( ruleB );
-        
+
         ValidationRuleGroup groupA = createValidationRuleGroup( 'A' );
         ValidationRuleGroup groupB = createValidationRuleGroup( 'B' );
-        
+
         groupA.setMembers( rules );
         groupB.setMembers( rules );
-        
+
         validationRuleGroupStore.save( groupA );
         validationRuleGroupStore.save( groupB );
-        
+
         Collection<ValidationRuleGroup> groups = validationRuleGroupStore.getAll();
-        
+
         assertEquals( 2, groups.size() );
         assertTrue( groups.contains( groupA ) );
         assertTrue( groups.contains( groupB ) );
@@ -254,26 +272,26 @@
     {
         ValidationRule ruleA = createValidationRule( 'A', equal_to, null, null, periodType );
         ValidationRule ruleB = createValidationRule( 'B', equal_to, null, null, periodType );
-        
+
         validationRuleStore.save( ruleA );
         validationRuleStore.save( ruleB );
-        
+
         Set<ValidationRule> rules = new HashSet<ValidationRule>();
-        
+
         rules.add( ruleA );
         rules.add( ruleB );
-        
+
         ValidationRuleGroup groupA = createValidationRuleGroup( 'A' );
         ValidationRuleGroup groupB = createValidationRuleGroup( 'B' );
-        
+
         groupA.setMembers( rules );
         groupB.setMembers( rules );
-        
+
         validationRuleGroupStore.save( groupA );
         validationRuleGroupStore.save( groupB );
-        
+
         ValidationRuleGroup groupByName = validationRuleGroupStore.getByName( groupA.getName() );
-        
+
         assertEquals( groupA, groupByName );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleServiceTest.java	2011-04-22 21:04:14 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleServiceTest.java	2011-06-03 13:11:34 +0000
@@ -77,7 +77,7 @@
     extends DhisTest
 {
     private BatchHandlerFactory batchHandlerFactory;
-    
+
     private DataElement dataElementA;
 
     private DataElement dataElementB;
@@ -100,6 +100,8 @@
 
     private Set<DataElement> dataElementsC = new HashSet<DataElement>();
 
+    private Set<DataElementCategoryOptionCombo> optionCombos;
+
     private DataElementCategoryCombo categoryCombo;
 
     private DataElementCategoryOptionCombo categoryOptionCombo;
@@ -143,7 +145,7 @@
         throws Exception
     {
         batchHandlerFactory = (BatchHandlerFactory) getBean( "batchHandlerFactory" );
-        
+
         validationRuleService = (ValidationRuleService) getBean( ValidationRuleService.ID );
 
         dataElementService = (DataElementService) getBean( DataElementService.ID );
@@ -157,7 +159,7 @@
         dataValueService = (DataValueService) getBean( DataValueService.ID );
 
         organisationUnitService = (OrganisationUnitService) getBean( OrganisationUnitService.ID );
-        
+
         periodService = (PeriodService) getBean( PeriodService.ID );
 
         periodType = new MonthlyPeriodType();
@@ -185,11 +187,14 @@
 
         String suffix = SEPARATOR + categoryOptionCombo.getId();
 
+        optionCombos = new HashSet<DataElementCategoryOptionCombo>();
+        optionCombos.add( categoryOptionCombo );
+
         expressionA = new Expression( "[" + dataElementIdA + suffix + "] + [" + dataElementIdB + suffix + "]",
-            "descriptionA", dataElementsA );
+            "descriptionA", dataElementsA, optionCombos );
         expressionB = new Expression( "[" + dataElementIdC + suffix + "] - [" + dataElementIdD + suffix + "]",
-            "descriptionB", dataElementsB );
-        expressionC = new Expression( "[" + dataElementIdB + suffix + "] * 2", "descriptionC", dataElementsC );
+            "descriptionB", dataElementsB , optionCombos);
+        expressionC = new Expression( "[" + dataElementIdB + suffix + "] * 2", "descriptionC", dataElementsC, optionCombos);
 
         expressionService.addExpression( expressionA );
         expressionService.addExpression( expressionB );
@@ -224,14 +229,14 @@
         dataElementB.getDataSets().add( dataSet );
         dataElementC.getDataSets().add( dataSet );
         dataElementD.getDataSets().add( dataSet );
-        
+
         dataSetService.addDataSet( dataSet );
-        
+
         dataElementService.updateDataElement( dataElementA );
         dataElementService.updateDataElement( dataElementB );
         dataElementService.updateDataElement( dataElementC );
         dataElementService.updateDataElement( dataElementD );
-        
+
         validationRuleA = createValidationRule( 'A', equal_to, expressionA, expressionB, periodType );
         validationRuleB = createValidationRule( 'B', greater_than, expressionB, expressionC, periodType );
         validationRuleC = createValidationRule( 'C', less_than_or_equal_to, expressionB, expressionA, periodType );
@@ -249,7 +254,7 @@
     // ----------------------------------------------------------------------
     // Business logic tests
     // ----------------------------------------------------------------------
-    
+
     @Test
     public void testGetAggregatedValidationResult()
     {
@@ -261,57 +266,74 @@
         List<Period> periods = new ArrayList<Period>();
         periods.add( periodA );
         periods.add( periodB );
-        
+
         List<OrganisationUnit> sources = new ArrayList<OrganisationUnit>();
         sources.add( sourceA );
         sources.add( sourceB );
-        
+
         Collection<ValidationResult> results = new HashSet<ValidationResult>();
-        
+
         results.add( new ValidationResult( periodA, sourceA, validationRuleA, 1, 1 ) );
         results.add( new ValidationResult( periodA, sourceA, validationRuleB, 1, 1 ) );
         results.add( new ValidationResult( periodA, sourceA, validationRuleC, 1, 1 ) );
         results.add( new ValidationResult( periodB, sourceB, validationRuleA, 1, 1 ) );
         results.add( new ValidationResult( periodB, sourceB, validationRuleB, 1, 1 ) );
-        
+
         Grid grid = validationRuleService.getAggregateValidationResult( results, periods, sources );
-        
+
         // First row is Periods, first column in each row is Source
-        
+
         assertEquals( "75.0", grid.getValue( 1, 1 ) );
         assertEquals( "0.0", grid.getValue( 1, 2 ) );
         assertEquals( "0.0", grid.getValue( 2, 1 ) );
         assertEquals( "50.0", grid.getValue( 2, 2 ) );
     }
-    
+
     @Test
     public void testValidateAggregatedDateDateSources()
     {
         periodService.addPeriod( periodA );
         periodService.addPeriod( periodB );
-        
-        BatchHandler<AggregatedDataValue> batchHandler = batchHandlerFactory.createBatchHandler( AggregatedDataValueBatchHandler.class ).init();
-        
-        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceA.getId(), 0, 1.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceA.getId(), 0, 2.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceA.getId(), 0, 3.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceA.getId(), 0, 4.0 ) );
-
-        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceA.getId(), 0, 1.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceA.getId(), 0, 2.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceA.getId(), 0, 3.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceA.getId(), 0, 4.0 ) );
-
-        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceB.getId(), 0, 1.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceB.getId(), 0, 2.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceB.getId(), 0, 3.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodA.getId(), 0, sourceB.getId(), 0, 4.0 ) );
-
-        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceB.getId(), 0, 1.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceB.getId(), 0, 2.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceB.getId(), 0, 3.0 ) );
-        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodB.getId(), 0, sourceB.getId(), 0, 4.0 ) );
-        
+
+        BatchHandler<AggregatedDataValue> batchHandler = batchHandlerFactory.createBatchHandler(
+            AggregatedDataValueBatchHandler.class ).init();
+
+        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceA.getId(), 0, 1.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceA.getId(), 0, 2.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceA.getId(), 0, 3.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceA.getId(), 0, 4.0 ) );
+
+        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceA.getId(), 0, 1.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceA.getId(), 0, 2.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceA.getId(), 0, 3.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceA.getId(), 0, 4.0 ) );
+
+        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceB.getId(), 0, 1.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceB.getId(), 0, 2.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceB.getId(), 0, 3.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodA
+            .getId(), 0, sourceB.getId(), 0, 4.0 ) );
+
+        batchHandler.addObject( new AggregatedDataValue( dataElementA.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceB.getId(), 0, 1.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementB.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceB.getId(), 0, 2.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementC.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceB.getId(), 0, 3.0 ) );
+        batchHandler.addObject( new AggregatedDataValue( dataElementD.getId(), categoryOptionCombo.getId(), periodB
+            .getId(), 0, sourceB.getId(), 0, 4.0 ) );
+
         batchHandler.flush();
 
         validationRuleService.saveValidationRule( validationRuleA );
@@ -319,8 +341,9 @@
         validationRuleService.saveValidationRule( validationRuleC );
         validationRuleService.saveValidationRule( validationRuleD );
 
-        Collection<ValidationResult> results = validationRuleService.validateAggregate( getDate( 2000, 2, 1 ), getDate( 2000, 6, 1 ), sourcesA );
-        
+        Collection<ValidationResult> results = validationRuleService.validateAggregate( getDate( 2000, 2, 1 ), getDate(
+            2000, 6, 1 ), sourcesA );
+
         Collection<ValidationResult> reference = new HashSet<ValidationResult>();
 
         reference.add( new ValidationResult( periodA, sourceA, validationRuleA, 3.0, -1.0 ) );
@@ -342,7 +365,7 @@
         assertEquals( results.size(), 8 );
         assertEquals( reference, results );
     }
-    
+
     @Test
     public void testValidateDateDateSources()
     {
@@ -520,14 +543,14 @@
     // ----------------------------------------------------------------------
     // CURD functionality tests
     // ----------------------------------------------------------------------
-    
+
     @Test
     public void testSaveValidationRule()
     {
         int id = validationRuleService.saveValidationRule( validationRuleA );
-        
+
         validationRuleA = validationRuleService.getValidationRule( id );
-        
+
         assertEquals( validationRuleA.getName(), "ValidationRuleA" );
         assertEquals( validationRuleA.getDescription(), "DescriptionA" );
         assertEquals( validationRuleA.getType(), ValidationRule.TYPE_ABSOLUTE );
@@ -536,13 +559,13 @@
         assertNotNull( validationRuleA.getRightSide().getExpression() );
         assertEquals( validationRuleA.getPeriodType(), periodType );
     }
-    
+
     @Test
     public void testUpdateValidationRule()
     {
         int id = validationRuleService.saveValidationRule( validationRuleA );
         validationRuleA = validationRuleService.getValidationRuleByName( "ValidationRuleA" );
-        
+
         assertEquals( validationRuleA.getName(), "ValidationRuleA" );
         assertEquals( validationRuleA.getDescription(), "DescriptionA" );
         assertEquals( validationRuleA.getType(), ValidationRule.TYPE_ABSOLUTE );
@@ -568,21 +591,21 @@
     {
         int idA = validationRuleService.saveValidationRule( validationRuleA );
         int idB = validationRuleService.saveValidationRule( validationRuleB );
-        
+
         assertNotNull( validationRuleService.getValidationRule( idA ) );
         assertNotNull( validationRuleService.getValidationRule( idB ) );
 
         validationRuleA.clearExpressions();
-        
+
         validationRuleService.deleteValidationRule( validationRuleA );
 
         assertNull( validationRuleService.getValidationRule( idA ) );
         assertNotNull( validationRuleService.getValidationRule( idB ) );
 
         validationRuleB.clearExpressions();
-        
+
         validationRuleService.deleteValidationRule( validationRuleB );
-        
+
         assertNull( validationRuleService.getValidationRule( idA ) );
         assertNull( validationRuleService.getValidationRule( idB ) );
     }
@@ -605,9 +628,9 @@
     {
         int id = validationRuleService.saveValidationRule( validationRuleA );
         validationRuleService.saveValidationRule( validationRuleB );
-        
+
         ValidationRule rule = validationRuleService.getValidationRuleByName( "ValidationRuleA" );
-        
+
         assertEquals( rule.getId(), id );
         assertEquals( rule.getName(), "ValidationRuleA" );
     }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleStoreTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleStoreTest.java	2010-12-29 10:06:33 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/validation/ValidationRuleStoreTest.java	2011-06-03 13:11:34 +0000
@@ -27,12 +27,12 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.expression.Operator.*;
-
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
+import static org.hisp.dhis.expression.Operator.equal_to;
+import static org.hisp.dhis.expression.Operator.greater_than;
 
 import java.util.Collection;
 import java.util.HashSet;
@@ -40,6 +40,9 @@
 
 import org.hisp.dhis.DhisTest;
 import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
 import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.expression.Expression;
 import org.hisp.dhis.expression.ExpressionService;
@@ -68,6 +71,8 @@
 
     private Set<DataElement> dataElements;
 
+    private Set<DataElementCategoryOptionCombo> optionCombos;
+
     private Expression expressionA;
 
     private Expression expressionB;
@@ -86,6 +91,8 @@
 
         dataElementService = (DataElementService) getBean( DataElementService.ID );
 
+        categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID );
+
         expressionService = (ExpressionService) getBean( ExpressionService.ID );
 
         dataElementA = createDataElement( 'A' );
@@ -105,8 +112,15 @@
         dataElements.add( dataElementC );
         dataElements.add( dataElementD );
 
-        expressionA = new Expression( "expressionA", "descriptionA", dataElements );
-        expressionB = new Expression( "expressionB", "descriptionB", dataElements );
+        DataElementCategoryCombo categoryCombo = categoryService
+            .getDataElementCategoryComboByName( DataElementCategoryCombo.DEFAULT_CATEGORY_COMBO_NAME );
+        DataElementCategoryOptionCombo categoryOptionCombo = categoryCombo.getOptionCombos().iterator().next();
+
+        optionCombos = new HashSet<DataElementCategoryOptionCombo>();
+        optionCombos.add( categoryOptionCombo );
+
+        expressionA = new Expression( "expressionA", "descriptionA", dataElements, optionCombos );
+        expressionB = new Expression( "expressionB", "descriptionB", dataElements, optionCombos );
 
         expressionService.addExpression( expressionB );
         expressionService.addExpression( expressionA );
@@ -127,8 +141,7 @@
     @Test
     public void testSaveValidationRule()
     {
-        ValidationRule validationRule = createValidationRule( 'A', equal_to, expressionA,
-            expressionB, periodType );
+        ValidationRule validationRule = createValidationRule( 'A', equal_to, expressionA, expressionB, periodType );
 
         int id = validationRuleStore.saveValidationRule( validationRule );
 
@@ -146,8 +159,7 @@
     @Test
     public void testUpdateValidationRule()
     {
-        ValidationRule validationRule = createValidationRule( 'A', equal_to, expressionA,
-            expressionB, periodType );
+        ValidationRule validationRule = createValidationRule( 'A', equal_to, expressionA, expressionB, periodType );
 
         int id = validationRuleStore.saveValidationRule( validationRule );
 
@@ -176,10 +188,8 @@
     @Test
     public void testDeleteValidationRule()
     {
-        ValidationRule validationRuleA = createValidationRule( 'A', equal_to, expressionA,
-            expressionB, periodType );
-        ValidationRule validationRuleB = createValidationRule( 'B', equal_to, expressionA,
-            expressionB, periodType );
+        ValidationRule validationRuleA = createValidationRule( 'A', equal_to, expressionA, expressionB, periodType );
+        ValidationRule validationRuleB = createValidationRule( 'B', equal_to, expressionA, expressionB, periodType );
 
         int idA = validationRuleStore.saveValidationRule( validationRuleA );
         int idB = validationRuleStore.saveValidationRule( validationRuleB );
@@ -205,10 +215,8 @@
     @Test
     public void testGetAllValidationRules()
     {
-        ValidationRule validationRuleA = createValidationRule( 'A', equal_to, expressionA,
-            expressionB, periodType );
-        ValidationRule validationRuleB = createValidationRule( 'B', equal_to, expressionA,
-            expressionB, periodType );
+        ValidationRule validationRuleA = createValidationRule( 'A', equal_to, expressionA, expressionB, periodType );
+        ValidationRule validationRuleB = createValidationRule( 'B', equal_to, expressionA, expressionB, periodType );
 
         validationRuleStore.saveValidationRule( validationRuleA );
         validationRuleStore.saveValidationRule( validationRuleB );
@@ -223,10 +231,8 @@
     @Test
     public void testGetValidationRuleByName()
     {
-        ValidationRule validationRuleA = createValidationRule( 'A', equal_to, expressionA,
-            expressionB, periodType );
-        ValidationRule validationRuleB = createValidationRule( 'B', equal_to, expressionA,
-            expressionB, periodType );
+        ValidationRule validationRuleA = createValidationRule( 'A', equal_to, expressionA, expressionB, periodType );
+        ValidationRule validationRuleB = createValidationRule( 'B', equal_to, expressionA, expressionB, periodType );
 
         int id = validationRuleStore.saveValidationRule( validationRuleA );
         validationRuleStore.saveValidationRule( validationRuleB );
@@ -254,25 +260,22 @@
         dataElementsD.addAll( dataElementsA );
         dataElementsD.addAll( dataElementsB );
 
-        Expression expression1 = new Expression( "Expression1", "Expression1", dataElementsA );
-        Expression expression2 = new Expression( "Expression2", "Expression2", dataElementsB );
-        Expression expression3 = new Expression( "Expression3", "Expression3", dataElementsC );
+        Expression expression1 = new Expression( "Expression1", "Expression1", dataElementsA, optionCombos );
+        Expression expression2 = new Expression( "Expression2", "Expression2", dataElementsB, optionCombos );
+        Expression expression3 = new Expression( "Expression3", "Expression3", dataElementsC, optionCombos );
 
         expressionService.addExpression( expression1 );
         expressionService.addExpression( expression2 );
         expressionService.addExpression( expression3 );
 
-        ValidationRule ruleA = createValidationRule( 'A', equal_to, expression1, expression3,
-            periodType );
-        ValidationRule ruleB = createValidationRule( 'B', equal_to, expression2, expression3,
-            periodType );
-        ValidationRule ruleC = createValidationRule( 'C', equal_to, expression3, expression3,
-            periodType );
+        ValidationRule ruleA = createValidationRule( 'A', equal_to, expression1, expression3, periodType );
+        ValidationRule ruleB = createValidationRule( 'B', equal_to, expression2, expression3, periodType );
+        ValidationRule ruleC = createValidationRule( 'C', equal_to, expression3, expression3, periodType );
 
         validationRuleStore.saveValidationRule( ruleA );
         validationRuleStore.saveValidationRule( ruleB );
         validationRuleStore.saveValidationRule( ruleC );
-
+        
         Collection<ValidationRule> rules = validationRuleStore.getValidationRulesByDataElements( dataElementsA );
 
         assertNotNull( rules );
@@ -310,20 +313,17 @@
         dataElementsD.addAll( dataElementsA );
         dataElementsD.addAll( dataElementsB );
 
-        Expression expression1 = new Expression( "Expression1", "Expression1", dataElementsA );
-        Expression expression2 = new Expression( "Expression2", "Expression2", dataElementsB );
-        Expression expression3 = new Expression( "Expression3", "Expression3", dataElementsC );
+        Expression expression1 = new Expression( "Expression1", "Expression1", dataElementsA, optionCombos );
+        Expression expression2 = new Expression( "Expression2", "Expression2", dataElementsB, optionCombos );
+        Expression expression3 = new Expression( "Expression3", "Expression3", dataElementsC, optionCombos );
 
         expressionService.addExpression( expression1 );
         expressionService.addExpression( expression2 );
         expressionService.addExpression( expression3 );
 
-        ValidationRule ruleA = createValidationRule( 'A', equal_to, expression1, expression3,
-            periodType );
-        ValidationRule ruleB = createValidationRule( 'B', equal_to, expression2, expression3,
-            periodType );
-        ValidationRule ruleC = createValidationRule( 'C', equal_to, expression3, expression3,
-            periodType );
+        ValidationRule ruleA = createValidationRule( 'A', equal_to, expression1, expression3, periodType );
+        ValidationRule ruleB = createValidationRule( 'B', equal_to, expression2, expression3, periodType );
+        ValidationRule ruleC = createValidationRule( 'C', equal_to, expression3, expression3, periodType );
 
         validationRuleStore.saveValidationRule( ruleA );
         validationRuleStore.saveValidationRule( ruleB );

=== modified file 'dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/dxf/converter/ValidationRuleConverter.java'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/dxf/converter/ValidationRuleConverter.java	2010-12-29 10:06:33 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/dxf/converter/ValidationRuleConverter.java	2011-06-03 13:11:34 +0000
@@ -180,6 +180,8 @@
             validationRule.getLeftSide().setDescription( values.get( FIELD_LEFTSIDE_DESCRIPTION ) );
             validationRule.getLeftSide().setDataElementsInExpression(
                 expressionService.getDataElementsInExpression( validationRule.getLeftSide().getExpression() ) );
+            validationRule.getLeftSide().setOptionCombosInExpression(
+                expressionService.getOptionCombosInExpression( validationRule.getLeftSide().getExpression() ) );
 
             validationRule.getRightSide().setExpression(
                 expressionService.convertExpression( values.get( FIELD_RIGHTSIDE_EXPRESSION ), dataElementMapping,
@@ -187,8 +189,9 @@
             validationRule.getRightSide().setDescription( values.get( FIELD_RIGHTSIDE_DESCRIPTION ) );
             validationRule.getRightSide().setDataElementsInExpression(
                 expressionService.getDataElementsInExpression( validationRule.getRightSide().getExpression() ) );
+            validationRule.getRightSide().setOptionCombosInExpression(
+                expressionService.getOptionCombosInExpression( validationRule.getRightSide().getExpression() ) );
 
-            // TODO Intermediate hack!
             validationRule.setPeriodType( PeriodType.getPeriodTypeByName( MonthlyPeriodType.NAME ) );
 
             importObject( validationRule, params );

=== modified file 'dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java	2010-05-31 13:53:07 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java	2011-06-03 13:11:34 +0000
@@ -83,6 +83,7 @@
         match.getRightSide().setExpression( object.getRightSide().getExpression() );
         match.getRightSide().setDescription( object.getRightSide().getDescription() );
         match.getRightSide().setDataElementsInExpression( object.getRightSide().getDataElementsInExpression() );
+        match.getRightSide().setOptionCombosInExpression( object.getRightSide().getOptionCombosInExpression() );
         
         expressionService.updateExpression( match.getLeftSide() );
         expressionService.updateExpression( match.getRightSide() );

=== modified file 'dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java'
--- dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java	2011-05-19 09:24:01 +0000
+++ dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/dbms/HibernateDbmsManager.java	2011-06-03 13:11:34 +0000
@@ -73,11 +73,11 @@
     // -------------------------------------------------------------------------
 
     public void emptyDatabase()
-    {   
+    {
         emptyTable( "translation" );
         emptyTable( "importobject" );
         emptyTable( "importdatavalue" );
-        
+
         emptyTable( "datavalue_audit" );
         emptyTable( "datavalue" );
         emptyTable( "completedatasetregistration" );
@@ -90,13 +90,13 @@
         emptyTable( "reporttable_organisationunits" );
         emptyTable( "reporttable_displaycolumns" );
         emptyTable( "reporttable" );
-        
+
         emptyTable( "datamartexportdataelements" );
         emptyTable( "datamartexportindicators" );
         emptyTable( "datamartexportorgunits" );
         emptyTable( "datamartexportperiods" );
         emptyTable( "datamartexport" );
-        
+
         emptyTable( "orgunitgroupsetmembers" );
         emptyTable( "orgunitgroupset" );
         emptyTable( "orgunitgroupmembers" );
@@ -111,11 +111,12 @@
         emptyTable( "validationrule" );
 
         emptyTable( "datasetsource" );
-        emptyTable( "datasetmembers" );        
+        emptyTable( "datasetmembers" );
         emptyTable( "dataset" );
 
         emptyTable( "minmaxdataelement" );
         emptyTable( "expressiondataelement" );
+        emptyTable( "expressionoptioncombo" );
         emptyTable( "calculateddataelement" );
         emptyTable( "dataelementgroupsetmembers" );
         emptyTable( "dataelementgroupset" );
@@ -123,15 +124,10 @@
         emptyTable( "dataelementgroup" );
         emptyTable( "dataelementaggregationlevels" );
         emptyTable( "dataelement" );
-        emptyTable( "expression" );
         emptyTable( "categoryoptioncombos_categoryoptions" );
         emptyTable( "categorycombos_optioncombos" );
         emptyTable( "categorycombos_categories" );
         emptyTable( "categories_categoryoptions" );
-        emptyTable( "categoryoptioncombo" );
-        emptyTable( "categorycombo" );
-        emptyTable( "dataelementcategory" );
-        emptyTable( "dataelementcategoryoption" );
 
         emptyTable( "organisationunit" );
         emptyTable( "mocksource" );
@@ -144,19 +140,25 @@
         emptyTable( "indicatorgroup" );
         emptyTable( "indicator" );
         emptyTable( "indicatortype" );
-        
+
+        emptyTable( "expression" );
+        emptyTable( "categoryoptioncombo" );
+        emptyTable( "categorycombo" );
+        emptyTable( "dataelementcategory" );
+        emptyTable( "dataelementcategoryoption" );
+
         dropTable( "aggregateddatavalue" );
-        dropTable( "aggregatedindicatorvalue" );        
-        dropTable( "aggregateddatasetcompleteness" ); 
+        dropTable( "aggregatedindicatorvalue" );
+        dropTable( "aggregateddatasetcompleteness" );
         dropTable( "datavaluecrosstab" );
-        
+
         log.debug( "Cleared database contents" );
-               
+
         cacheManager.clearCache();
-        
+
         log.debug( "Cleared Hibernate cache" );
     }
-    
+
     public void clearSession()
     {
         sessionFactory.getCurrentSession().clear();
@@ -177,7 +179,7 @@
             log.debug( "Table " + table + " does not exist" );
         }
     }
-    
+
     private void dropTable( String table )
     {
         try

=== modified file 'dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java'
--- dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java	2011-04-24 15:50:02 +0000
+++ dhis-2/dhis-support/dhis-support-test/src/main/java/org/hisp/dhis/DhisConvenienceTest.java	2011-06-03 13:11:34 +0000
@@ -743,14 +743,15 @@
      *        entering into the expression.
      */
     public static Expression createExpression( char uniqueCharacter, String expressionString,
-        Set<DataElement> dataElementsInExpression )
+        Set<DataElement> dataElementsInExpression, Set<DataElementCategoryOptionCombo> optionCombosInExpression )
     {
         Expression expression = new Expression();
 
         expression.setExpression( expressionString );
         expression.setDescription( "Description" + uniqueCharacter );
         expression.setDataElementsInExpression( dataElementsInExpression );
-
+        expression.setOptionCombosInExpression( optionCombosInExpression );
+        
         return expression;
     }
 

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/AddValidationRuleAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/AddValidationRuleAction.java	2011-05-05 21:15:45 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/AddValidationRuleAction.java	2011-06-03 13:11:34 +0000
@@ -143,12 +143,14 @@
         leftSide.setExpression( leftSideExpression );
         leftSide.setDescription( leftSideDescription );
         leftSide.setDataElementsInExpression( expressionService.getDataElementsInExpression( leftSideExpression ) );
+        leftSide.setOptionCombosInExpression( expressionService.getOptionCombosInExpression( leftSideExpression ) );
         
         Expression rightSide = new Expression();
         
         rightSide.setExpression( rightSideExpression );
         rightSide.setDescription( rightSideDescription );
         rightSide.setDataElementsInExpression( expressionService.getDataElementsInExpression( rightSideExpression ) );
+        rightSide.setOptionCombosInExpression( expressionService.getOptionCombosInExpression( rightSideExpression ) );
         
         ValidationRule validationRule = new ValidationRule();
         

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/UpdateValidationRuleAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/UpdateValidationRuleAction.java	2011-05-05 21:15:45 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/UpdateValidationRuleAction.java	2011-06-03 13:11:34 +0000
@@ -153,12 +153,15 @@
         validationRule.getLeftSide().setDescription( leftSideDescription );
         validationRule.getLeftSide().setDataElementsInExpression(
             expressionService.getDataElementsInExpression( leftSideExpression ) );
+        validationRule.getLeftSide().setOptionCombosInExpression(
+            expressionService.getOptionCombosInExpression( leftSideExpression ) );
 
         validationRule.getRightSide().setExpression( rightSideExpression );
         validationRule.getRightSide().setDescription( rightSideDescription );
-
         validationRule.getRightSide().setDataElementsInExpression(
             expressionService.getDataElementsInExpression( rightSideExpression ) );
+        validationRule.getRightSide().setOptionCombosInExpression(
+            expressionService.getOptionCombosInExpression( rightSideExpression ) );
 
         PeriodType periodType = periodService.getPeriodTypeByName( periodTypeName );
         validationRule.setPeriodType( periodService.getPeriodTypeByClass( periodType.getClass() ) );