← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 7702: Reimplemented std dev and min-max data analysis. Improves performance.

 

------------------------------------------------------------
revno: 7702
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2012-07-25 15:18:48 +0200
message:
  Reimplemented std dev and min-max data analysis. Improves performance.
removed:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/validation/
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/validation/MinMaxValuesGenerationService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxValueMap.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/validation/
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/validation/DefaultMinMaxValuesGenerationService.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/RemoveMinMaxValueAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidationForm.js
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/MinMaxDataAnalysisService.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/DataAnalysisStoreTest.java
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/MinMaxDataElementBatchHandler.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/filter/DataElementTypeFilter.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/DefaultMinMaxDataElementService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/hibernate/HibernateMinMaxDataElementStore.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/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisServiceTest.java
  dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisServiceTest.java
  dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/objectmapper/DeflatedDataValueNameMinMaxRowMapper.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/ValidationAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/utils/FormUtils.java
  dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GenerateMinMaxValuesAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GetMinMaxValidationParamsAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidation.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/minMaxValidation.vm
  dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java
  dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml


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

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisService.java	2011-02-10 23:09:13 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisService.java	2012-07-25 13:18:48 +0000
@@ -36,15 +36,13 @@
 
 /**
  * @author Dag Haavi Finstad
- * @version $Id: StdDevOutlierAnalysisService.java 882 2009-05-14 23:09:31Z
- *          daghf $
  */
 public interface DataAnalysisService
 {
     String ID = DataAnalysisService.class.getName();
 
-    int MAX_OUTLIERS = 500;
+    final int MAX_OUTLIERS = 500;
     
-    Collection<DeflatedDataValue> analyse( OrganisationUnit organisationUnit, Collection<DataElement> dataElements,
+    Collection<DeflatedDataValue> analyse( Collection<OrganisationUnit> organisationUnits, Collection<DataElement> dataElements,
         Collection<Period> periods, Double stdDevFactor );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java	2012-07-20 07:29:46 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/DataAnalysisStore.java	2012-07-25 13:18:48 +0000
@@ -28,6 +28,8 @@
  */
 
 import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
 
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
@@ -40,6 +42,8 @@
  */
 public interface DataAnalysisStore
 {
+    final String ID = DataAnalysisStore.class.getName();
+    
     /**
      * Calculates the standard deviation of the DataValues registered for the given
      * data element, category option combo and organisation unit.
@@ -49,7 +53,7 @@
      * @param organisationUnit the OrganisationUnit.
      * @return the standard deviation.
      */
-    Double getStandardDeviation( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, OrganisationUnit organisationUnit );
+    Map<Integer, Double> getStandardDeviation( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, Set<Integer> organisationUnits );
     
     /**
      * Calculates the average of the DataValues registered for the given
@@ -60,7 +64,10 @@
      * @param organisationUnit the OrganisationUnit.
      * @return the average.
      */
-    Double getAverage( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, OrganisationUnit organisationUnit );
+    Map<Integer, Double> getAverage( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, Set<Integer> organisationUnits );
+    
+    Collection<DeflatedDataValue> getMinMaxViolations( Collection<DataElement> dataElements, Collection<DataElementCategoryOptionCombo> categoryOptionCombos,
+        Collection<Period> periods, Collection<OrganisationUnit> organisationUnits, int limit );
     
     /**
      * Returns a collection of DeflatedDataValues for the given input.
@@ -74,7 +81,7 @@
      * @return
      */
     Collection<DeflatedDataValue> getDeflatedDataValues( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo,
-        Collection<Period> periods, OrganisationUnit organisationUnit, int lowerBound, int upperBound );
+        Collection<Period> periods, Map<Integer, Integer> lowerBoundMap, Map<Integer, Integer> upperBoundMap );
     
     /**
      * Returns a collection of DeflatedDataValues which are marked for followup.

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/MinMaxDataAnalysisService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/MinMaxDataAnalysisService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataanalysis/MinMaxDataAnalysisService.java	2012-07-25 13:18:48 +0000
@@ -0,0 +1,13 @@
+package org.hisp.dhis.dataanalysis;
+
+import java.util.Collection;
+
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+
+public interface MinMaxDataAnalysisService
+    extends DataAnalysisService
+{    
+    void generateMinMaxValues( Collection<OrganisationUnit> organisationUnits,
+        Collection<DataElement> dataElements, Double stdDevFactor );
+}

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryService.java	2012-07-25 13:18:48 +0000
@@ -27,11 +27,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import java.util.Collection;
+
 import org.hisp.dhis.concept.Concept;
 import org.hisp.dhis.hierarchy.HierarchyViolationException;
 
-import java.util.Collection;
-
 /**
  * @author Abyot Asalefew
  * @version $Id$
@@ -419,7 +419,7 @@
      * @return a collection of all DataElementCategories, or an empty collection.
      */
     Collection<DataElementCategory> getDataElementCategorysByConcept( Concept concept );
-
+    
     int getDataElementCategoryCount();
 
     int getDataElementCategoryCountByName( String name );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementService.java	2012-07-01 07:12:58 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementService.java	2012-07-25 13:18:48 +0000
@@ -62,4 +62,6 @@
     void removeMinMaxDataElements( DataElement dataElement );
     
     void removeMinMaxDataElements( DataElementCategoryOptionCombo optionCombo );
+    
+    void removeMinMaxDataElements( Collection<DataElement> dataElements, Collection<OrganisationUnit> organisationUnits );
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementStore.java	2012-07-01 07:12:58 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/MinMaxDataElementStore.java	2012-07-25 13:18:48 +0000
@@ -54,4 +54,6 @@
     void delete( DataElement dataElement );
     
     void delete( DataElementCategoryOptionCombo optionCombo );
+    
+    void delete( Collection<DataElement> dataElements, Collection<OrganisationUnit> organisationUnits );
 }

=== removed directory 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/validation'
=== removed file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/validation/MinMaxValuesGenerationService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/validation/MinMaxValuesGenerationService.java	2010-04-29 04:33:47 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/minmax/validation/MinMaxValuesGenerationService.java	1970-01-01 00:00:00 +0000
@@ -1,51 +0,0 @@
-package org.hisp.dhis.minmax.validation;
-
-/*
- * Copyright (c) 2004-2009, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- * * Neither the name of the HISP project nor the names of its contributors may
- *   be used to endorse or promote products derived from this software without
- *   specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import java.util.Collection;
-
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.datavalue.DeflatedDataValue;
-import org.hisp.dhis.minmax.MinMaxDataElement;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.period.Period;
-
-/**
- * @author Chau Thu Tran
- * @version $Id$
- */
-public interface MinMaxValuesGenerationService
-{
-    String ID = MinMaxValuesGenerationService.class.getName();
-
-    Collection<MinMaxDataElement> getMinMaxValues( OrganisationUnit organisationUnit,
-        Collection<DataElement> dataElements, Double stdDevFactor );
-
-    Collection<DeflatedDataValue> findOutliers( OrganisationUnit organisationUnit, Collection<Period> periods,
-        Collection<MinMaxDataElement> minMaxDataElements );
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java	2010-04-08 11:10:09 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/FollowupAnalysisService.java	2012-07-25 13:18:48 +0000
@@ -40,6 +40,10 @@
 public class FollowupAnalysisService
     implements DataAnalysisService
 {
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
     private DataAnalysisStore dataAnalysisStore;
     
     public void setDataAnalysisStore( DataAnalysisStore dataAnalysisStore )
@@ -47,8 +51,12 @@
         this.dataAnalysisStore = dataAnalysisStore;
     }
 
+    // -------------------------------------------------------------------------
+    // DataAnalysisService implementation
+    // -------------------------------------------------------------------------
+
     @Override
-    public Collection<DeflatedDataValue> analyse( OrganisationUnit organisationUnit,
+    public Collection<DeflatedDataValue> analyse( Collection<OrganisationUnit> organisationUnits,
         Collection<DataElement> dataElements, Collection<Period> periods, Double stdDevFactor )
     {
         return dataAnalysisStore.getDataValuesMarkedForFollowup();

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java	2011-02-10 23:09:13 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisService.java	2012-07-25 13:18:48 +0000
@@ -27,116 +27,130 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
+import org.amplecode.quick.BatchHandler;
+import org.amplecode.quick.BatchHandlerFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.datavalue.DeflatedDataValue;
+import org.hisp.dhis.jdbc.batchhandler.MinMaxDataElementBatchHandler;
 import org.hisp.dhis.minmax.MinMaxDataElement;
 import org.hisp.dhis.minmax.MinMaxDataElementService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.Period;
+import org.hisp.dhis.system.filter.DataElementTypeFilter;
+import org.hisp.dhis.system.util.ConversionUtils;
+import org.hisp.dhis.system.util.Filter;
+import org.hisp.dhis.system.util.FilterUtils;
+import org.hisp.dhis.system.util.MathUtils;
 
 /**
- * @author Dag Haavi Finstad
  * @author Lars Helge Overland
  */
 public class MinMaxOutlierAnalysisService
-    implements DataAnalysisService
+    implements MinMaxDataAnalysisService
 {
+    private static final Log log = LogFactory.getLog( MinMaxOutlierAnalysisService.class );
+    
+    private static final Filter<DataElement> DATALEMENT_INT_FILTER = new DataElementTypeFilter( DataElement.VALUE_TYPE_INT );
+    
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
+    
+    private DataAnalysisStore dataAnalysisStore;
 
+    public void setDataAnalysisStore( DataAnalysisStore dataAnalysisStore )
+    {
+        this.dataAnalysisStore = dataAnalysisStore;
+    }
+    
     private MinMaxDataElementService minMaxDataElementService;
 
     public void setMinMaxDataElementService( MinMaxDataElementService minMaxDataElementService )
     {
         this.minMaxDataElementService = minMaxDataElementService;
     }
-
-    private OrganisationUnitService organisationUnitService;
-    
-    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
-    {
-        this.organisationUnitService = organisationUnitService;
-    }
-    
-    private DataAnalysisStore dataAnalysisStore;
-
-    public void setDataAnalysisStore( DataAnalysisStore dataAnalysisStore )
-    {
-        this.dataAnalysisStore = dataAnalysisStore;
-    }
-
-    // -------------------------------------------------------------------------
-    // MinMaxOutlierAnalysisService implementation
-    // -------------------------------------------------------------------------
-
-    public final Collection<DeflatedDataValue> analyse( OrganisationUnit organisationUnit,
+    
+    private BatchHandlerFactory batchHandlerFactory;
+
+    public void setBatchHandlerFactory( BatchHandlerFactory batchHandlerFactory )
+    {
+        this.batchHandlerFactory = batchHandlerFactory;
+    }
+
+    // -------------------------------------------------------------------------
+    // DataAnalysisService implementation
+    // -------------------------------------------------------------------------
+
+    public Collection<DeflatedDataValue> analyse( Collection<OrganisationUnit> organisationUnits,
         Collection<DataElement> dataElements, Collection<Period> periods, Double stdDevFactor )
     {
-        Collection<OrganisationUnit> units = organisationUnitService.getOrganisationUnitWithChildren( organisationUnit.getId() );
-        
-        Collection<DeflatedDataValue> outlierCollection = new ArrayList<DeflatedDataValue>();
-        
-        loop : for ( OrganisationUnit unit : units )
-        {
-            MinMaxValueMap map = getMinMaxValueMap( minMaxDataElementService.getMinMaxDataElements( unit, dataElements ) );
-            
-            for ( DataElement dataElement : dataElements )
+        FilterUtils.filter( dataElements, DATALEMENT_INT_FILTER );
+        
+        Set<DataElementCategoryOptionCombo> categoryOptionCombos = new HashSet<DataElementCategoryOptionCombo>();
+        
+        for ( DataElement dataElement : dataElements )
+        {
+            categoryOptionCombos.addAll( dataElement.getCategoryCombo().getOptionCombos() );
+        }
+
+        log.info( "Starting min-max analysis, no of data elements: " + dataElements.size() + ", no of org units: " + organisationUnits.size() );
+        
+        return dataAnalysisStore.getMinMaxViolations( dataElements, categoryOptionCombos, periods, organisationUnits, MAX_OUTLIERS );
+    }
+    
+    public void generateMinMaxValues( Collection<OrganisationUnit> organisationUnits,
+        Collection<DataElement> dataElements, Double stdDevFactor )
+    {
+        log.info( "Starting min-max value generation, no of data elements: " + dataElements.size() + ", no of org units: " + organisationUnits.size() );
+
+        Set<Integer> orgUnitIds = new HashSet<Integer>( ConversionUtils.getIdentifiers( OrganisationUnit.class, organisationUnits ) ); 
+
+        minMaxDataElementService.removeMinMaxDataElements( dataElements, organisationUnits );
+
+        log.info( "Deleted existing min-max values" );
+
+        BatchHandler<MinMaxDataElement> batchHandler = batchHandlerFactory.createBatchHandler( MinMaxDataElementBatchHandler.class ).init();
+        
+        for ( DataElement dataElement : dataElements )
+        {
+            if ( dataElement.getType().equals( DataElement.VALUE_TYPE_INT ) )
             {
-                if ( dataElement.getType().equals( DataElement.VALUE_TYPE_INT ) )
-                {                    
-                    Collection<DataElementCategoryOptionCombo> categoryOptionCombos = dataElement.getCategoryCombo().getOptionCombos();
-                    
-                    for ( DataElementCategoryOptionCombo categoryOptionCombo : categoryOptionCombos )
+                Collection<DataElementCategoryOptionCombo> categoryOptionCombos = dataElement.getCategoryCombo().getOptionCombos();
+
+                for ( DataElementCategoryOptionCombo categoryOptionCombo : categoryOptionCombos )
+                {
+                    Map<Integer, Double> standardDeviations = dataAnalysisStore.getStandardDeviation( dataElement, categoryOptionCombo, orgUnitIds );
+                    
+                    Map<Integer, Double> averages = dataAnalysisStore.getAverage( dataElement, categoryOptionCombo, standardDeviations.keySet() );
+                    
+                    for ( Integer unit : averages.keySet() )
                     {
-                        outlierCollection.addAll( findOutliers( unit, dataElement, categoryOptionCombo, periods, map ) );
+                        Double stdDev = standardDeviations.get( unit );
+                        Double avg = averages.get( unit );
                         
-                        if ( outlierCollection.size() > MAX_OUTLIERS )
+                        if ( stdDev != null && avg != null )
                         {
-                            break loop;
+                            int min = (int) MathUtils.getLowBound( stdDev, stdDevFactor, avg );
+                            int max = (int) MathUtils.getHighBound( stdDev, stdDevFactor, avg );
+                            
+                            OrganisationUnit source = new OrganisationUnit();
+                            source.setId( unit );
+                            
+                            batchHandler.addObject( new MinMaxDataElement( source, dataElement, categoryOptionCombo, min, max, true ) );
                         }
-                    }
+                    }                        
                 }
             }
         }
-
-        return outlierCollection;
-        
-        //TODO improve performance by joining datavalue with minmaxdataelement
-    }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    private Collection<DeflatedDataValue> findOutliers( OrganisationUnit organisationUnit, DataElement dataElement, 
-        DataElementCategoryOptionCombo categoryOptionCombo, Collection<Period> periods, MinMaxValueMap map )
-    {
-        MinMaxDataElement minMaxDataElement = map.get( organisationUnit, dataElement, categoryOptionCombo );
-
-        if ( minMaxDataElement != null )
-        {
-            return dataAnalysisStore.getDeflatedDataValues( dataElement, categoryOptionCombo, periods, 
-                organisationUnit, minMaxDataElement.getMin(), minMaxDataElement.getMax() );
-        }
-        
-        return new ArrayList<DeflatedDataValue>();
-    }
-    
-    private MinMaxValueMap getMinMaxValueMap( Collection<MinMaxDataElement> minMaxDataElements )
-    {
-        MinMaxValueMap map = new MinMaxValueMap();
-        
-        for ( MinMaxDataElement element : minMaxDataElements )
-        {
-            map.put( element );
-        }
-        
-        return map;
+        
+        batchHandler.flush();
     }
 }

=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxValueMap.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxValueMap.java	2011-05-05 21:14:56 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/MinMaxValueMap.java	1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-package org.hisp.dhis.dataanalysis;
-
-/*
- * Copyright (c) 2004-${year}, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- * * Neither the name of the HISP project nor the names of its contributors may
- *   be used to endorse or promote products derived from this software without
- *   specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import java.util.HashMap;
-
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
-import org.hisp.dhis.minmax.MinMaxDataElement;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-
-/**
- * @author Lars Helge Overland
- */
-public class MinMaxValueMap
-    extends HashMap<String, MinMaxDataElement>
-{
-    /**
-     * Determines if a de-serialized file is compatible with this class.
-     */
-    private static final long serialVersionUID = -6046170950071436264L;
-
-    private static final String SEP = "-";
-    
-    public void put( MinMaxDataElement element )
-    {
-        final String key = element.getSource().getId() + SEP + element.getDataElement().getId() + SEP + element.getOptionCombo().getId();
-        
-        super.put( key, element );
-    }
-    
-    public MinMaxDataElement get( OrganisationUnit source, DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo )
-    {
-        return super.get( source.getId() + SEP + dataElement.getId() + SEP + categoryOptionCombo.getId() );
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisService.java	2011-06-12 08:42:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisService.java	2012-07-25 13:18:48 +0000
@@ -27,26 +27,31 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.system.util.MathUtils.isEqual;
-
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
-import org.hisp.dhis.common.AggregatedValue;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.Period;
+import org.hisp.dhis.system.util.ConversionUtils;
+import org.hisp.dhis.system.util.MathUtils;
 
 /**
- * @author Dag Haavi Finstad
  * @author Lars Helge Overland
  */
 public class StdDevOutlierAnalysisService
     implements DataAnalysisService
 {
+    private static final Log log = LogFactory.getLog( StdDevOutlierAnalysisService.class );
+    
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
@@ -58,23 +63,17 @@
         this.dataAnalysisStore = dataAnalysisStore;
     }
 
-    private OrganisationUnitService organisationUnitService;
-
-    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
-    {
-        this.organisationUnitService = organisationUnitService;
-    }
-
-    // -------------------------------------------------------------------------
-    // OutlierAnalysisService implementation
-    // -------------------------------------------------------------------------
-
-    public final Collection<DeflatedDataValue> analyse( OrganisationUnit organisationUnit,
+    // -------------------------------------------------------------------------
+    // DataAnalysisService implementation
+    // -------------------------------------------------------------------------
+
+    public final Collection<DeflatedDataValue> analyse( Collection<OrganisationUnit> organisationUnits,
         Collection<DataElement> dataElements, Collection<Period> periods, Double stdDevFactor )
     {
-        Collection<OrganisationUnit> units = organisationUnitService.getOrganisationUnitWithChildren( organisationUnit
-            .getId() );
+        Set<Integer> units = new HashSet<Integer>( ConversionUtils.getIdentifiers( OrganisationUnit.class, organisationUnits ) );
 
+        log.info( "Starting std dev analysis, no of org units: " + organisationUnits.size() + ", factor: " + stdDevFactor );
+        
         Collection<DeflatedDataValue> outlierCollection = new ArrayList<DeflatedDataValue>();
 
         loop : for ( DataElement dataElement : dataElements )
@@ -88,43 +87,36 @@
 
                 for ( DataElementCategoryOptionCombo categoryOptionCombo : categoryOptionCombos )
                 {
-                    for ( OrganisationUnit unit : units )
+                    Map<Integer, Double> standardDeviations = dataAnalysisStore.getStandardDeviation( dataElement, categoryOptionCombo, units );
+                    
+                    Map<Integer, Double> averages = dataAnalysisStore.getAverage( dataElement, categoryOptionCombo, standardDeviations.keySet() );
+                    
+                    Map<Integer, Integer> lowBoundMap = new HashMap<Integer, Integer>();
+                    Map<Integer, Integer> highBoundMap = new HashMap<Integer, Integer>();
+                    
+                    for ( Integer unit : averages.keySet() )
                     {
-                        outlierCollection.addAll( findOutliers( unit, dataElement, categoryOptionCombo, periods,
-                            stdDevFactor ) );
+                        Double stdDev = standardDeviations.get( unit );
+                        Double avg = averages.get( unit );
                         
-                        if ( outlierCollection.size() > MAX_OUTLIERS )
+                        if ( stdDev != null && avg != null )
                         {
-                            break loop;
+                            lowBoundMap.put( unit, (int) MathUtils.getLowBound( stdDev, stdDevFactor, avg ) );
+                            highBoundMap.put( unit, (int) MathUtils.getHighBound( stdDev, stdDevFactor, avg ) );                            
                         }
                     }
+
+                    outlierCollection.addAll( dataAnalysisStore.getDeflatedDataValues( dataElement, categoryOptionCombo, periods,
+                        lowBoundMap, highBoundMap ) );
+                    
+                    if ( outlierCollection.size() > MAX_OUTLIERS )
+                    {
+                        break loop;
+                    }
                 }
             }
         }
 
         return outlierCollection;
     }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    private Collection<DeflatedDataValue> findOutliers( OrganisationUnit organisationUnit, DataElement dataElement,
-        DataElementCategoryOptionCombo categoryOptionCombo, Collection<Period> periods, Double stdDevFactor )
-    {
-        Double stdDev = dataAnalysisStore.getStandardDeviation( dataElement, categoryOptionCombo, organisationUnit );
-
-        if ( !isEqual( stdDev, AggregatedValue.ZERO ) ) // No values found or no outliers exist when 0.0
-        {
-            Double avg = dataAnalysisStore.getAverage( dataElement, categoryOptionCombo, organisationUnit );
-
-            double deviation = stdDev * stdDevFactor;
-            Double lowerBound = avg - deviation;
-            Double upperBound = avg + deviation;
-            return dataAnalysisStore.getDeflatedDataValues( dataElement, categoryOptionCombo, periods,
-                organisationUnit, lowerBound.intValue(), upperBound.intValue() );
-        }
-
-        return new ArrayList<DeflatedDataValue>();
-    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java	2012-07-23 12:33:49 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataanalysis/jdbc/JdbcDataAnalysisStore.java	2012-07-25 13:18:48 +0000
@@ -27,13 +27,17 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.sql.ResultSet;
-import java.sql.SQLException;
+import static org.hisp.dhis.common.AggregatedValue.ZERO;
+import static org.hisp.dhis.system.util.ConversionUtils.getIdentifiers;
+import static org.hisp.dhis.system.util.MathUtils.isEqual;
+import static org.hisp.dhis.system.util.TextUtils.getCommaDelimitedString;
+
 import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
-import org.amplecode.quick.StatementHolder;
-import org.amplecode.quick.StatementManager;
-import org.amplecode.quick.mapper.ObjectMapper;
 import org.hisp.dhis.dataanalysis.DataAnalysisStore;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
@@ -45,6 +49,7 @@
 import org.hisp.dhis.system.util.ConversionUtils;
 import org.hisp.dhis.system.util.TextUtils;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
 
 /**
  * @author Lars Helge Overland
@@ -56,13 +61,6 @@
     // Dependencies
     // -------------------------------------------------------------------------
 
-    private StatementManager statementManager;
-
-    public void setStatementManager( StatementManager statementManager )
-    {
-        this.statementManager = statementManager;
-    }
-
     private StatementBuilder statementBuilder;
 
     public void setStatementBuilder( StatementBuilder statementBuilder )
@@ -81,63 +79,156 @@
     // OutlierAnalysisStore implementation
     // -------------------------------------------------------------------------
 
-    public Double getStandardDeviation( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, OrganisationUnit organisationUnit )
-    {
-         final String sql = statementBuilder.getStandardDeviation( dataElement.getId(), categoryOptionCombo.getId(), organisationUnit.getId() );
-        
-        return statementManager.getHolder().queryForDouble( sql );
-    }
-    
-    public Double getAverage( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, OrganisationUnit organisationUnit )
-    {
-        final String sql =  statementBuilder.getAverage( dataElement.getId(), categoryOptionCombo.getId(), organisationUnit.getId() );
-           
-        return statementManager.getHolder().queryForDouble( sql );
+    public Map<Integer, Double> getStandardDeviation( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, Set<Integer> organisationUnits )
+    {
+        final String sql = 
+            "select ou.organisationunitid, " +
+              "(select stddev_pop( cast( value as " + statementBuilder.getDoubleColumnType() + " ) ) " +
+              "from datavalue where dataelementid = " + dataElement.getId() + " " +
+              "and categoryoptioncomboid = " + categoryOptionCombo.getId() + " " +
+              "and sourceid = ou.organisationunitid) as deviation " +
+            "from organisationunit ou " +
+            "where ou.organisationunitid in (" + getCommaDelimitedString( organisationUnits ) + ")";
+        
+        Map<Integer, Double> map = new HashMap<Integer, Double>();
+        
+        SqlRowSet rowSet = jdbcTemplate.queryForRowSet( sql );
+        
+        while ( rowSet.next() )
+        {
+            Object stdDev = rowSet.getObject( "deviation" );
+            
+            if ( stdDev != null && !isEqual( (Double) stdDev, ZERO ) )
+            {
+                map.put( rowSet.getInt( "organisationunitid" ), (Double) stdDev );
+            }
+        }
+        
+        return map;
+    }
+    
+    public Map<Integer, Double> getAverage( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo, Set<Integer> organisationUnits )
+    {
+        final String sql = 
+            "select ou.organisationunitid, " +
+                "(select avg( cast( value as " + statementBuilder.getDoubleColumnType() + " ) ) " +
+                "from datavalue where dataelementid = " + dataElement.getId() + " " +
+                "and categoryoptioncomboid = " + categoryOptionCombo.getId() + " " +
+                "and sourceid = ou.organisationunitid) as average " +
+            "from organisationunit ou " +
+            "where ou.organisationunitid in (" + getCommaDelimitedString( organisationUnits ) + ")";
+        
+        Map<Integer, Double> map = new HashMap<Integer, Double>();
+        
+        SqlRowSet rowSet = jdbcTemplate.queryForRowSet( sql );
+        
+        while ( rowSet.next() )
+        {
+            Object avg = rowSet.getObject( "average" );
+            
+            if ( avg != null )
+            {
+                map.put( rowSet.getInt( "organisationunitid" ), (Double) avg );
+            }
+        }
+        
+        return map;        
+    }
+    
+    public Collection<DeflatedDataValue> getMinMaxViolations( Collection<DataElement> dataElements, Collection<DataElementCategoryOptionCombo> categoryOptionCombos,
+        Collection<Period> periods, Collection<OrganisationUnit> organisationUnits, int limit )
+    {
+        String dataElementIds = getCommaDelimitedString( getIdentifiers( DataElement.class, dataElements ) );
+        String organisationUnitIds = getCommaDelimitedString( getIdentifiers( OrganisationUnit.class, organisationUnits ) );
+        String periodIds = getCommaDelimitedString( getIdentifiers( Period.class, periods ) );
+        String categoryOptionComboIds = getCommaDelimitedString( getIdentifiers( DataElementCategoryOptionCombo.class, categoryOptionCombos ) );
+        
+        Map<Integer, String> optionComboMap = getCategoryOptionComboMap( categoryOptionCombos );
+        
+        //TODO persist name on category option combo and use join to improve performance
+        
+        String sql = 
+            "select dv.dataelementid, dv.periodid, dv.sourceid, dv.categoryoptioncomboid, dv.value, dv.storedby, dv.lastupdated, " +
+            "dv.comment, dv.followup, ou.name as sourcename, de.name as dataelementname, pt.name as periodtypename, pe.startdate, pe.enddate, mm.minvalue, mm.maxvalue " + 
+            "from datavalue dv " +
+            "join minmaxdataelement mm on ( dv.dataelementid = mm.dataelementid and dv.categoryoptioncomboid = mm.categoryoptioncomboid and dv.sourceid = mm.sourceid ) " +
+            "join dataelement de on dv.dataelementid = de.dataelementid " +
+            "join period pe on dv.periodid = pe.periodid " +
+            "join periodtype pt on pe.periodtypeid = pt.periodtypeid " +
+            "join organisationunit ou on dv.sourceid = ou.organisationunitid " +
+            "where dv.dataelementid in (" + dataElementIds + ") " +
+            "and dv.categoryoptioncomboid in (" + categoryOptionComboIds + ") " +
+            "and dv.periodid in (" + periodIds + ") " + 
+            "and dv.sourceid in (" + organisationUnitIds + ") and ( " +
+                "cast( dv.value as " + statementBuilder.getDoubleColumnType() + " ) < mm.minvalue " +
+                "or cast( dv.value as " + statementBuilder.getDoubleColumnType() + " ) > mm.maxvalue )" +
+            statementBuilder.limitRecord( 0, limit );
+        
+        return jdbcTemplate.query( sql, new DeflatedDataValueNameMinMaxRowMapper( null, null, optionComboMap ) );
     }
     
     public Collection<DeflatedDataValue> getDeflatedDataValues( DataElement dataElement, DataElementCategoryOptionCombo categoryOptionCombo,
-        Collection<Period> periods, OrganisationUnit organisationUnit, int lowerBound, int upperBound )
+        Collection<Period> periods, Map<Integer, Integer> lowerBoundMap, Map<Integer, Integer> upperBoundMap )
     {
-        final StatementHolder holder = statementManager.getHolder();
-        
-        final ObjectMapper<DeflatedDataValue> mapper = new ObjectMapper<DeflatedDataValue>();
-        
-        final String periodIds = TextUtils.getCommaDelimitedString( ConversionUtils.getIdentifiers( Period.class, periods ) );
-        
-        final String sql = statementBuilder.getDeflatedDataValues( dataElement.getId(), dataElement.getName(), categoryOptionCombo.getId(),
-    		periodIds, organisationUnit.getId(), organisationUnit.getName(), lowerBound, upperBound );
-        
-        try
-        {            
-            final ResultSet resultSet = holder.getStatement().executeQuery( sql );
-            
-            return mapper.getCollection( resultSet, new DeflatedDataValueNameMinMaxRowMapper() );
-        }
-        catch ( SQLException ex )
-        {
-            throw new RuntimeException( "Failed to get deflated data values", ex );
-        }
-        finally
-        {
-            holder.close();
-        }
+        if ( lowerBoundMap == null || lowerBoundMap.isEmpty() )
+        {
+            return new HashSet<DeflatedDataValue>();
+        }
+        
+        String periodIds = TextUtils.getCommaDelimitedString( ConversionUtils.getIdentifiers( Period.class, periods ) );
+        
+        String sql = 
+            "select dv.dataelementid, dv.periodid, dv.sourceid, dv.categoryoptioncomboid, dv.value, dv.storedby, dv.lastupdated, " +
+            "dv.comment, dv.followup, ou.name as sourcename, " +
+            "'" + dataElement.getName() + "' as dataelementname, pt.name as periodtypename, pe.startdate, pe.enddate, " + 
+            "'" + categoryOptionCombo.getName() + "' as categoryoptioncomboname " +
+            "from datavalue dv " +
+            "join period pe on dv.periodid = pe.periodid " +
+            "join periodtype pt on pe.periodtypeid = pt.periodtypeid " +
+            "join organisationunit ou on dv.sourceid = ou.organisationunitid " +
+            "where dv.dataelementid = " + dataElement.getId() + " " +
+            "and dv.categoryoptioncomboid = " + categoryOptionCombo.getId() + " " +
+            "and dv.periodid in (" + periodIds + ") and ( ";
+        
+        for ( Integer organisationUnit : lowerBoundMap.keySet() )
+        {
+            sql += "( dv.sourceid = " + organisationUnit + " " +
+                "and ( cast( dv.value as " + statementBuilder.getDoubleColumnType() + " ) < " + lowerBoundMap.get( organisationUnit ) + " " +
+                "or cast( dv.value as " + statementBuilder.getDoubleColumnType() + " ) > " + upperBoundMap.get( organisationUnit ) + " ) ) or ";
+        }
+        
+        sql = sql.substring( 0, ( sql.length() - 3 ) ) + " )";
+        
+        return jdbcTemplate.query( sql, new DeflatedDataValueNameMinMaxRowMapper( lowerBoundMap, upperBoundMap, null ) );
     }
     
     public Collection<DeflatedDataValue> getDataValuesMarkedForFollowup()
     {
         final String sql =
-            "SELECT dv.dataelementid, dv.periodid, dv.sourceid, dv.categoryoptioncomboid, dv.value, " +
-            "dv.storedby, dv.lastupdated, dv.comment, dv.followup, mm.minvalue, mm.maxvalue, de.name AS dataelementname, " +
+            "select dv.dataelementid, dv.periodid, dv.sourceid, dv.categoryoptioncomboid, dv.value, " +
+            "dv.storedby, dv.lastupdated, dv.comment, dv.followup, mm.minvalue, mm.maxvalue, de.name as dataelementname, " +
             "pe.startdate, pe.enddate, pt.name AS periodtypename, ou.name AS sourcename, cc.categoryoptioncomboname " +
-            "FROM datavalue AS dv " +
-            "LEFT JOIN minmaxdataelement AS mm ON (dv.sourceid = mm.sourceid AND dv.dataelementid = mm.dataelementid AND dv.categoryoptioncomboid = mm.categoryoptioncomboid) " +
-            "JOIN dataelement AS de ON (dv.dataelementid = de.dataelementid) " +
-            "JOIN period AS pe ON (dv.periodid = pe.periodid) " +
-            "JOIN periodtype AS pt ON (pe.periodtypeid = pt.periodtypeid) " +
-            "LEFT JOIN organisationunit AS ou ON (ou.organisationunitid = dv.sourceid) " +
-            "LEFT JOIN _categoryoptioncomboname AS cc ON (dv.categoryoptioncomboid = cc.categoryoptioncomboid) " +
-            "WHERE dv.followup=true";
+            "from datavalue dv " +
+            "left join minmaxdataelement mm on (dv.sourceid = mm.sourceid and dv.dataelementid = mm.dataelementid and dv.categoryoptioncomboid = mm.categoryoptioncomboid) " +
+            "join dataelement de on dv.dataelementid = de.dataelementid " +
+            "join period pe on dv.periodid = pe.periodid " +
+            "join periodtype pt on pe.periodtypeid = pt.periodtypeid " +
+            "left join organisationunit ou on ou.organisationunitid = dv.sourceid " +
+            "left join _categoryoptioncomboname cc on dv.categoryoptioncomboid = cc.categoryoptioncomboid " +
+            "where dv.followup = true";
         
         return jdbcTemplate.query( sql, new DeflatedDataValueNameMinMaxRowMapper() );        
-    }        
+    }
+    
+    private Map<Integer, String> getCategoryOptionComboMap( Collection<DataElementCategoryOptionCombo> categoryOptionCombos )
+    {
+        Map<Integer, String> map = new HashMap<Integer, String>();
+        
+        for ( DataElementCategoryOptionCombo coc : categoryOptionCombos )
+        {
+            map.put( coc.getId(), coc.getName() );
+        }
+        
+        return map;
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryService.java	2012-07-25 13:18:48 +0000
@@ -501,7 +501,7 @@
 
         updateDataElementCategoryCombo( categoryCombo );
     }
-
+    
     public int getDataElementCategoryCount()
     {
         return dataElementCategoryStore.getCount();

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/DefaultMinMaxDataElementService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/DefaultMinMaxDataElementService.java	2012-07-01 07:12:58 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/DefaultMinMaxDataElementService.java	2012-07-25 13:18:48 +0000
@@ -111,4 +111,9 @@
     {
         minMaxDataElementStore.delete( optionCombo );
     }
+    
+    public void removeMinMaxDataElements( Collection<DataElement> dataElements, Collection<OrganisationUnit> organisationUnits )
+    {
+        minMaxDataElementStore.delete( dataElements, organisationUnits );
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/hibernate/HibernateMinMaxDataElementStore.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/hibernate/HibernateMinMaxDataElementStore.java	2012-07-01 07:12:58 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/hibernate/HibernateMinMaxDataElementStore.java	2012-07-25 13:18:48 +0000
@@ -101,4 +101,13 @@
         
         getQuery( hql ).setEntity( "optionCombo", optionCombo ).executeUpdate();
     }
+    
+    public void delete( Collection<DataElement> dataElements, Collection<OrganisationUnit> organisationUnits )
+    {
+        String hql = "delete from MinMaxDataElement m where m.dataElement in (:dataElements) and m.source in (:organisationUnits)";
+        
+        getQuery( hql ).
+            setParameterList( "dataElements", dataElements ).
+            setParameterList( "organisationUnits", organisationUnits ).executeUpdate();
+    }
 }

=== removed directory 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/validation'
=== removed file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/validation/DefaultMinMaxValuesGenerationService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/validation/DefaultMinMaxValuesGenerationService.java	2011-06-12 08:42:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/minmax/validation/DefaultMinMaxValuesGenerationService.java	1970-01-01 00:00:00 +0000
@@ -1,122 +0,0 @@
-package org.hisp.dhis.minmax.validation;
-
-/*
- * Copyright (c) 2004-2009, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- * * Neither the name of the HISP project nor the names of its contributors may
- *   be used to endorse or promote products derived from this software without
- *   specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import static org.hisp.dhis.system.util.MathUtils.isEqual;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.hisp.dhis.common.AggregatedValue;
-import org.hisp.dhis.dataanalysis.DataAnalysisStore;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
-import org.hisp.dhis.datavalue.DeflatedDataValue;
-import org.hisp.dhis.minmax.MinMaxDataElement;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.period.Period;
-
-/**
- * @author Chau Thu Tran
- * @version $Id$
- */
-public class DefaultMinMaxValuesGenerationService
-    implements MinMaxValuesGenerationService
-{
-    // -------------------------------------------------------------------------
-    // Dependency
-    // -------------------------------------------------------------------------
-
-    private DataAnalysisStore dataAnalysisStore;
-
-    public void setDataAnalysisStore( DataAnalysisStore dataAnalysisStore )
-    {
-        this.dataAnalysisStore = dataAnalysisStore;
-    }
-
-    // -------------------------------------------------------------------------
-    // Action Implementation
-    // -------------------------------------------------------------------------
-
-    public final Collection<MinMaxDataElement> getMinMaxValues( OrganisationUnit organisationUnit,
-        Collection<DataElement> dataElements, Double stdDevFactor )
-    {
-        Collection<MinMaxDataElement> minMaxDataElements = new ArrayList<MinMaxDataElement>();
-
-        for ( DataElement dataElement : dataElements )
-        {
-            if ( dataElement.getType().equals( DataElement.VALUE_TYPE_INT ) )
-            {
-                Collection<DataElementCategoryOptionCombo> categoryOptionCombos = dataElement.getCategoryCombo()
-                    .getOptionCombos();
-
-                for ( DataElementCategoryOptionCombo categoryOptionCombo : categoryOptionCombos )
-                {
-                    Double stdDev = dataAnalysisStore.getStandardDeviation( dataElement, categoryOptionCombo,
-                        organisationUnit );
-
-                    if ( !isEqual( stdDev, AggregatedValue.ZERO ) ) // No values found or no
-                    {
-                        Double avg = dataAnalysisStore.getAverage( dataElement, categoryOptionCombo, organisationUnit );
-
-                        double deviation = stdDev * stdDevFactor;
-                        Double lowerBound = avg - deviation;
-                        Double upperBound = avg + deviation;
-
-                        MinMaxDataElement minMaxDataElement = new MinMaxDataElement();
-                        minMaxDataElement.setDataElement( dataElement );
-                        minMaxDataElement.setOptionCombo( categoryOptionCombo );
-                        minMaxDataElement.setSource( organisationUnit );
-                        minMaxDataElement.setMin( lowerBound.intValue() );
-                        minMaxDataElement.setMax( upperBound.intValue() );
-
-                        minMaxDataElements.add( minMaxDataElement );
-                    }
-                }
-            }
-        }
-
-        return minMaxDataElements;
-    }
-
-    public Collection<DeflatedDataValue> findOutliers( OrganisationUnit organisationUnit, Collection<Period> periods,
-        Collection<MinMaxDataElement> minMaxDataElements )
-    {
-        Set<DeflatedDataValue> result = new HashSet<DeflatedDataValue>();
-
-        for ( MinMaxDataElement minMaxs : minMaxDataElements )
-        {
-            result.addAll( dataAnalysisStore.getDeflatedDataValues( minMaxs.getDataElement(), minMaxs.getOptionCombo(),
-                periods, organisationUnit, minMaxs.getMin(), minMaxs.getMax() ) );
-        }
-
-        return result;
-    }
-}

=== 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-20 11:41:57 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/validation/DefaultValidationRuleService.java	2012-07-25 13:18:48 +0000
@@ -27,7 +27,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import static org.hisp.dhis.i18n.I18nUtils.*;
+import static org.hisp.dhis.i18n.I18nUtils.getCountByName;
+import static org.hisp.dhis.i18n.I18nUtils.getObjectsBetween;
+import static org.hisp.dhis.i18n.I18nUtils.getObjectsBetweenByName;
+import static org.hisp.dhis.i18n.I18nUtils.getObjectsByName;
+import static org.hisp.dhis.i18n.I18nUtils.i18n;
 import static org.hisp.dhis.system.util.MathUtils.expressionIsTrue;
 import static org.hisp.dhis.system.util.MathUtils.getRounded;
 

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2012-07-23 12:33:49 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/META-INF/dhis/beans.xml	2012-07-25 13:18:48 +0000
@@ -187,8 +187,7 @@
     <property name="cacheable" value="true" />
   </bean>
 
-  <bean id="org.hisp.dhis.dataanalysis.jdbc.DataAnalysisStore" class="org.hisp.dhis.dataanalysis.jdbc.JdbcDataAnalysisStore">
-    <property name="statementManager" ref="statementManager" />
+  <bean id="org.hisp.dhis.dataanalysis.DataAnalysisStore" class="org.hisp.dhis.dataanalysis.jdbc.JdbcDataAnalysisStore">
     <property name="statementBuilder" ref="statementBuilder" />
 	<property name="jdbcTemplate" ref="jdbcTemplate" />
   </bean>
@@ -397,18 +396,17 @@
   </bean>
 
   <bean id="org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService" class="org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService">
-    <property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
-    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.jdbc.DataAnalysisStore" />
+    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.DataAnalysisStore" />
   </bean>
 
   <bean id="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" class="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService">
-    <property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
-    <property name="minMaxDataElementService" ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
-    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.jdbc.DataAnalysisStore" />
+    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.DataAnalysisStore" />
+	<property name="minMaxDataElementService" ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
+	<property name="batchHandlerFactory" ref="batchHandlerFactory" />
   </bean>
 
   <bean id="org.hisp.dhis.dataanalysis.FollowupAnalysisService" class="org.hisp.dhis.dataanalysis.FollowupAnalysisService">
-    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.jdbc.DataAnalysisStore" />
+    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.DataAnalysisStore" />
   </bean>
 
   <bean id="dataAnalysisServiceProvider" class="org.hisp.dhis.common.ServiceProvider">
@@ -876,12 +874,6 @@
     </property>
   </bean>
 
-  <!-- Min/Max validation -->
-
-  <bean id="org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService" class="org.hisp.dhis.minmax.validation.DefaultMinMaxValuesGenerationService">
-    <property name="dataAnalysisStore" ref="org.hisp.dhis.dataanalysis.jdbc.DataAnalysisStore" />
-  </bean>
-
   <!-- AOP definitions -->
 
   <aop:config>
@@ -906,11 +898,6 @@
       <aop:before pointcut="execution( * org.hisp.dhis.attribute.AttributeService.delete*(..) )" method="intercept" />	  
     </aop:aspect>
 
-    <aop:aspect ref="statementInterceptor">
-      <aop:around pointcut="execution( * org.hisp.dhis.dataanalysis.DataAnalysisService.analyse(..) )"
-        method="intercept" />
-    </aop:aspect>
-
     <!-- <aop:aspect ref="i18nTranslationInterceptor"> <aop:after-returning pointcut="execution( * org.hisp.dhis.dataelement.DataElementService.get*(..) 
       )" method="intercept" returning="object"/> <aop:after-returning pointcut="execution( * org.hisp.dhis.dataelement.DataElementCategoryService.get*(..) 
       )" method="intercept" returning="object"/> <aop:after-returning pointcut="execution( * org.hisp.dhis.indicator.IndicatorService.get*(..) 

=== added file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/DataAnalysisStoreTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/DataAnalysisStoreTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/DataAnalysisStoreTest.java	2012-07-25 13:18:48 +0000
@@ -0,0 +1,179 @@
+package org.hisp.dhis.dataanalysis;
+
+/*
+ * Copyright (c) 2004-2012, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.HashSet;
+import java.util.Set;
+
+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.dataset.DataSetService;
+import org.hisp.dhis.datavalue.DataValueService;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
+import org.hisp.dhis.period.MonthlyPeriodType;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodService;
+import org.junit.Test;
+
+import static junit.framework.Assert.*;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class DataAnalysisStoreTest
+    extends DhisTest
+{
+    private DataAnalysisStore dataAnalysisStore;
+    
+    private DataElement dataElementA;
+    private DataElement dataElementB;
+
+    private DataElementCategoryCombo categoryCombo;
+
+    private DataElementCategoryOptionCombo categoryOptionCombo;
+
+    private Period periodA;
+    private Period periodB;
+    private Period periodC;    
+    private Period periodD;    
+    private Period periodE;    
+    private Period periodF;    
+    private Period periodG;
+    private Period periodH;
+    private Period periodI;
+    private Period periodJ;
+
+    private OrganisationUnit organisationUnitA;
+    private OrganisationUnit organisationUnitB;
+    
+    private Set<Integer> organisationUnits;
+    
+    // ----------------------------------------------------------------------
+    // Fixture
+    // ----------------------------------------------------------------------
+
+    @Override
+    public void setUpTest()
+    {
+        dataAnalysisStore = (DataAnalysisStore) getBean( DataAnalysisStore.ID );
+        
+        dataElementService = (DataElementService) getBean( DataElementService.ID );
+
+        categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID );
+
+        dataSetService = (DataSetService) getBean( DataSetService.ID );
+
+        organisationUnitService = (OrganisationUnitService) getBean( OrganisationUnitService.ID );
+        
+        dataValueService = (DataValueService) getBean( DataValueService.ID );
+
+        periodService = (PeriodService) getBean( PeriodService.ID );
+
+        categoryCombo = categoryService.getDataElementCategoryComboByName( DataElementCategoryCombo.DEFAULT_CATEGORY_COMBO_NAME );
+
+        dataElementA = createDataElement( 'A', categoryCombo );
+        dataElementB = createDataElement( 'B', categoryCombo );
+
+        dataElementService.addDataElement( dataElementA );
+        dataElementService.addDataElement( dataElementB );
+
+        categoryOptionCombo = categoryService.getDefaultDataElementCategoryOptionCombo();
+
+        periodA = createPeriod( new MonthlyPeriodType(), getDate( 2000, 3, 1 ), getDate( 2000, 3, 31 ) );
+        periodB = createPeriod( new MonthlyPeriodType(), getDate( 2000, 4, 1 ), getDate( 2000, 4, 30 ) );
+        periodC = createPeriod( new MonthlyPeriodType(), getDate( 2000, 5, 1 ), getDate( 2000, 5, 30 ) );
+        periodD = createPeriod( new MonthlyPeriodType(), getDate( 2000, 6, 1 ), getDate( 2000, 6, 30 ) );
+        periodE = createPeriod( new MonthlyPeriodType(), getDate( 2000, 7, 1 ), getDate( 2000, 7, 30 ) );
+        periodF = createPeriod( new MonthlyPeriodType(), getDate( 2000, 8, 1 ), getDate( 2000, 8, 30 ) );
+        periodG = createPeriod( new MonthlyPeriodType(), getDate( 2000, 9, 1 ), getDate( 2000, 9, 30 ) );
+        periodH = createPeriod( new MonthlyPeriodType(), getDate( 2000, 10, 1 ), getDate( 2000, 10, 30 ) );
+        periodI = createPeriod( new MonthlyPeriodType(), getDate( 2000, 11, 1 ), getDate( 2000, 11, 30 ) );
+        periodJ = createPeriod( new MonthlyPeriodType(), getDate( 2000, 12, 1 ), getDate( 2000, 12, 30 ) );
+
+        organisationUnitA = createOrganisationUnit( 'A' );
+        organisationUnitB = createOrganisationUnit( 'B' );
+
+        organisationUnitService.addOrganisationUnit( organisationUnitA );
+        organisationUnitService.addOrganisationUnit( organisationUnitB );
+        
+        organisationUnits = new HashSet<Integer>();
+        organisationUnits.add( organisationUnitA.getId() );
+        organisationUnits.add( organisationUnitB.getId() );
+    }
+
+    @Override
+    public boolean emptyDatabaseAfterTest()
+    {
+        return true;
+    }
+    
+    // ----------------------------------------------------------------------
+    // Business logic tests
+    // ----------------------------------------------------------------------
+
+    @Test
+    public void getGetStdDev()
+    {
+        dataValueService.addDataValue( createDataValue( dataElementA, periodA, organisationUnitA, "5", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodB, organisationUnitA, "2", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodC, organisationUnitA, "1", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodD, organisationUnitA, "12", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodE, organisationUnitA, "10", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodF, organisationUnitA, "7", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodG, organisationUnitA, "52", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodH, organisationUnitA, "23", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodI, organisationUnitA, "3", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodJ, organisationUnitA, "15", categoryOptionCombo ) );
+        
+        assertEquals( 14.49, dataAnalysisStore.getStandardDeviation( dataElementA, categoryOptionCombo, organisationUnits ).get( organisationUnitA.getId() ), 0.01 );
+        assertNull( dataAnalysisStore.getStandardDeviation( dataElementA, categoryOptionCombo, organisationUnits ).get( organisationUnitB.getId() ) );
+    }
+
+    @Test
+    public void getGetAvg()
+    {
+        dataValueService.addDataValue( createDataValue( dataElementA, periodA, organisationUnitA, "5", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodB, organisationUnitA, "2", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodC, organisationUnitA, "1", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodD, organisationUnitA, "12", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodE, organisationUnitA, "10", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodF, organisationUnitA, "7", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodG, organisationUnitA, "52", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodH, organisationUnitA, "23", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodI, organisationUnitA, "3", categoryOptionCombo ) );
+        dataValueService.addDataValue( createDataValue( dataElementA, periodJ, organisationUnitA, "15", categoryOptionCombo ) );
+        
+        assertEquals( 13, dataAnalysisStore.getAverage( dataElementA, categoryOptionCombo, organisationUnits ).get( organisationUnitA.getId() ), 0.01 );
+        assertNull( dataAnalysisStore.getAverage( dataElementA, categoryOptionCombo, organisationUnits ).get( organisationUnitB.getId() ) );
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisServiceTest.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/MinMaxOutlierAnalysisServiceTest.java	2012-07-25 13:18:48 +0000
@@ -27,6 +27,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static junit.framework.Assert.assertEquals;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -41,6 +43,7 @@
 import org.hisp.dhis.dataset.DataSetService;
 import org.hisp.dhis.datavalue.DataValue;
 import org.hisp.dhis.datavalue.DataValueService;
+import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.minmax.MinMaxDataElement;
 import org.hisp.dhis.minmax.MinMaxDataElementService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -48,13 +51,15 @@
 import org.hisp.dhis.period.MonthlyPeriodType;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
+import org.hisp.dhis.system.util.ListUtils;
 import org.junit.Test;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
 
 /**
  * @author eirikmi
  * @version $Id: MinMaxOutlierAnalysisServiceTest.java 883 2009-05-15 00:42:45Z daghf $
  */
-@SuppressWarnings( "unused" )
 public class MinMaxOutlierAnalysisServiceTest
     extends DhisTest
 {
@@ -93,6 +98,8 @@
 
     private MinMaxDataElement minMaxDataElement;
 
+    private JdbcTemplate jdbcTemplate;
+    
     // ----------------------------------------------------------------------
     // Fixture
     // ----------------------------------------------------------------------
@@ -101,6 +108,8 @@
     public void setUpTest()
         throws Exception
     {
+        jdbcTemplate = (JdbcTemplate) getBean( "jdbcTemplate" );
+        
         minMaxOutlierAnalysisService = (DataAnalysisService) getBean( "org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" );
 
         dataElementService = (DataElementService) getBean( DataElementService.ID );
@@ -166,10 +175,6 @@
     @Test
     public void testGetFindOutliers()
     {
-        // testvalues = [5, 5, -5, -5, 10, -10, 13, -13, 41, -41]
-        // mean(testvalues) = 0.0
-        // std(testvalues) = 20.0
-        
         dataValueA = createDataValue( dataElementA, periodI, organisationUnitA, "41", categoryOptionCombo );
         dataValueB = createDataValue( dataElementA, periodJ, organisationUnitA, "-41", categoryOptionCombo );
 
@@ -188,14 +193,21 @@
         minMaxDataElement = new MinMaxDataElement( organisationUnitA, dataElementA, categoryOptionCombo, -40, 40, false );
         minMaxDataElementService.addMinMaxDataElement( minMaxDataElement );
 
+        SqlRowSet rowSet = jdbcTemplate.queryForRowSet( "select mm.minvalue from minmaxdataelement mm" );
+        
+        while ( rowSet.next() )
+        {
+            System.out.println( "min value " + rowSet.getInt( "minvalue" ) );
+        }
+                
         Collection<Period> periods = new ArrayList<Period>();
         periods.add( periodI );
         periods.add( periodJ );
         periods.add( periodA );
         periods.add( periodE );
 
-        //Collection<DeflatedDataValue> result = minMaxOutlierAnalysisService.findOutliers( organisationUnitA, dataElementsA, periods, null );
+        Collection<DeflatedDataValue> result = minMaxOutlierAnalysisService.analyse( ListUtils.getCollection( organisationUnitA ), dataElementsA, periods, null );
 
-        //assertEquals( 2, result.size() );
+        assertEquals( 2, result.size() );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisServiceTest.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/dataanalysis/StdDevOutlierAnalysisServiceTest.java	2012-07-25 13:18:48 +0000
@@ -27,6 +27,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -41,16 +44,17 @@
 import org.hisp.dhis.dataset.DataSetService;
 import org.hisp.dhis.datavalue.DataValue;
 import org.hisp.dhis.datavalue.DataValueService;
+import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.MonthlyPeriodType;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
+import org.hisp.dhis.system.util.ListUtils;
 import org.junit.Test;
 
 /**
- * @author eirikmi
- * @version $Id: StdDevOutlierAnalysisServiceTest.java 883 2009-05-15 00:42:45Z daghf $
+ * @author Lars Helge Overland
  */
 @SuppressWarnings( "unused" )
 public class StdDevOutlierAnalysisServiceTest
@@ -84,7 +88,7 @@
     private Period periodJ;
 
     private OrganisationUnit organisationUnitA;
-
+    
     // ----------------------------------------------------------------------
     // Fixture
     // ----------------------------------------------------------------------
@@ -93,7 +97,7 @@
     public void setUpTest()
     {
         stdDevOutlierAnalysisService = (DataAnalysisService) getBean( "org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService" );
-
+        
         dataElementService = (DataElementService) getBean( DataElementService.ID );
 
         categoryService = (DataElementCategoryService) getBean( DataElementCategoryService.ID );
@@ -121,7 +125,7 @@
         dataElementsA.add( dataElementA );
         dataElementsA.add( dataElementB );
 
-        categoryOptionCombo = categoryCombo.getOptionCombos().iterator().next();
+        categoryOptionCombo = categoryService.getDefaultDataElementCategoryOptionCombo();
 
         periodA = createPeriod( new MonthlyPeriodType(), getDate( 2000, 3, 1 ), getDate( 2000, 3, 31 ) );
         periodB = createPeriod( new MonthlyPeriodType(), getDate( 2000, 4, 1 ), getDate( 2000, 4, 30 ) );
@@ -152,10 +156,6 @@
     @Test
     public void testGetFindOutliers()
     {
-        // testvalues = [5, 5, -5, -5, 10, -10, 13, -13, 71, -71]
-        // mean(testvalues) = 0.0
-        // std(testvalues) = 34.51
-        
         dataValueA = createDataValue( dataElementA, periodI, organisationUnitA, "71", categoryOptionCombo );
         dataValueB = createDataValue( dataElementA, periodJ, organisationUnitA, "-71", categoryOptionCombo );
 
@@ -177,11 +177,16 @@
         periods.add( periodA );
         periods.add( periodE );
 
-        //Collection<DeflatedDataValue> result = stdDevOutlierAnalysisService.findOutliers( organisationUnitA, dataElementsA, periods, stdDevFactor );
-
-        //double lowerBound = -34.51 * stdDevFactor;
-        //double upperBound = 34.51 * stdDevFactor;
+        Collection<DeflatedDataValue> values = stdDevOutlierAnalysisService.analyse( ListUtils.getCollection( organisationUnitA ), dataElementsA, periods, stdDevFactor );
+
+        double lowerBound = -34.51 * stdDevFactor;
+        double upperBound = 34.51 * stdDevFactor;
+
+        DeflatedDataValue valueA = new DeflatedDataValue( dataValueA );
+        DeflatedDataValue valueB = new DeflatedDataValue( dataValueB );
         
-        //assertEquals( 2, result.size() );
+        assertEquals( 2, values.size() );
+        assertTrue( values.contains( valueA ) );
+        assertTrue( values.contains( valueB ) );        
     }
 }

=== added file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/MinMaxDataElementBatchHandler.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/MinMaxDataElementBatchHandler.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/batchhandler/MinMaxDataElementBatchHandler.java	2012-07-25 13:18:48 +0000
@@ -0,0 +1,110 @@
+package org.hisp.dhis.jdbc.batchhandler;
+
+/*
+ * Copyright (c) 2004-${year}, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.amplecode.quick.JdbcConfiguration;
+import org.amplecode.quick.batchhandler.AbstractBatchHandler;
+import org.hisp.dhis.minmax.MinMaxDataElement;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class MinMaxDataElementBatchHandler
+    extends AbstractBatchHandler<MinMaxDataElement>
+{
+    // -------------------------------------------------------------------------
+    // Constructor
+    // -------------------------------------------------------------------------
+ 
+    public MinMaxDataElementBatchHandler( JdbcConfiguration config )
+    {
+        super( config, false, true );
+    }
+
+    @Override
+    protected void setTableName()
+    {
+        statementBuilder.setTableName( "minmaxdataelement" );
+    }
+
+    @Override
+    protected void setAutoIncrementColumn()
+    {
+        statementBuilder.setAutoIncrementColumn( "minmaxdataelementid" );
+    }
+
+    @Override
+    protected void setIdentifierColumns()
+    {
+        statementBuilder.setIdentifierColumn( "minmaxdataelementid" );
+    }
+
+    @Override
+    protected void setIdentifierValues( MinMaxDataElement dataElement )
+    {        
+        statementBuilder.setIdentifierValue( dataElement.getId() );
+    }
+
+    @Override
+    protected void setUniqueColumns()
+    {
+        statementBuilder.setUniqueColumn( "sourceid" );
+        statementBuilder.setUniqueColumn( "dataelementid" );
+        statementBuilder.setUniqueColumn( "categoryoptioncomboid" );
+    }
+
+    @Override
+    protected void setUniqueValues( MinMaxDataElement dataElement )
+    {
+        statementBuilder.setUniqueValue( dataElement.getSource().getId() );
+        statementBuilder.setUniqueValue( dataElement.getDataElement().getId() );
+        statementBuilder.setUniqueValue( dataElement.getOptionCombo().getId() );        
+    }
+
+    @Override
+    protected void setColumns()
+    {
+        statementBuilder.setColumn( "sourceid" );
+        statementBuilder.setColumn( "dataelementid" );
+        statementBuilder.setColumn( "categoryoptioncomboid" );
+        statementBuilder.setColumn( "minvalue" );
+        statementBuilder.setColumn( "maxvalue" );
+        statementBuilder.setColumn( "generated" );
+    }
+
+    @Override
+    protected void setValues( MinMaxDataElement dataElement )
+    {
+        statementBuilder.setValue( dataElement.getSource().getId() );
+        statementBuilder.setValue( dataElement.getDataElement().getId() );
+        statementBuilder.setValue( dataElement.getOptionCombo().getId() );
+        statementBuilder.setValue( dataElement.getMin() );
+        statementBuilder.setValue( dataElement.getMax() );
+        statementBuilder.setValue( dataElement.isGenerated() );
+    }
+}

=== modified file 'dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java'
--- dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java	2012-07-23 12:56:20 +0000
+++ dhis-2/dhis-support/dhis-support-jdbc/src/main/java/org/hisp/dhis/jdbc/statementbuilder/MySQLStatementBuilder.java	2012-07-25 13:18:48 +0000
@@ -102,7 +102,6 @@
             + destDataElementId + ", d1.categoryoptioncomboid = " + destCategoryOptionComboId
             + " WHERE d1.dataelementid = " + sourceDataElementId + " AND d1.categoryoptioncomboid = "
             + sourceCategoryOptionComboId + " AND d2.dataelementid IS NULL";
-
     }
 
     @Override

=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/filter/DataElementTypeFilter.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/filter/DataElementTypeFilter.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/filter/DataElementTypeFilter.java	2012-07-25 13:18:48 +0000
@@ -0,0 +1,50 @@
+package org.hisp.dhis.system.filter;
+
+/*
+ * Copyright (c) 2004-${year}, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright notice, this
+ *   list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * * Neither the name of the HISP project nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software without
+ *   specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.system.util.Filter;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class DataElementTypeFilter
+    implements Filter<DataElement>
+{
+    private String type;
+    
+    public DataElementTypeFilter( String type )
+    {
+        this.type = type;
+    }
+    
+    public boolean retain( DataElement object )
+    {
+        return object != null && type.equals( object.getType() );
+    }
+}

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/objectmapper/DeflatedDataValueNameMinMaxRowMapper.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/objectmapper/DeflatedDataValueNameMinMaxRowMapper.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/objectmapper/DeflatedDataValueNameMinMaxRowMapper.java	2012-07-25 13:18:48 +0000
@@ -29,6 +29,7 @@
 
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Map;
 
 import org.amplecode.quick.mapper.RowMapper;
 import org.hisp.dhis.datavalue.DeflatedDataValue;
@@ -61,6 +62,21 @@
 public class DeflatedDataValueNameMinMaxRowMapper
     implements RowMapper<DeflatedDataValue>, org.springframework.jdbc.core.RowMapper<DeflatedDataValue>
 {
+    private Map<Integer, Integer> minMap;
+    private Map<Integer, Integer> maxMap;
+    private Map<Integer, String> optionComboMap;
+    
+    public DeflatedDataValueNameMinMaxRowMapper()
+    {
+    }
+    
+    public DeflatedDataValueNameMinMaxRowMapper( Map<Integer, Integer> minMap, Map<Integer, Integer> maxMap, Map<Integer, String> optionComboMap )
+    {
+        this.minMap = minMap;
+        this.maxMap = maxMap;
+        this.optionComboMap = optionComboMap;
+    }
+    
     public DeflatedDataValue mapRow( ResultSet resultSet )
         throws SQLException
     {
@@ -75,15 +91,15 @@
         value.setTimestamp( resultSet.getDate( "lastupdated" ) );
         value.setComment( resultSet.getString( "comment" ) );
         value.setFollowup( resultSet.getBoolean( "followup" ) );
-        value.setMin( resultSet.getInt( "minvalue" ) );
-        value.setMax( resultSet.getInt( "maxvalue" ) );
+        value.setMin( minMap != null ? minMap.get( value.getSourceId() ) : resultSet.getInt( "minvalue" ) );
+        value.setMax( maxMap != null ? maxMap.get( value.getSourceId() ) : resultSet.getInt( "maxvalue" ) );
         value.setDataElementName( resultSet.getString( "dataelementname" ) );
         value.setPeriod( 
             resultSet.getString( "periodtypename" ), 
             resultSet.getString( "startdate" ),
             resultSet.getString( "enddate" ) );
         value.setSourceName( resultSet.getString( "sourcename" ) );
-        value.setCategoryOptionComboName( resultSet.getString( "categoryoptioncomboname" ) );
+        value.setCategoryOptionComboName( optionComboMap != null ? optionComboMap.get( value.getCategoryOptionComboId() ) : resultSet.getString( "categoryoptioncomboname" ) );
         
         return value;
     }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java	2012-07-20 11:41:57 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/MathUtils.java	2012-07-25 13:18:48 +0000
@@ -339,4 +339,34 @@
             return null;
         }
     }
+    
+    /**
+     * Returns the lower bound for the given standard deviation, number of standard
+     * deviations and average.
+     * 
+     * @param stdDev the standard deviation.
+     * @param stdDevNo the number of standard deviations.
+     * @param average the average.
+     * @return a double.
+     */
+    public static double getLowBound( double stdDev, double stdDevNo, double average )
+    {
+        double deviation = stdDev * stdDevNo;
+        return average - deviation;
+    }
+
+    /**
+     * Returns the high bound for the given standard deviation, number of standard
+     * deviations and average.
+     * 
+     * @param stdDev the standard deviation.
+     * @param stdDevNo the number of standard deviations.
+     * @param average the average.
+     * @return a double.
+     */
+    public static double getHighBound( double stdDev, double stdDevFactor, double average )
+    {
+        double deviation = stdDev * stdDevFactor;
+        return average + deviation;
+    }
 }

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/ValidationAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/ValidationAction.java	2012-02-16 19:58:55 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/ValidationAction.java	2012-07-25 13:18:48 +0000
@@ -27,8 +27,15 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import com.opensymphony.xwork2.Action;
-import org.apache.commons.collections.CollectionUtils;
+import static org.hisp.dhis.system.util.ListUtils.getCollection;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hisp.dhis.dataanalysis.DataAnalysisService;
@@ -36,21 +43,16 @@
 import org.hisp.dhis.dataset.DataSetService;
 import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.expression.ExpressionService;
-import org.hisp.dhis.minmax.MinMaxDataElement;
-import org.hisp.dhis.minmax.MinMaxDataElementService;
-import org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
 import org.hisp.dhis.period.PeriodType;
-import org.hisp.dhis.setting.SystemSettingManager;
-import org.hisp.dhis.system.util.ListUtils;
 import org.hisp.dhis.validation.ValidationResult;
 import org.hisp.dhis.validation.ValidationRule;
 import org.hisp.dhis.validation.ValidationRuleService;
 
-import java.util.*;
+import com.opensymphony.xwork2.Action;
 
 /**
  * @author Margrethe Store
@@ -86,13 +88,6 @@
         this.periodService = periodService;
     }
 
-    private DataAnalysisService stdDevOutlierAnalysisService;
-
-    public void setStdDevOutlierAnalysisService( DataAnalysisService stdDevOutlierAnalysisService )
-    {
-        this.stdDevOutlierAnalysisService = stdDevOutlierAnalysisService;
-    }
-
     private DataAnalysisService minMaxOutlierAnalysisService;
 
     public void setMinMaxOutlierAnalysisService( DataAnalysisService minMaxOutlierAnalysisService )
@@ -100,27 +95,6 @@
         this.minMaxOutlierAnalysisService = minMaxOutlierAnalysisService;
     }
 
-    private SystemSettingManager systemSettingManager;
-
-    public void setSystemSettingManager( SystemSettingManager systemSettingManager )
-    {
-        this.systemSettingManager = systemSettingManager;
-    }
-
-    private MinMaxValuesGenerationService minMaxValuesGenerationService;
-
-    public void setMinMaxValuesGenerationService( MinMaxValuesGenerationService minMaxValuesGenerationService )
-    {
-        this.minMaxValuesGenerationService = minMaxValuesGenerationService;
-    }
-
-    private MinMaxDataElementService minMaxDataElementService;
-
-    public void setMinMaxDataElementService( MinMaxDataElementService minMaxDataElementService )
-    {
-        this.minMaxDataElementService = minMaxDataElementService;
-    }
-
     private DataSetService dataSetService;
 
     public void setDataSetService( DataSetService dataSetService )
@@ -196,7 +170,6 @@
     // Action implementation
     // -------------------------------------------------------------------------
 
-    @SuppressWarnings( "unchecked" )
     public String execute()
         throws Exception
     {
@@ -215,28 +188,8 @@
             // Min-max and outlier analysis
             // ---------------------------------------------------------------------
 
-            Collection<MinMaxDataElement> minmaxs = minMaxDataElementService.getMinMaxDataElements( orgUnit,
-                dataSet.getDataElements() );
-
-            if ( minmaxs == null )
-            {
-                Double factor = (Double) systemSettingManager.getSystemSetting(
-                    SystemSettingManager.KEY_FACTOR_OF_DEVIATION, 2.0 );
-
-                Collection<DeflatedDataValue> stdDevs = stdDevOutlierAnalysisService.analyse( orgUnit,
-                    dataSet.getDataElements(), ListUtils.getCollection( period ), factor );
-
-                Collection<DeflatedDataValue> minMaxs = minMaxOutlierAnalysisService.analyse( orgUnit,
-                    dataSet.getDataElements(), ListUtils.getCollection( period ), null );
-
-                dataValues = CollectionUtils.union( stdDevs, minMaxs );
-            }
-            else
-            {
-                dataValues = minMaxValuesGenerationService.findOutliers( orgUnit, ListUtils.getCollection( period ),
-                    minmaxs );
-            }
-
+            dataValues = minMaxOutlierAnalysisService.analyse( getCollection( orgUnit ), dataSet.getDataElements(), getCollection( period ), null );
+            
             log.debug( "Number of outlier values: " + dataValues.size() );
 
             // ---------------------------------------------------------------------

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml	2012-02-21 18:45:10 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml	2012-07-25 13:18:48 +0000
@@ -105,12 +105,7 @@
     <property name="validationRuleService" ref="org.hisp.dhis.validation.ValidationRuleService" />
     <property name="expressionService" ref="org.hisp.dhis.expression.ExpressionService" />
     <property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
-    <property name="stdDevOutlierAnalysisService" ref="org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService" />
     <property name="minMaxOutlierAnalysisService" ref="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" />
-    <property name="minMaxValuesGenerationService"
-        ref="org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService" />
-    <property name="minMaxDataElementService" ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
-    <property name="systemSettingManager" ref="org.hisp.dhis.setting.SystemSettingManager" />
     <property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
     <property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
   </bean>

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/utils/FormUtils.java'
--- dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/utils/FormUtils.java	2012-04-11 09:59:20 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/java/org/hisp/dhis/light/utils/FormUtils.java	2012-07-25 13:18:48 +0000
@@ -47,14 +47,11 @@
 import org.hisp.dhis.datavalue.DataValueService;
 import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.expression.ExpressionService;
-import org.hisp.dhis.minmax.MinMaxDataElement;
-import org.hisp.dhis.minmax.MinMaxDataElementService;
-import org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService;
-import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
 import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.period.CalendarPeriodType;
 import org.hisp.dhis.period.Period;
+import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.system.filter.OrganisationUnitWithDataSetsFilter;
 import org.hisp.dhis.system.filter.PastAndCurrentPeriodFilter;
 import org.hisp.dhis.system.util.FilterUtils;
@@ -128,20 +125,6 @@
         this.systemSettingManager = systemSettingManager;
     }
 
-    private MinMaxValuesGenerationService minMaxValuesGenerationService;
-
-    public void setMinMaxValuesGenerationService( MinMaxValuesGenerationService minMaxValuesGenerationService )
-    {
-        this.minMaxValuesGenerationService = minMaxValuesGenerationService;
-    }
-
-    private MinMaxDataElementService minMaxDataElementService;
-
-    public void setMinMaxDataElementService( MinMaxDataElementService minMaxDataElementService )
-    {
-        this.minMaxDataElementService = minMaxDataElementService;
-    }
-
     private ValidationRuleService validationRuleService;
 
     public void setValidationRuleService( ValidationRuleService validationRuleService )
@@ -166,29 +149,17 @@
     {
         Map<String, DeflatedDataValue> validationErrorMap = new HashMap<String, DeflatedDataValue>();
 
-        Collection<MinMaxDataElement> minmaxs = minMaxDataElementService.getMinMaxDataElements( organisationUnit,
-            dataElements );
-        Collection<DeflatedDataValue> deflatedDataValues;
-
-        if ( minmaxs == null )
-        {
-            Double factor = (Double) systemSettingManager.getSystemSetting(
-                SystemSettingManager.KEY_FACTOR_OF_DEVIATION, 2.0 );
-
-            Collection<DeflatedDataValue> stdDevs = stdDevOutlierAnalysisService.analyse( organisationUnit,
-                dataElements, ListUtils.getCollection( period ), factor );
-
-            Collection<DeflatedDataValue> minMaxs = minMaxOutlierAnalysisService.analyse( organisationUnit,
-                dataElements, ListUtils.getCollection( period ), null );
-
-            deflatedDataValues = CollectionUtils.union( stdDevs, minMaxs );
-        }
-        else
-        {
-            deflatedDataValues = minMaxValuesGenerationService.findOutliers( organisationUnit,
-                ListUtils.getCollection( period ), minmaxs );
-        }
-
+        Double factor = (Double) systemSettingManager.getSystemSetting(
+            SystemSettingManager.KEY_FACTOR_OF_DEVIATION, 2.0 );
+
+        Collection<DeflatedDataValue> stdDevs = stdDevOutlierAnalysisService.analyse( ListUtils.getCollection( organisationUnit ),
+            dataElements, ListUtils.getCollection( period ), factor );
+
+        Collection<DeflatedDataValue> minMaxs = minMaxOutlierAnalysisService.analyse( ListUtils.getCollection( organisationUnit ),
+            dataElements, ListUtils.getCollection( period ), null );
+
+        Collection<DeflatedDataValue> deflatedDataValues = CollectionUtils.union( stdDevs, minMaxs );
+        
         for ( DeflatedDataValue deflatedDataValue : deflatedDataValues )
         {
             String key = String.format( "DE%dOC%d", deflatedDataValue.getDataElementId(),

=== modified file 'dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml	2012-07-23 09:58:04 +0000
+++ dhis-2/dhis-web/dhis-web-light/src/main/resources/META-INF/dhis/beans.xml	2012-07-25 13:18:48 +0000
@@ -28,10 +28,6 @@
 			ref="org.hisp.dhis.dataanalysis.StdDevOutlierAnalysisService" />
 		<property name="minMaxOutlierAnalysisService"
 			ref="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" />
-		<property name="minMaxValuesGenerationService"
-			ref="org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService" />
-		<property name="minMaxDataElementService"
-			ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
 		<property name="systemSettingManager" ref="org.hisp.dhis.setting.SystemSettingManager" />
 		<property name="validationRuleService"
 			ref="org.hisp.dhis.validation.ValidationRuleService" />

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GenerateMinMaxValuesAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GenerateMinMaxValuesAction.java	2012-05-17 16:47:13 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GenerateMinMaxValuesAction.java	2012-07-25 13:18:48 +0000
@@ -28,16 +28,18 @@
  */
 
 import java.util.Collection;
+import java.util.HashSet;
 
+import org.hisp.dhis.dataanalysis.MinMaxDataAnalysisService;
+import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataset.DataSet;
 import org.hisp.dhis.dataset.DataSetService;
 import org.hisp.dhis.i18n.I18n;
-import org.hisp.dhis.minmax.MinMaxDataElement;
 import org.hisp.dhis.minmax.MinMaxDataElementService;
-import org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService;
-import org.hisp.dhis.setting.SystemSettingManager;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.oust.manager.SelectionTreeManager;
+import org.hisp.dhis.setting.SystemSettingManager;
 
 import com.opensymphony.xwork2.Action;
 
@@ -53,73 +55,82 @@
 
     private DataSetService dataSetService;
 
-    private MinMaxValuesGenerationService minMaxValuesGenerationService;
-
-    private MinMaxDataElementService minMaxDataElementService;
-
-    private SystemSettingManager systemSettingManager;
-
-    private SelectionTreeManager selectionTreeManager;
-
-    // -------------------------------------------------------------------------------------------------
-    // Input
-    // -------------------------------------------------------------------------------------------------
-
-    private Integer[] dataSets;
-
-    private String message;
-
-    private I18n i18n;
-
-    // -------------------------------------------------------------------------------------------------
-    // Setters
-    // -------------------------------------------------------------------------------------------------
-
     public void setDataSetService( DataSetService dataSetService )
     {
         this.dataSetService = dataSetService;
     }
 
-    public void setMinMaxValuesGenerationService( MinMaxValuesGenerationService minMaxValuesGenerationService )
-    {
-        this.minMaxValuesGenerationService = minMaxValuesGenerationService;
-    }
-
-    public void setMinMaxDataElementService( MinMaxDataElementService minMaxDataElementService )
-    {
-        this.minMaxDataElementService = minMaxDataElementService;
-    }
+    private SystemSettingManager systemSettingManager;
 
     public void setSystemSettingManager( SystemSettingManager systemSettingManager )
     {
         this.systemSettingManager = systemSettingManager;
     }
+    
+    private SelectionTreeManager selectionTreeManager;
 
     public void setSelectionTreeManager( SelectionTreeManager selectionTreeManager )
     {
         this.selectionTreeManager = selectionTreeManager;
     }
 
-    public void setMessage( String message )
-    {
-        this.message = message;
-    }
-
-    public String getMessage()
-    {
-        return message;
-    }
+    private MinMaxDataAnalysisService dataAnalysisService;
+    
+    public void setDataAnalysisService( MinMaxDataAnalysisService dataAnalysisService )
+    {
+        this.dataAnalysisService = dataAnalysisService;
+    }
+    
+    private MinMaxDataElementService minMaxDataElementService;
+
+    public void setMinMaxDataElementService( MinMaxDataElementService minMaxDataElementService )
+    {
+        this.minMaxDataElementService = minMaxDataElementService;
+    }
+    
+    private OrganisationUnitService organisationUnitService;
+
+    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
+    {
+        this.organisationUnitService = organisationUnitService;
+    }
+
+    private I18n i18n;
 
     public void setI18n( I18n i18n )
     {
         this.i18n = i18n;
     }
 
-    public void setDataSets( Integer[] dataSets )
+    // -------------------------------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------------------------------
+
+    private Collection<Integer> dataSets;
+
+    public void setDataSets( Collection<Integer> dataSets )
     {
         this.dataSets = dataSets;
     }
 
+    private boolean remove = false;
+    
+    public void setRemove( boolean remove )
+    {
+        this.remove = remove;
+    }
+
+    // -------------------------------------------------------------------------------------------------
+    // Output
+    // -------------------------------------------------------------------------------------------------
+
+    private String message;
+
+    public String getMessage()
+    {
+        return message;
+    }
+
     // -------------------------------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------------------------------
@@ -128,51 +139,37 @@
     public String execute()
         throws Exception
     {
-        Collection<OrganisationUnit> orgUnits = selectionTreeManager.getReloadedSelectedOrganisationUnits();
+        OrganisationUnit unit = selectionTreeManager.getReloadedSelectedOrganisationUnit();
 
-        if ( orgUnits == null || orgUnits.size() == 0 )
+        if ( unit == null )
         {
             message = i18n.getString( "not_choose_organisation" );
             return INPUT;
         }
 
-        Double factor = (Double) systemSettingManager.getSystemSetting( SystemSettingManager.KEY_FACTOR_OF_DEVIATION,
-            2.0 );
+        Collection<OrganisationUnit> orgUnits = organisationUnitService.getOrganisationUnitWithChildren( unit.getId() );
+        
+        Double factor = (Double) systemSettingManager.
+            getSystemSetting( SystemSettingManager.KEY_FACTOR_OF_DEVIATION, 2.0 );
 
+        Collection<DataElement> dataElements = new HashSet<DataElement>();
+        
         for ( Integer dataSetId : dataSets )
         {
             DataSet dataSet = dataSetService.getDataSet( dataSetId );
-
-            for ( OrganisationUnit orgUnit : orgUnits )
-            {
-                if ( orgUnit.getDataSets().contains( dataSet ) )
-                {
-                    Collection<MinMaxDataElement> minMaxDataElements = (Collection<MinMaxDataElement>) minMaxValuesGenerationService
-                        .getMinMaxValues( orgUnit, dataSet.getDataElements(), factor );
-
-                    for ( MinMaxDataElement minMaxDataElement : minMaxDataElements )
-                    {
-                        MinMaxDataElement minMaxValue = minMaxDataElementService.getMinMaxDataElement(
-                            minMaxDataElement.getSource(), minMaxDataElement.getDataElement(), minMaxDataElement
-                                .getOptionCombo() );
-
-                        if ( minMaxValue != null )
-                        {
-                            minMaxValue.setMax( minMaxDataElement.getMax() );
-                            minMaxValue.setMin( minMaxDataElement.getMin() );
-                            minMaxDataElementService.updateMinMaxDataElement( minMaxValue );
-                        }
-                        else
-                        {
-                            minMaxDataElement.setGenerated( true );
-                            minMaxDataElementService.addMinMaxDataElement( minMaxDataElement );
-                        }
-                    }
-                }
-            }
-        }
-
-        message = i18n.getString( "generate_values_success" );
+            dataElements.addAll( dataSet.getDataElements() );            
+        }
+
+        if ( remove )
+        {
+            minMaxDataElementService.removeMinMaxDataElements( dataElements, orgUnits );
+        }
+        else
+        {
+            dataAnalysisService.generateMinMaxValues( orgUnits, dataElements, factor );
+        }
+        
+        message = i18n.getString( "done" );
 
         return SUCCESS;
     }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GetMinMaxValidationParamsAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GetMinMaxValidationParamsAction.java	2012-05-17 16:47:13 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/GetMinMaxValidationParamsAction.java	2012-07-25 13:18:48 +0000
@@ -27,8 +27,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.Collection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
 
+import org.hisp.dhis.common.comparator.IdentifiableObjectNameComparator;
 import org.hisp.dhis.dataset.DataSet;
 import org.hisp.dhis.dataset.DataSetService;
 
@@ -56,9 +59,9 @@
     // Output
     // -------------------------------------------------------------------------
 
-    private Collection<DataSet> dataSets;
+    private List<DataSet> dataSets;
 
-    public Collection<DataSet> getDataSets()
+    public List<DataSet> getDataSets()
     {
         return dataSets;
     }
@@ -70,7 +73,9 @@
     public String execute()
         throws Exception
     {
-        dataSets = dataSetService.getAllDataSets();
+        dataSets = new ArrayList<DataSet>( dataSetService.getAllDataSets() );
+        
+        Collections.sort( dataSets, IdentifiableObjectNameComparator.INSTANCE );
 
         return SUCCESS;
     }

=== removed file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/RemoveMinMaxValueAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/RemoveMinMaxValueAction.java	2012-05-17 16:47:13 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/minmaxvalidation/RemoveMinMaxValueAction.java	1970-01-01 00:00:00 +0000
@@ -1,172 +0,0 @@
-package org.hisp.dhis.dataadmin.action.minmaxvalidation;
-
-/*
- * Copyright (c) 2004-2012, University of Oslo
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright notice, this
- *   list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright notice,
- *   this list of conditions and the following disclaimer in the documentation
- *   and/or other materials provided with the distribution.
- * * Neither the name of the HISP project nor the names of its contributors may
- *   be used to endorse or promote products derived from this software without
- *   specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-import java.util.Collection;
-
-import org.hisp.dhis.dataset.DataSet;
-import org.hisp.dhis.dataset.DataSetService;
-import org.hisp.dhis.i18n.I18n;
-import org.hisp.dhis.minmax.MinMaxDataElement;
-import org.hisp.dhis.minmax.MinMaxDataElementService;
-import org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService;
-import org.hisp.dhis.setting.SystemSettingManager;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.oust.manager.SelectionTreeManager;
-
-import com.opensymphony.xwork2.Action;
-
-/**
- * @author Chau Thu Tran
- */
-public class RemoveMinMaxValueAction
-    implements Action
-{
-    // -------------------------------------------------------------------------------------------------
-    // Dependencies
-    // -------------------------------------------------------------------------------------------------
-    
-    private DataSetService dataSetService;
-
-    private MinMaxValuesGenerationService minMaxValuesGenerationService;
-
-    private MinMaxDataElementService minMaxDataElementService;
-
-    private SystemSettingManager systemSettingManager;
-
-    private SelectionTreeManager selectionTreeManager;
-
-    // -------------------------------------------------------------------------------------------------
-    // Input
-    // -------------------------------------------------------------------------------------------------
-
-    private Integer[] dataSets;
-
-    private String message;
-
-    private I18n i18n;
-
-    // -------------------------------------------------------------------------------------------------
-    // Setters
-    // -------------------------------------------------------------------------------------------------
-    
-    public void setSelectionTreeManager( SelectionTreeManager selectionTreeManager )
-    {
-        this.selectionTreeManager = selectionTreeManager;
-    }
-
-    public void setSystemSettingManager( SystemSettingManager systemSettingManager )
-    {
-        this.systemSettingManager = systemSettingManager;
-    }
-
-    public void setDataSetService( DataSetService dataSetService )
-    {
-        this.dataSetService = dataSetService;
-    }
-
-    public void setMessage( String message )
-    {
-        this.message = message;
-    }
-
-    public String getMessage()
-    {
-        return message;
-    }
-
-    public void setI18n( I18n i18n )
-    {
-        this.i18n = i18n;
-    }
-
-    public void setMinMaxValuesGenerationService( MinMaxValuesGenerationService minMaxValuesGenerationService )
-    {
-        this.minMaxValuesGenerationService = minMaxValuesGenerationService;
-    }
-
-    public void setMinMaxDataElementService( MinMaxDataElementService minMaxDataElementService )
-    {
-        this.minMaxDataElementService = minMaxDataElementService;
-    }
-
-    public void setDataSets( Integer[] dataSets )
-    {
-        this.dataSets = dataSets;
-    }
-
-    // -------------------------------------------------------------------------------------------------
-    // Action implementation
-    // -------------------------------------------------------------------------------------------------
-
-    @Override
-    public String execute()
-        throws Exception
-    {
-        Collection<OrganisationUnit> orgUnits = selectionTreeManager.getReloadedSelectedOrganisationUnits();
-
-        if ( orgUnits == null || orgUnits.size() == 0 )
-        {
-            message = i18n.getString( "not_choose_organisation" );
-            return INPUT;
-        }
-
-        Double factor = (Double) systemSettingManager.getSystemSetting( SystemSettingManager.KEY_FACTOR_OF_DEVIATION, 2.0 );
-
-        for ( Integer dataSetId : dataSets )
-        {
-            DataSet dataSet = dataSetService.getDataSet( dataSetId );
-
-            for ( OrganisationUnit orgUnit : orgUnits )
-            {
-                if ( orgUnit.getDataSets().contains( dataSet ) )
-                {
-                    Collection<MinMaxDataElement> minMaxDataElements = (Collection<MinMaxDataElement>) minMaxValuesGenerationService
-                        .getMinMaxValues( orgUnit, dataSet.getDataElements(), factor );
-
-                    for ( MinMaxDataElement minMaxDataElement : minMaxDataElements )
-                    {
-                        MinMaxDataElement minMaxValue = minMaxDataElementService.getMinMaxDataElement(
-                            minMaxDataElement.getSource(), minMaxDataElement.getDataElement(), minMaxDataElement.getOptionCombo() );
-
-                        if ( minMaxValue != null )
-                        {
-                            minMaxValue.setMax( minMaxDataElement.getMax() );
-                            minMaxValue.setMin( minMaxDataElement.getMin() );
-                            minMaxDataElementService.deleteMinMaxDataElement( minMaxValue );
-                        }
-                    }
-                }
-            }
-        }
-
-        message = i18n.getString( "remove_values_success" );
-
-        return SUCCESS;
-    }
-}
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/META-INF/dhis/beans.xml	2012-04-26 18:32:46 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/META-INF/dhis/beans.xml	2012-07-25 13:18:48 +0000
@@ -149,34 +149,12 @@
 
   <bean id="org.hisp.dhis.dataadmin.action.minmaxvalidation.GenerateMinMaxValuesAction"
       class="org.hisp.dhis.dataadmin.action.minmaxvalidation.GenerateMinMaxValuesAction">
-    <property name="selectionTreeManager">
-      <ref bean="org.hisp.dhis.oust.manager.SelectionTreeManager" />
-    </property>
-    <property name="dataSetService">
-      <ref bean="org.hisp.dhis.dataset.DataSetService" />
-    </property>
-    <property name="minMaxValuesGenerationService"
-        ref="org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService" />
-    <property name="minMaxDataElementService" ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
-    <property name="systemSettingManager">
-      <ref bean="org.hisp.dhis.setting.SystemSettingManager" />
-    </property>
-  </bean>
-
-  <bean id="org.hisp.dhis.dataadmin.action.minmaxvalidation.RemoveMinMaxValueAction"
-      class="org.hisp.dhis.dataadmin.action.minmaxvalidation.RemoveMinMaxValueAction">
-    <property name="selectionTreeManager">
-      <ref bean="org.hisp.dhis.oust.manager.SelectionTreeManager" />
-    </property>
-    <property name="dataSetService">
-      <ref bean="org.hisp.dhis.dataset.DataSetService" />
-    </property>
-    <property name="minMaxValuesGenerationService"
-        ref="org.hisp.dhis.minmax.validation.MinMaxValuesGenerationService" />
-    <property name="minMaxDataElementService" ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
-    <property name="systemSettingManager">
-      <ref bean="org.hisp.dhis.setting.SystemSettingManager" />
-    </property>
+    <property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
+    <property name="systemSettingManager" ref="org.hisp.dhis.setting.SystemSettingManager" />
+    <property name="selectionTreeManager" ref="org.hisp.dhis.oust.manager.SelectionTreeManager" />
+	<property name="dataAnalysisService" ref="org.hisp.dhis.dataanalysis.MinMaxOutlierAnalysisService" />
+    <property name="minMaxDataElementService" ref="org.hisp.dhis.minmax.MinMaxDataElementService" />
+	<property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
   </bean>
 
   <!-- Sql View -->

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties	2012-06-28 07:00:06 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/org/hisp/dhis/dataadmin/i18n_module.properties	2012-07-25 13:18:48 +0000
@@ -306,4 +306,7 @@
 aggregated_data_set_completeness=Aggregated data set completeness
 show_sql_view=Show SQL view
 financial_yearly=Financial Yearly
-update_option = Update option
\ No newline at end of file
+update_option=Update option
+removing_min_max_values=Removing min-max values
+generating_min_max_values=Generating min-max values
+done=Done
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml	2012-06-08 02:43:59 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/resources/struts.xml	2012-07-25 13:18:48 +0000
@@ -219,22 +219,8 @@
     <!-- Min/Max validation -->
 
     <action name="generateMinMaxValue" class="org.hisp.dhis.dataadmin.action.minmaxvalidation.GenerateMinMaxValuesAction">
-      <result name="success" type="velocity-xml">
-        /dhis-web-maintenance-dataadmin/responseSuccess.vm
-      </result>
-      <result name="input" type="velocity-xml">
-        /dhis-web-maintenance-dataadmin/responseError.vm
-      </result>
-	  <param name="requiredAuthorities">F_GENERATE_MIN_MAX_VALUES</param>
-    </action>
-
-    <action name="removeMinMaxValue" class="org.hisp.dhis.dataadmin.action.minmaxvalidation.RemoveMinMaxValueAction">
-      <result name="success" type="velocity-xml">
-        /dhis-web-maintenance-dataadmin/responseSuccess.vm
-      </result>
-      <result name="input" type="velocity-xml">
-        /dhis-web-maintenance-dataadmin/responseError.vm
-      </result>
+      <result name="success" type="velocity-xml">/dhis-web-maintenance-dataadmin/responseSuccess.vm</result>
+      <result name="input" type="velocity-xml">/dhis-web-maintenance-dataadmin/responseError.vm</result>
 	  <param name="requiredAuthorities">F_GENERATE_MIN_MAX_VALUES</param>
     </action>
 
@@ -242,7 +228,7 @@
       <result name="success" type="velocity">/main.vm</result>
       <param name="page">/dhis-web-maintenance-dataadmin/minMaxValidation.vm</param>
       <param name="menu">/dhis-web-maintenance-dataadmin/menu.vm</param>
-      <param name="javascripts">javascript/minMaxValidation.js, javascript/minMaxValidationForm.js </param>
+      <param name="javascripts">javascript/minMaxValidation.js</param>
 	  <param name="requiredAuthorities">F_GENERATE_MIN_MAX_VALUES</param>
     </action>
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidation.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidation.js	2012-02-24 08:44:29 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidation.js	2012-07-25 13:18:48 +0000
@@ -1,51 +1,54 @@
-function generateMinMaxValue(){
-	
+
+function modifyMinMaxValues( remove )
+{
 	var datasetIds = "";
 	var datasetField = byId( 'dataSetIds' ); 
-	for (var i = 0; i < datasetField.options.length; i++)
-	{
-		if (datasetField.options[ i ].selected)
+	
+	if ( $( "#dataSetIds :selected" ).length == 0 )
+	{
+		setHeaderDelayMessage( i18n_not_choose_dataset );
+		return;
+	}
+	
+	for ( var i = 0; i < datasetField.options.length; i++ )
+	{
+		if ( datasetField.options[ i ].selected )
 		{
-		  datasetIds+= "dataSets=" + datasetField.options[ i ].value + "&";
+			datasetIds+= "dataSets=" + datasetField.options[ i ].value + "&";
 		}
 	}
 	
+	if ( remove )
+	{
+		setHeaderWaitMessage( i18n_removing_min_max_values );
+	}
+	else
+	{
+		setHeaderWaitMessage( i18n_generating_min_max_values );
+	}
+	
+	disableButtons();
+	
 	$.ajax({
 		   type: "POST",
 		   url: "generateMinMaxValue.action",
 		   data: datasetIds,
 		   dataType: "xml",
-		   success: function(xmlObject){
-				xmlObject = xmlObject.getElementsByTagName( 'message' )[0];
-				showSuccessMessage (xmlObject.firstChild.nodeValue);
-		   }
-		});
-}
-
-//-----------------------------------------------------------------------------------
-// Organisation Tree
-//-----------------------------------------------------------------------------------
-
-function removeMinMaxValue(){
-
-	var datasetIds = "";
-	var datasetField = byId( 'dataSetIds' ); 
-	for (var i = 0; i < datasetField.options.length; i++)
-	{
-		if (datasetField.options[ i ].selected)
-		{
-		  datasetIds+= "dataSets=" + datasetField.options[ i ].value + "&";
-		}
-	}
-	
-	$.ajax({
-		   type: "POST",
-		   url: "removeMinMaxValue.action",
-		   data: datasetIds,
-		   dataType: "xml",
-		   success: function(xmlObject){
-				xmlObject = xmlObject.getElementsByTagName( 'message' )[0];
-				showSuccessMessage (xmlObject.firstChild.nodeValue);
-		   }
-		});
+		   success: function(xmlObject)
+		   {
+		   		enableButtons();
+				xmlObject = xmlObject.getElementsByTagName( 'message' )[0];
+				setHeaderDelayMessage(xmlObject.firstChild.nodeValue);
+		   }
+		});
+}
+
+function disableButtons()
+{
+	$( ":button" ).attr( "disabled", "disabled" );
+}
+
+function enableButtons()
+{
+	$( ":button" ).removeAttr( "disabled" );
 }
\ No newline at end of file

=== removed file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidationForm.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidationForm.js	2011-04-11 12:08:16 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/javascript/minMaxValidationForm.js	1970-01-01 00:00:00 +0000
@@ -1,14 +0,0 @@
-jQuery(document).ready(function() {
-	validation2("minMaxGeneratingForm", function() {
-		if (isGenerate) {
-			generateMinMaxValue();
-		} else {
-			removeMinMaxValue();
-		}
-	}, {
-		'rules' : getValidationRules("minMax")
-	});
-});
-
-var isGenerate = true;
-var numberOfSelects = 0;

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/minMaxValidation.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/minMaxValidation.vm	2012-04-16 12:26:55 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/minMaxValidation.vm	2012-07-25 13:18:48 +0000
@@ -1,9 +1,9 @@
 <script type="text/javascript" src="javascript/minMaxValidationForm.js"></script>
 <script type="text/javascript">
-	var i18n_loading = '$encoder.jsEncode( $i18n.getString( "loading" ) )';
-	var levelMustBeInt = '$encoder.jsEncode( $i18n.getString( "level_must_be_int" ) )';
 	var i18n_not_choose_dataset = '$encoder.jsEncode( $i18n.getString( "not_choose_dataset" ) )';
 	var i18n_not_choose_organisation = '$encoder.jsEncode( $i18n.getString( "not_choose_organisation" ) )';
+	var i18n_generating_min_max_values = '$encoder.jsEncode( $i18n.getString( "generating_min_max_values" ) )';
+	var i18n_removing_min_max_values = '$encoder.jsEncode( $i18n.getString( "removing_min_max_values" ) )';
 </script>
 
 <h3>$i18n.getString( "min_max_value_generation" ) #openHelp( "minMaxValueGeneration" )</h3>
@@ -12,7 +12,7 @@
 <table>
   <tr>
     <th colspan="2">$i18n.getString('available_dataset')</th>
-    <td rowspan="2">#organisationUnitSelectionTree( false, true, true ) </td>
+    <td rowspan="2">#organisationUnitSelectionTree( false, false, true ) </td>
   </tr>
   <tr>
     <td colspan="2" rowspan="2">
@@ -26,14 +26,9 @@
   </tr>
   <tr>
   	<td>
-	  	<input type="submit" id="saveButton" onclick="javascipt: isGenerate = true;" style="width:10em" value="$i18n.getString( 'generate' )">
-		<input type="submit" id="removeButton" onclick="javascipt: isGenerate = false;" style="width:10em" value="$i18n.getString( 'remove' )"/>
-		<input type="button" style="width:10em" onClick="window.location.href='index.action'" value="$i18n.getString( 'back' )"/>
+	  	<input type="button" onclick="javascipt:modifyMinMaxValues( false )" style="width:10em" value="$i18n.getString( 'generate' )">
+		<input type="button" onclick="javascipt:modifyMinMaxValues( true )" style="width:10em" value="$i18n.getString( 'remove' )"/>
 	</td>
   </tr>
 </table>
 </form>
-
-<span id="info" style="display:none;top:70px;right:5px;position:fixed;" onclick="hideById(this.id)"></span>
-
-<span id="message"></span>

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java	2011-03-02 00:23:51 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/java/org/hisp/dhis/validationrule/action/dataanalysis/GetAnalysisAction.java	2012-07-25 13:18:48 +0000
@@ -41,6 +41,7 @@
 import org.hisp.dhis.datavalue.DeflatedDataValue;
 import org.hisp.dhis.i18n.I18nFormat;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitService;
 import org.hisp.dhis.oust.manager.SelectionTreeManager;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
@@ -91,6 +92,13 @@
         this.dataSetService = dataSetService;
     }
 
+    private OrganisationUnitService organisationUnitService;
+
+    public void setOrganisationUnitService( OrganisationUnitService organisationUnitService )
+    {
+        this.organisationUnitService = organisationUnitService;
+    }
+
     private I18nFormat format;
 
     public void setFormat( I18nFormat format )
@@ -175,8 +183,12 @@
     {
         Set<DataElement> dataElements = new HashSet<DataElement>();
         Collection<Period> periods = null;
-        OrganisationUnit unit = selectionTreeManager.getReloadedSelectedOrganisationUnit();;
+        OrganisationUnit unit = selectionTreeManager.getReloadedSelectedOrganisationUnit();
 
+        Collection<OrganisationUnit> orgUnits = organisationUnitService.getOrganisationUnitWithChildren( unit.getId() );
+        
+        // TODO filter periods with data element period type
+        
         if ( fromDate != null && toDate != null && dataSets != null )
         {
             periods = periodService.getPeriodsBetweenDates( format.parseDate( fromDate ), format.parseDate( toDate ) );
@@ -186,9 +198,9 @@
                 dataElements.addAll( dataSetService.getDataSet( Integer.parseInt( id ) ).getDataElements() );
             }
 
-
             log.info( "From date: " + fromDate + ", To date: " + toDate + ", Organisation unit: " + unit
                 + ", Std dev: " + standardDeviation + ", Key: " + key );
+            
             log.info( "Nr of data elements: " + dataElements.size() + " Nr of periods: " + periods.size() );
         }
 
@@ -196,7 +208,7 @@
 
         if ( service != null ) // Follow-up analysis has no input params
         {
-            dataValues = service.analyse( unit, dataElements, periods, standardDeviation );
+            dataValues = service.analyse( orgUnits, dataElements, periods, standardDeviation );
 
             maxExceeded = dataValues.size() > DataAnalysisService.MAX_OUTLIERS;
         }

=== modified file 'dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml	2012-01-22 06:34:56 +0000
+++ dhis-2/dhis-web/dhis-web-validationrule/src/main/resources/META-INF/dhis/beans.xml	2012-07-25 13:18:48 +0000
@@ -239,6 +239,7 @@
     <property name="selectionTreeManager" ref="org.hisp.dhis.oust.manager.SelectionTreeManager" />
     <property name="periodService" ref="org.hisp.dhis.period.PeriodService" />
     <property name="dataSetService" ref="org.hisp.dhis.dataset.DataSetService" />
+	<property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
   </bean>
 
   <bean id="org.hisp.dhis.validationrule.action.dataanalysis.EditDataValueAction" class="org.hisp.dhis.validationrule.action.dataanalysis.EditDataValueAction"