← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 7725: Implemented option on expressions to ignore them or not if there are missing data values during e...

 

------------------------------------------------------------
revno: 7725
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2012-07-26 13:14:41 +0200
message:
  Implemented option on expressions to ignore them or not if there are missing data values during evaluation
added:
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expressionBuilder.js
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/expression/DefaultExpressionService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/expression/hibernate/Expression.hbm.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/indicatorExpressionBuilderForm.vm
  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
  dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties
  dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleForm.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/expressionBuilderForm.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expression.js
  dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleForm.vm


--
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	2012-06-27 05:46:37 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/Expression.java	2012-07-26 11:14:41 +0000
@@ -91,6 +91,12 @@
      * A description of the Expression.
      */
     private String description;
+    
+    /**
+     * Indicates whether the expression should evaluate to null if there are 
+     * missing data values in the expression.
+     */
+    private boolean nullIfBlank;
 
     /**
      * A reference to the DataElements in the Expression.
@@ -274,4 +280,17 @@
     {
         this.description = description;
     }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty
+    public boolean isNullIfBlank()
+    {
+        return nullIfBlank;
+    }
+
+    public void setNullIfBlank( boolean nullIfBlank )
+    {
+        this.nullIfBlank = nullIfBlank;
+    }
 }

=== 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	2012-07-25 14:44:02 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/expression/ExpressionService.java	2012-07-26 11:14:41 +0000
@@ -103,7 +103,7 @@
     Collection<Expression> getAllExpressions();
 
     Double getExpressionValue( Expression expression, Map<DataElementOperand, Double> valueMap, 
-        Map<Integer, Double> constantMap, Integer days, boolean nullIfNoValues );
+        Map<Integer, Double> constantMap, Integer days );
     
     /**
      * Returns all DataElements included in the given expression string.

=== 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	2012-07-25 14:44:02 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/expression/DefaultExpressionService.java	2012-07-26 11:14:41 +0000
@@ -143,9 +143,9 @@
     // -------------------------------------------------------------------------
     
     public Double getExpressionValue( Expression expression, Map<DataElementOperand, Double> valueMap, 
-        Map<Integer, Double> constantMap, Integer days, boolean nullIfNoValues )
+        Map<Integer, Double> constantMap, Integer days )
     {
-        final String expressionString = generateExpression( expression.getExpression(), valueMap, constantMap, days, nullIfNoValues );
+        final String expressionString = generateExpression( expression.getExpression(), valueMap, constantMap, days, expression.isNullIfBlank() );
 
         return expressionString != null ? calculateExpression( expressionString ) : null;
     }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2012-07-26 06:41:43 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2012-07-26 11:14:41 +0000
@@ -387,6 +387,7 @@
         executeSql( "update dataelement set zeroissignificant = false where zeroissignificant is null" );
         executeSql( "update organisationunit set haspatients = false where haspatients is null" );
         executeSql( "update dataset set expirydays = 0 where expirydays is null" );
+        executeSql( "update expression set nullifblank = false where nullifblank is null" );
 
         executeSql( "update reporttable set reportingmonth = false where reportingmonth is null" );
         executeSql( "update reporttable set reportingbimonth = false where reportingbimonth is null" );

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java	2012-07-25 13:18:48 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java	2012-07-26 11:14:41 +0000
@@ -146,7 +146,7 @@
     // -------------------------------------------------------------------------
 
     // -------------------------------------------------------------------------
-    // Aggregate
+    // Aggregate TODO remove
     // -------------------------------------------------------------------------
 
     public Grid getAggregateValidationResult( Collection<ValidationResult> results, List<Period> periods,
@@ -377,11 +377,11 @@
                 if ( validationRule.getPeriodType() != null
                     && validationRule.getPeriodType().equals( period.getPeriodType() ) )
                 {
-                    leftSide = expressionService.getExpressionValue( validationRule.getLeftSide(), valueMap, constantMap, null, true );
+                    leftSide = expressionService.getExpressionValue( validationRule.getLeftSide(), valueMap, constantMap, null );
 
                     if ( leftSide != null )
                     {
-                        rightSide = expressionService.getExpressionValue( validationRule.getRightSide(), valueMap, constantMap, null, true );
+                        rightSide = expressionService.getExpressionValue( validationRule.getRightSide(), valueMap, constantMap, null );
 
                         if ( rightSide != 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-06-03 13:11:34 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/expression/hibernate/Expression.hbm.xml	2012-07-26 11:14:41 +0000
@@ -16,6 +16,8 @@
 
     <property name="expression" type="text" />
 
+	<property name="nullIfBlank" />
+
     <set name="dataElementsInExpression" table="expressiondataelement">
       <cache usage="read-write" />      
       <key column="expressionid" foreign-key="fk_expressiondataelement_expressionid" />

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/indicatorExpressionBuilderForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/indicatorExpressionBuilderForm.vm	2012-06-09 22:21:27 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/webapp/dhis-web-maintenance-datadictionary/indicatorExpressionBuilderForm.vm	2012-07-26 11:14:41 +0000
@@ -9,10 +9,10 @@
 		dialog = jQuery("#indicator-expression-container").dialog({
 			modal: true,
 			autoOpen: false,
-			minWidth: 820,
-			minHeight: 550,
-			width: 820,
-			height: 550
+			minWidth: 840,
+			minHeight: 560,
+			width: 840,
+			height: 560
 		});
 		
 		getConstantsPage();

=== 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-12-26 10:07:59 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/AddValidationRuleAction.java	2012-07-26 11:14:41 +0000
@@ -111,6 +111,13 @@
         this.leftSideDescription = leftSideDescription;
     }
 
+    private boolean leftSideNullIfBlank;
+    
+    public void setLeftSideNullIfBlank( boolean leftSideNullIfBlank )
+    {
+        this.leftSideNullIfBlank = leftSideNullIfBlank;
+    }
+
     private String rightSideExpression;
 
     public void setRightSideExpression( String rightSideExpression )
@@ -124,6 +131,13 @@
     {
         this.rightSideDescription = rightSideDescription;
     }
+    
+    private boolean rightSideNullIfBlank;
+
+    public void setRightSideNullIfBlank( boolean rightSideNullIfBlank )
+    {
+        this.rightSideNullIfBlank = rightSideNullIfBlank;
+    }
 
     private String periodTypeName;
     
@@ -142,6 +156,7 @@
         
         leftSide.setExpression( leftSideExpression );
         leftSide.setDescription( leftSideDescription );
+        leftSide.setNullIfBlank( leftSideNullIfBlank );
         leftSide.setDataElementsInExpression( expressionService.getDataElementsInExpression( leftSideExpression ) );
         leftSide.setOptionCombosInExpression( expressionService.getOptionCombosInExpression( leftSideExpression ) );
         
@@ -149,6 +164,7 @@
         
         rightSide.setExpression( rightSideExpression );
         rightSide.setDescription( rightSideDescription );
+        rightSide.setNullIfBlank( rightSideNullIfBlank );
         rightSide.setDataElementsInExpression( expressionService.getDataElementsInExpression( rightSideExpression ) );
         rightSide.setOptionCombosInExpression( expressionService.getOptionCombosInExpression( rightSideExpression ) );
         

=== 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-12-26 10:07:59 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/UpdateValidationRuleAction.java	2012-07-26 11:14:41 +0000
@@ -116,6 +116,13 @@
         this.leftSideDescription = leftSideDescription;
     }
 
+    private boolean leftSideNullIfBlank;
+    
+    public void setLeftSideNullIfBlank( boolean leftSideNullIfBlank )
+    {
+        this.leftSideNullIfBlank = leftSideNullIfBlank;
+    }
+
     private String rightSideExpression;
 
     public void setRightSideExpression( String rightSideExpression )
@@ -130,6 +137,13 @@
         this.rightSideDescription = rightSideDescription;
     }
 
+    private boolean rightSideNullIfBlank;
+
+    public void setRightSideNullIfBlank( boolean rightSideNullIfBlank )
+    {
+        this.rightSideNullIfBlank = rightSideNullIfBlank;
+    }
+
     private String periodTypeName;
 
     public void setPeriodTypeName( String periodTypeName )
@@ -151,17 +165,15 @@
 
         validationRule.getLeftSide().setExpression( leftSideExpression );
         validationRule.getLeftSide().setDescription( leftSideDescription );
-        validationRule.getLeftSide().setDataElementsInExpression(
-            expressionService.getDataElementsInExpression( leftSideExpression ) );
-        validationRule.getLeftSide().setOptionCombosInExpression(
-            expressionService.getOptionCombosInExpression( leftSideExpression ) );
+        validationRule.getLeftSide().setNullIfBlank( leftSideNullIfBlank );
+        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 ) );
+        validationRule.getRightSide().setNullIfBlank( rightSideNullIfBlank );
+        validationRule.getRightSide().setDataElementsInExpression( expressionService.getDataElementsInExpression( rightSideExpression ) );
+        validationRule.getRightSide().setOptionCombosInExpression( expressionService.getOptionCombosInExpression( rightSideExpression ) );
 
         PeriodType periodType = periodService.getPeriodTypeByName( periodTypeName );
         validationRule.setPeriodType( periodService.getPeriodTypeByClass( periodType.getClass() ) );

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties	2012-05-01 13:14:33 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/org/hisp/dhis/validationrule/i18n_module.properties	2012-07-26 11:14:41 +0000
@@ -122,4 +122,5 @@
 get_report_as_pdf=Download as PDF
 max_values_exceeded=More than 500 values found, please fix the violations or narrow the search to see all
 specify_dataset=Please specify data sets
-analysing_please_wait=Analysing data, please wait
\ No newline at end of file
+analysing_please_wait=Analysing data, please wait
+skip_for_missing_values=Skip for missing values
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml	2012-02-22 18:23:04 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/struts.xml	2012-07-26 11:14:41 +0000
@@ -33,7 +33,7 @@
       <param name="page">/dhis-web-validationrule/addValidationRuleForm.vm</param>
       <param name="menu">/dhis-web-validationrule/menu.vm</param>
       <param name="javascripts">javascript/general.js,javascript/expression.js,
-        javascript/addValidationRuleForm.js</param>
+        javascript/expressionBuilder.js,javascript/addValidationRuleForm.js</param>
       <param name="requiredAuthorities">F_VALIDATIONRULE_ADD</param>
     </action>
 
@@ -63,7 +63,7 @@
       <result name="success" type="velocity">/main.vm</result>
       <param name="page">/dhis-web-validationrule/updateValidationRuleForm.vm</param>
       <param name="javascripts">javascript/general.js,javascript/expression.js,
-        javascript/updateValidationRuleForm.js</param>
+        javascript/expressionBuilder.js,javascript/updateValidationRuleForm.js</param>
       <param name="requiredAuthorities">F_VALIDATIONRULE_UPDATE</param>
     </action>
 

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleForm.vm	2011-09-26 09:31:56 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/addValidationRuleForm.vm	2012-07-26 11:14:41 +0000
@@ -45,10 +45,13 @@
 			<input type="hidden" id="leftSideDescription" name="leftSideDescription">
 			<input type="hidden" id="leftSideExpression" name="leftSideExpression">
 			<input type="hidden" id="leftSideTextualExpression" name="leftSideTextualExpression">
+			<input type="hidden" id="leftSideNullIfBlank" name="leftSideNullIfBlank">
+			
 			<input type="button" value="$i18n.getString( 'edit_right_side' )" style="width:10em" onclick="editRightExpression();"></td>
 			<input type="hidden" id="rightSideDescription" name="rightSideDescription">
 			<input type="hidden" id="rightSideExpression" name="rightSideExpression">
 			<input type="hidden" id="rightSideTextualExpression" name="rightSideTextualExpression">
+			<input type="hidden" id="rightSideNullIfBlank" name="rightSideNullIfBlank">
 		</td>	
 	</tr>
 	<tr>

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/expressionBuilderForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/expressionBuilderForm.vm	2012-06-09 22:21:27 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/expressionBuilderForm.vm	2012-07-26 11:14:41 +0000
@@ -1,141 +1,4 @@
 <script type="text/javascript">
-	var left = true;
-	var dialog = null;
-	
-	jQuery(document).ready(function() {
-		dialog = jQuery( "#expression-container" ).dialog({
-			modal: true,
-			autoOpen:false,
-			minWidth: 820,
-			minHeight: 550,
-			width:820,
-			height:550,
-			title: "$i18n.getString( 'expression' )"
-		});
-			
-		jQuery( "#periodTypeName" ).change(function(){
-			getOperandsPage();
-		});
-		
-		getConstantsPage();
-		getOperandsPage();
-	});
-	
-	function editLeftExpression()
-	{		
-		left = true;
-		
-		var leftSideDescription = getFieldValue( 'leftSideDescription' );
-		var leftSideExpression = getFieldValue( 'leftSideExpression' );
-		var leftSideTextualExpression = getFieldValue( 'leftSideTextualExpression' );
-		
-		setFieldValue( 'expression', leftSideExpression );
-		setFieldValue( 'description', leftSideDescription );
-		setInnerHTML( 'formulaText', leftSideTextualExpression );
-		
-		dialog.dialog("open");
-	}
-	
-	function editRightExpression()
-	{
-		left = false;
-		
-		var rightSideDescription = getFieldValue( 'rightSideDescription' );
-		var rightSideExpression = getFieldValue( 'rightSideExpression' );
-		var rightSideTextualExpression = getFieldValue( 'rightSideTextualExpression' );
-		
-		setFieldValue( 'expression', rightSideExpression );
-		setFieldValue( 'description', rightSideDescription );
-		setInnerHTML( 'formulaText', rightSideTextualExpression );
-		
-		dialog.dialog("open");
-	}
-	
-	function getConstantsPage()
-	{
-		var target = jQuery( "#expression-container select[id=constantId]" );
-		target.children().remove();
-		
-		jQuery.postJSON( '../dhis-web-commons-ajax-json/getConstants.action', {},
-			function( json ) {
-				if ( json.constants.length == 0 )
-				{
-					setInnerHTML( 'constantHeader', "<i style='color:red'>"+i18n_no_constant_to_select+"</i>" );
-					return;
-				}
-				
-				jQuery.each( json.constants, function(i, item) {
-					target.append( '<option value="[C'+item.constantId+']">'+item.constantName+'</option>' );
-				});
-			});
-	}
-	
-	function getOperandsPage()
-	{
-		var key = getFieldValue( "expression-container input[id=filter]" );
-		
-		var periodType = getFieldValue( "periodTypeName" );
-	
-		dataDictionary.loadOperands( "#expression-container select[id=dataElementId]", {usePaging: true, key: key, periodType: periodType} );	
-	}
-	
-	function clearSearchText()
-	{
-		jQuery( "#expression-container input[id=filter]").val("");
-		getOperandsPage();
-	}
-	
-	function getExpressionText()
-	{
-		if( hasText('expression') ){
-			jQuery.postJSON( '../dhis-web-commons-ajax-json/getExpressionText.action', {
-				expression: getFieldValue('expression')
-			}, function( json ){
-				if( json.response == 'success' || json.response == 'error' )
-				{
-					jQuery( "#formulaText").html( json.message );
-				}
-				else {
-					jQuery( "#formulaText").html( '' );
-				}
-			});
-		}else{
-			jQuery( "#formulaText").html( '' );
-		}
-	}
-	
-	function insertText( inputAreaName, inputText )
-	{
-		insertTextCommon( inputAreaName, inputText );
-		
-		getExpressionText();
-	}
-	
-	function insertExpression()
-	{
-		var expression = getFieldValue( 'expression-container textarea[id=expression]' );
-		var description = getFieldValue( 'expression-container input[id=description]' );
-		
-		jQuery.postJSON( '../dhis-web-commons-ajax-json/getExpressionText.action', 
-			{expression: expression},
-			function( json ){
-				if( json.response == 'error') markInvalid( 'expression-container textarea[id=expression]' , json.message );
-				else {								
-					if( left ){								
-						setFieldValue( 'leftSideExpression', expression );
-						setFieldValue( 'leftSideDescription', description );
-						setFieldValue( 'leftSideTextualExpression', getInnerHTML('formulaText') );			
-					}else{
-						setFieldValue( 'rightSideExpression', expression );
-						setFieldValue( 'rightSideDescription', description );
-						setFieldValue( 'rightSideTextualExpression', getInnerHTML('formulaText') );									
-					}
-					
-					dialog.dialog( "close" );
-				}
-			});
-	}
-		
 	jQuery( function()
 	{
 		validation( 'expression-form', insertExpression );
@@ -160,7 +23,8 @@
 	</tr>
 	<tr>
 		<td colspan="2">
-			<input type="text" id="description" name="description" style="width:250px" class="{validate:{required:true}}"/>
+			<input type="text" id="description" name="description" style="width:250px" class="{validate:{required:true}}"/><br><br>
+			<input type="checkbox" id="nullIfBlank" name="nullIfBlank" value="true">&nbsp;<label for="nullIfBlank">$i18n.getString( "skip_for_missing_values" )</label>
 		</td>
 		<td>
 			<select id="constantId" name="constantId" size="3" style="min-width:450px" ondblclick="insertText( 'expression', this.value )">

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expression.js'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expression.js	2011-06-23 14:44:17 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expression.js	2012-07-26 11:14:41 +0000
@@ -81,7 +81,6 @@
 
 function checkNotEmpty( field, message )
 {
-
     if ( field.value.length == 0 )
     {
         setInnerHTML( field.name + "Info", message );
@@ -139,7 +138,8 @@
         var side = byId( "side" ).value;
         saveExpression( side, description, expression, textualDescription );
         disable( 'periodTypeName' );
-    } else if ( type == "error" )
+    } 
+    else if ( type == "error" )
     {
         byId( "textualExpression" ).innerHTML = message;
     }
@@ -152,7 +152,8 @@
         byId( "leftSideDescription" ).value = description;
         byId( "leftSideExpression" ).value = expression;
         byId( "leftSideTextualExpression" ).value = textualDescription;
-    } else if ( side == "right" )
+    } 
+    else if ( side == "right" )
     {
         byId( "rightSideDescription" ).value = description;
         byId( "rightSideExpression" ).value = expression;

=== added file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expressionBuilder.js'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expressionBuilder.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/javascript/expressionBuilder.js	2012-07-26 11:14:41 +0000
@@ -0,0 +1,149 @@
+var left = true;
+var dialog = null;
+
+jQuery(document).ready(function() 
+{
+	dialog = jQuery( "#expression-container" ).dialog({
+		modal: true,
+		autoOpen: false,
+		minWidth: 840,
+		minHeight: 560,
+		width: 840,
+		height: 560,
+		title: "Expression"
+	});
+		
+	jQuery( "#periodTypeName" ).change(function(){
+		getOperandsPage();
+	});
+	
+	getConstantsPage();
+	getOperandsPage();
+});
+
+function editLeftExpression()
+{		
+	left = true;
+	
+	$( '#expression' ).val( $( '#leftSideExpression' ).val() );
+	$( '#description' ).val( $( '#leftSideDescription' ).val() );
+	$( '#formulaText' ).text( $( '#leftSideTextualExpression' ).val() );
+	$( '#nullIfBlank' ).attr( 'checked', ( $( '#leftSideNullIfBlank' ).val() == 'true' || $( '#leftSideNullIfBlank' ).val() == '' ) );
+	
+	dialog.dialog("open");
+}
+
+function editRightExpression()
+{
+	left = false;
+	
+	$( '#expression' ).val( $( '#rightSideExpression' ).val() );
+	$( '#description' ).val( $( '#rightSideDescription' ).val() );
+	$( '#formulaText' ).text( $( '#rightSideTextualExpression' ).val() );
+	$( '#nullIfBlank' ).attr( 'checked', ( $( '#rightSideNullIfBlank' ).val() == 'true' || $( '#rightSideNullIfBlank' ).val() == '' ) );
+	
+	dialog.dialog("open");
+}
+
+function getConstantsPage()
+{
+	var target = jQuery( "#expression-container select[id=constantId]" );
+	target.children().remove();
+	
+	jQuery.postJSON( '../dhis-web-commons-ajax-json/getConstants.action', {}, function( json ) 
+	{
+		if ( json.constants.length == 0 )
+		{
+			setInnerHTML( 'constantHeader', "<i style='color:red'>"+i18n_no_constant_to_select+"</i>" );
+			return;
+		}
+		
+		jQuery.each( json.constants, function(i, item) {
+			target.append( '<option value="[C'+item.constantId+']">'+item.constantName+'</option>' );
+		});
+	});
+}
+
+function getOperandsPage()
+{
+	var key = getFieldValue( "expression-container input[id=filter]" );
+	
+	var periodType = getFieldValue( "periodTypeName" );
+
+	dataDictionary.loadOperands( "#expression-container select[id=dataElementId]", {usePaging: true, key: key, periodType: periodType} );	
+}
+
+function clearSearchText()
+{
+	jQuery( "#expression-container input[id=filter]").val("");
+	getOperandsPage();
+}
+
+function getExpressionText()
+{
+	if( hasText('expression') )
+	{
+		jQuery.postJSON( '../dhis-web-commons-ajax-json/getExpressionText.action', 
+		{
+			expression: $( '#expression' ).val()
+		}, 
+		function( json )
+		{
+			if( json.response == 'success' || json.response == 'error' )
+			{
+				jQuery( "#formulaText").html( json.message );
+			}
+			else {
+				jQuery( "#formulaText").html( '' );
+			}
+		});
+	}
+	else
+	{
+		jQuery( "#formulaText").html( '' );
+	}
+}
+
+function insertText( inputAreaName, inputText )
+{
+	insertTextCommon( inputAreaName, inputText );
+	
+	getExpressionText();
+}
+
+function insertExpression()
+{
+	var expression = $( '#expression' ).val();
+	var description = $( '#description' ).val();
+	
+	jQuery.postJSON( '../dhis-web-commons-ajax-json/getExpressionText.action', 
+	{
+		expression: expression
+	},
+	function( json )
+	{
+		if ( json.response == 'error' )
+		{
+			markInvalid( 'expression-container textarea[id=expression]' , json.message );
+		}
+		else 
+		{								
+			if ( left )
+			{
+				$( '#leftSideExpression' ).val( expression );
+				$( '#leftSideDescription' ).val( description );					
+				$( '#leftSideTextualExpression' ).val( $( '#formulaText' ).text() );
+				$( '#leftSideNullIfBlank' ).val( $( '#nullIfBlank' ).is( ':checked' ) );
+			}
+			else
+			{
+				$( '#rightSideExpression' ).val( expression );
+				$( '#rightSideDescription' ).val( description );					
+				$( '#rightSideTextualExpression' ).val( $( '#formulaText' ).text() );
+				$( '#rightSideNullIfBlank' ).val( $( '#nullIfBlank' ).is( ':checked' ) );								
+			}
+			
+			dialog.dialog( "close" );
+		}
+	});
+}

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleForm.vm'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleForm.vm	2011-09-26 09:31:56 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/webapp/dhis-web-validationrule/updateValidationRuleForm.vm	2012-07-26 11:14:41 +0000
@@ -52,16 +52,20 @@
 			<input type="button" value="$i18n.getString( 'edit_left_side' )" style="width:10em" onclick="editLeftExpression();">
 				<input type="hidden" id="leftSideDescription" name="leftSideDescription" value="$!validationRule.leftSide.description">
 				<input type="hidden" id="leftSideExpression" name="leftSideExpression" value="$!validationRule.leftSide.expression">
-				<input type="hidden" id="leftSideTextualExpression" name="leftSideTextualExpression" value="$!leftSideTextualExpression"">	
-				<input type="button" value="$i18n.getString( 'edit_right_side' )" style="width:10em" onclick="editRightExpression();"></td>
+				<input type="hidden" id="leftSideTextualExpression" name="leftSideTextualExpression" value="$!leftSideTextualExpression">
+				<input type="hidden" id="leftSideNullIfBlank" name="leftSideNullIfBlank" value="$!validationRule.leftSide.zeroForBlank">
+				
+				<input type="button" value="$i18n.getString( 'edit_right_side' )" style="width:10em" onclick="editRightExpression();">
 				<input type="hidden" id="rightSideDescription" name="rightSideDescription" value="$!validationRule.rightSide.description">
 				<input type="hidden" id="rightSideExpression" name="rightSideExpression" value="$!validationRule.rightSide.expression">
 				<input type="hidden" id="rightSideTextualExpression" name="rightSideTextualExpression" value="$!rightSideTextualExpression">
+				<input type="hidden" id="rightSideNullIfBlank" name="rightSideNullIfBlank" value="$!validationRule.rightSide.zeroForBlank">
+		</td>
 	</tr>
 	<tr>
 		<td></td>
-		<td><input type="submit" value="$i18n.getString( 'save' )" style="width:10em"><input 
-				type="button" value="$i18n.getString( 'cancel' )" id="cancel" name="cancel" onclick="window.location.href='validationRule.action'" style="width:10em"></td>		
+		<td><input type="submit" value="$i18n.getString( 'save' )" style="width:10em">
+		    <input type="button" value="$i18n.getString( 'cancel' )" id="cancel" name="cancel" onclick="window.location.href='validationRule.action'" style="width:10em"></td>		
 	</tr>
 </table>
 </form>