← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 870: put comment on optioncombo generation and sorting

 

------------------------------------------------------------
revno: 870
committer: abyot <abyota@xxxxxxxxx>
branch nick: trunk
timestamp: Thu 2009-10-15 20:07:59 +0200
message:
  put comment on optioncombo generation and sorting
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryOptionComboService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/OptionsCategoriesDefaultSortOrderPopulator.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataelement/hibernate/DataElementCategoryCombo.hbm.xml
  dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/multidimensional/FormAction.java
  dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categorycombo/UpdateDataElementCategoryComboAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/dataset/action/GenerateDefaultDataSetReportAction.java
  dhis-2/dhis-web/dhis-web-reporting/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/dataelement/DataElementCategoryCombo.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java	2009-10-15 18:07:59 +0000
@@ -156,8 +156,8 @@
         return optionCombos;
     }
     
-    public void setOptionCombos( Set<DataElementCategoryOptionCombo> optionsCombo )
-    {
-        this.optionCombos = optionsCombo;
+    public void setOptionCombos( Set<DataElementCategoryOptionCombo> optionCombos )
+    {        
+        this.optionCombos = optionCombos;
     }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboService.java	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOptionComboService.java	2009-10-15 18:07:59 +0000
@@ -33,14 +33,15 @@
  * @author Abyot Asalefew
  * @version $Id$
  */
-public interface DataElementCategoryOptionComboService 
-{	
+public interface DataElementCategoryOptionComboService
+{
     String ID = DataElementCategoryOptionComboService.class.getName();
-    
+
     /**
      * Adds a DataElementCategoryOptionCombo.
      * 
-     * @param dataElementCategoryOptionCombo the DataElementCategoryOptionCombo to add.
+     * @param dataElementCategoryOptionCombo the DataElementCategoryOptionCombo
+     *        to add.
      * @return the generated identifier.
      */
     int addDataElementCategoryOptionCombo( DataElementCategoryOptionCombo dataElementCategoryOptionCombo );
@@ -48,14 +49,16 @@
     /**
      * Updates a DataElementCategoryOptionCombo.
      * 
-     * @param dataElementCategoryOptionCombo the DataElementCategoryOptionCombo to update.
+     * @param dataElementCategoryOptionCombo the DataElementCategoryOptionCombo
+     *        to update.
      */
     void updateDataElementCategoryOptionCombo( DataElementCategoryOptionCombo dataElementCategoryOptionCombo );
 
     /**
      * Deletes a DataElementCategoryOptionCombo.
      * 
-     * @param dataElementCategoryOptionCombo the DataElementCategoryOptionCombo to delete.
+     * @param dataElementCategoryOptionCombo the DataElementCategoryOptionCombo
+     *        to delete.
      */
     void deleteDataElementCategoryOptionCombo( DataElementCategoryOptionCombo dataElementCategoryOptionCombo );
 
@@ -66,44 +69,48 @@
      * @return the DataElementCategoryOptionCombo.
      */
     DataElementCategoryOptionCombo getDataElementCategoryOptionCombo( int id );
-    
+
     /**
      * Retrieves the DataElementCategoryOptionCombos with the given identifiers.
      * 
-     * @param identifiers the identifiers of the DataElementCategoryOptionCombos.
+     * @param identifiers the identifiers of the
+     *        DataElementCategoryOptionCombos.
      * @return a Collection of DataElementCategoryOptionCombos.
      */
     Collection<DataElementCategoryOptionCombo> getDataElementCategoryOptionCombos( Collection<Integer> identifiers );
-    
+
     /**
      * Retrieves a DataElementCategoryOptionCombo.
      * 
-     * @param categoryOptionCombo the DataElementCategoryOptionCombo to retrieve.
+     * @param categoryOptionCombo the DataElementCategoryOptionCombo to
+     *        retrieve.
      * @return a DataElementCategoryOptionCombo.
      */
     DataElementCategoryOptionCombo getDataElementCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo ); // TODO WTF?
-    
+
     /**
      * Retrieves all DataElementCategoryOptionCombos.
      * 
      * @return a Collection of DataElementCategoryOptionCombos.
      */
-    Collection<DataElementCategoryOptionCombo> getAllDataElementCategoryOptionCombos(); 
-    
+    Collection<DataElementCategoryOptionCombo> getAllDataElementCategoryOptionCombos();
+
     /**
-     * Sorts the DataElementCategoryOptionCombos in the given DataElementCategoryCombo.
+     * Sorts the DataElementCategoryOptionCombos in the given
+     * DataElementCategoryCombo.
      * 
      * @param categoryCombo the DataElementCategoryCombo.
-     * @return a sorted Collection of DataElementCategoryOptionCombos.
+     * 
      */
-    Collection<DataElementCategoryOptionCombo> sortDataElementCategoryOptionCombos( DataElementCategoryCombo categoryCombo ); // TODO List instead?
-    
+    Collection<DataElementCategoryOptionCombo> sortOptionCombos( DataElementCategoryCombo categoryCombo );
+
     /**
-     * Generates and persists a default DataElementCategory, DataElmentCategoryOption, 
-     * DataElementCategoryCombo and DataElementCategoryOptionCombo.
+     * Generates and persists a default DataElementCategory,
+     * DataElmentCategoryOption, DataElementCategoryCombo and
+     * DataElementCategoryOptionCombo.
      */
     void generateDefaultDimension();
-    
+
     /**
      * Retrieves the default DataElementCategoryOptionCombo.
      * 
@@ -112,12 +119,12 @@
     DataElementCategoryOptionCombo getDefaultDataElementCategoryOptionCombo();
 
     /**
-     * Generates and persists DataElementCategoryOptionCombos for the given DataElementCategoryCombo.
+     * Generates and persists DataElementCategoryOptionCombos for the given
+     * DataElementCategoryCombo.
      * 
      * @param categoryCombo the DataElementCategoryCombo.
      */
     void generateOptionCombos( DataElementCategoryCombo categoryCombo );
-    
 
     /**
      * 
@@ -125,12 +132,12 @@
      * @return
      */
     Collection<Operand> getOperandsByIds( Collection<Integer> dataElementIdentifiers );
-    
+
     /**
      * Gets the Operands for the given Collection of DataElements.
      * 
      * @param dataElements the Collection of DataElements.
      * @return the Operands for the given Collection of DataElements.
      */
-    Collection<Operand> getOperands( Collection<DataElement> dataElements );    
+    Collection<Operand> getOperands( Collection<DataElement> dataElements );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryOptionComboService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryOptionComboService.java	2009-10-14 12:51:53 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementCategoryOptionComboService.java	2009-10-15 18:07:59 +0000
@@ -128,9 +128,8 @@
 
         return categoryOptionCombos;
     }
-
-    public DataElementCategoryOptionCombo getDataElementCategoryOptionCombo(
-        DataElementCategoryOptionCombo categoryOptionCombo )
+    
+    public DataElementCategoryOptionCombo getDataElementCategoryOptionCombo( DataElementCategoryOptionCombo categoryOptionCombo )
     {
         for ( DataElementCategoryOptionCombo dcoc : getAllDataElementCategoryOptionCombos() )
         {
@@ -152,89 +151,7 @@
     {
         return dataElementCategoryOptionComboStore.getAll();
     }
-
-    public Collection<DataElementCategoryOptionCombo> sortDataElementCategoryOptionCombos(
-        DataElementCategoryCombo categoryCombo )
-    {
-
-        // Gets optionCombos for a given categoryCombo
-        Collection<DataElementCategoryOptionCombo> optionCombos = new ArrayList<DataElementCategoryOptionCombo>(
-            categoryCombo.getOptionCombos() );
-
-        // ---------------------------------------------------------------------
-        // Determine the number of times each category is going to repeat
-        // ---------------------------------------------------------------------
-
-        int categoryColSpan = optionCombos.size();
-
-        Map<Integer, Integer> categoryRepeat = new HashMap<Integer, Integer>();
-
-        for ( DataElementCategory category : categoryCombo.getCategories() )
-        {
-            categoryColSpan = categoryColSpan / category.getCategoryOptions().size();
-
-            categoryRepeat.put( category.getId(), categoryColSpan );
-        }
-
-        Map<Integer, Collection<DataElementCategoryOption>> orderedOptions = new HashMap<Integer, Collection<DataElementCategoryOption>>();
-
-        for ( DataElementCategory cat : categoryCombo.getCategories() )
-        {
-            int outerForLoopCount = optionCombos.size();
-            int innerForLoopCount = categoryRepeat.get( cat.getId() );
-
-            Collection<DataElementCategoryOption> requiredOptions = new ArrayList<DataElementCategoryOption>();
-            Collection<DataElementCategoryOption> options = cat.getCategoryOptions();
-
-            int x = 0;
-
-            while ( x < outerForLoopCount )
-            {
-                for ( DataElementCategoryOption option : options )
-                {
-                    for ( int i = 0; i < innerForLoopCount; i++ )
-                    {
-                        requiredOptions.add( option );
-
-                        x++;
-                    }
-                }
-            }
-
-            orderedOptions.put( cat.getId(), requiredOptions );
-        }
-
-        Collection<DataElementCategoryOptionCombo> orderdCategoryOptionCombos = new ArrayList<DataElementCategoryOptionCombo>();
-
-        for ( int i = 0; i < optionCombos.size(); i++ )
-        {
-            Collection<DataElementCategoryOption> options = new ArrayList<DataElementCategoryOption>( categoryCombo
-                .getCategories().size() );
-            Collection<DataElementCategory> copyOforderedCategories = categoryCombo.getCategories();
-            Iterator<DataElementCategory> categoryIterator = copyOforderedCategories.iterator();
-
-            while ( categoryIterator.hasNext() )
-            {
-                DataElementCategory category = categoryIterator.next();
-                Iterator<DataElementCategoryOption> optionIterator = orderedOptions.get( category.getId() ).iterator();
-                DataElementCategoryOption option = optionIterator.next();
-                options.add( option );
-                optionIterator.remove();
-            }
-
-            for ( DataElementCategoryOptionCombo optionCombo : optionCombos )
-            {
-                if ( optionCombo.getCategoryOptions().containsAll( options ) )
-                {
-                    orderdCategoryOptionCombos.add( optionCombo );
-                    break;
-                }
-            }
-        }
-
-        return orderdCategoryOptionCombos;
-    }
-
+    
     public void generateDefaultDimension()
     {
         // ---------------------------------------------------------------------
@@ -299,9 +216,172 @@
         return categoryCombo.getOptionCombos().iterator().next();
     }
 
+    public Collection<Operand> getOperandsByIds( Collection<Integer> dataElementIdentifiers )
+    {
+        Collection<DataElement> dataElements = dataElementService.getDataElements( dataElementIdentifiers );
+
+        return getOperands( dataElements );
+    }
+
+    public Collection<Operand> getOperands( Collection<DataElement> dataElements )
+    {
+        Collection<Operand> operands = new ArrayList<Operand>();
+
+        for ( DataElement dataElement : dataElements )
+        {
+            Set<DataElementCategoryOptionCombo> categoryOptionCombos = dataElement.getCategoryCombo()
+                .getOptionCombos();
+
+            if ( categoryOptionCombos.size() > 1 && !(dataElement instanceof CalculatedDataElement) )
+            {
+                for ( DataElementCategoryOptionCombo optionCombo : categoryOptionCombos )
+                {
+                    Operand operand = new Operand( dataElement.getId(), optionCombo.getId(), dataElement.getName()
+                        + optionCombo.getName(), new ArrayList<Integer>( dataElement.getAggregationLevels() ) );
+
+                    operands.add( operand );
+                }
+            }
+            else
+            {
+                Operand operand = new Operand( dataElement.getId(), categoryOptionCombos.iterator().next().getId(),
+                    dataElement.getName(), new ArrayList<Integer>( dataElement.getAggregationLevels() ) );
+
+                operands.add( operand );
+            }
+        }
+
+        return operands;
+    }
+
     public void generateOptionCombos( DataElementCategoryCombo categoryCombo )
     {
-        // Get categories for a give category
+
+        int totalOptionCombos = 1;
+
+        for ( DataElementCategory category : categoryCombo.getCategories() )
+        {
+            totalOptionCombos = totalOptionCombos * category.getCategoryOptions().size();
+        }
+
+        /*
+         * Iterate through the collection of optionsMap every time picking one option
+         * from each collection. Because we have put enough number of
+         * options in each collection, better to remove the picked options
+         * so that we don't get confused how many times to pick an option - pick
+         * an option only once!
+         */
+        
+        Map<Integer, Collection<DataElementCategoryOption>> optionsMap = prepareOptionsForCombination( categoryCombo ); 
+
+        Set<DataElementCategoryOptionCombo> optionCombos = new HashSet<DataElementCategoryOptionCombo>(
+            totalOptionCombos );
+
+        for ( int i = 0; i < totalOptionCombos; i++ )
+        {
+            List<DataElementCategoryOption> options = new ArrayList<DataElementCategoryOption>( categoryCombo
+                .getCategories().size() );
+
+            /*
+             * We are going to iterate the list of categories a number of times.
+             * better to create a copy and iterate through the copy. we can stop
+             * iterating when we have create the required option combinations.
+             */
+            Collection<DataElementCategory> copyOfCategories = categoryCombo.getCategories();
+
+            Iterator<DataElementCategory> categoryIterator = copyOfCategories.iterator();
+
+            while ( categoryIterator.hasNext() )
+            {
+                DataElementCategory cat = categoryIterator.next();
+
+                /*
+                 * From each category pick one option
+                 */
+                Iterator<DataElementCategoryOption> optionIterator = optionsMap.get( cat.getId() ).iterator();
+
+                DataElementCategoryOption option = optionIterator.next();
+
+                options.add( option );
+
+                /*
+                 * Once we used the option, better to remove it. because we have
+                 * enough number of options
+                 */
+
+                optionIterator.remove();
+            }
+
+            DataElementCategoryOptionCombo optionCombo = new DataElementCategoryOptionCombo();
+
+            optionCombo.setCategoryCombo( categoryCombo );
+
+            optionCombo.setCategoryOptions( options );
+
+            addDataElementCategoryOptionCombo( optionCombo );
+
+            optionCombos.add( optionCombo );
+
+        }
+
+        categoryCombo.setOptionCombos( optionCombos );
+
+        dataElementCategoryComboService.updateDataElementCategoryCombo( categoryCombo );
+
+    }
+
+    public Collection<DataElementCategoryOptionCombo> sortOptionCombos( DataElementCategoryCombo categoryCombo )
+    {
+        Collection<DataElementCategoryOptionCombo> optionCombos = new ArrayList<DataElementCategoryOptionCombo>(
+            categoryCombo.getOptionCombos() );
+
+        int totalColumns = optionCombos.size();        
+
+        Map<Integer, Collection<DataElementCategoryOption>> orderedOptions = prepareOptionsForCombination( categoryCombo );
+
+        Collection<DataElementCategoryOptionCombo> orderdCategoryOptionCombos = new ArrayList<DataElementCategoryOptionCombo>();
+
+        for ( int i = 0; i < totalColumns; i++ )
+        {
+            Collection<DataElementCategoryOption> options = new ArrayList<DataElementCategoryOption>( categoryCombo
+                .getCategories().size() );
+
+            Collection<DataElementCategory> copyOforderedCategories = categoryCombo.getCategories();
+
+            Iterator<DataElementCategory> categoryIterator = copyOforderedCategories.iterator();
+
+            while ( categoryIterator.hasNext() )
+            {
+                DataElementCategory category = categoryIterator.next();
+                Iterator<DataElementCategoryOption> optionIterator = orderedOptions.get( category.getId() ).iterator();
+                DataElementCategoryOption option = optionIterator.next();
+                options.add( option );
+                optionIterator.remove();
+            }
+
+            for ( DataElementCategoryOptionCombo optionCombo : optionCombos )
+            {
+                if ( optionCombo.getCategoryOptions().containsAll( options ) )
+                {
+                    orderdCategoryOptionCombos.add( optionCombo );
+                    break;
+                }
+            }
+        }
+
+        return orderdCategoryOptionCombos;
+        
+    }
+
+    // -------------------------------------------------------------------------
+    // DataElementCategoryOptionCombo
+    // -------------------------------------------------------------------------
+
+    private Map<Integer, Collection<DataElementCategoryOption>> prepareOptionsForCombination(
+        DataElementCategoryCombo categoryCombo )
+    {
+        // Get categories for a given category
+        
         List<DataElementCategory> categories = new ArrayList<DataElementCategory>( categoryCombo.getCategories() );
 
         /*
@@ -319,11 +399,54 @@
          * generalizing this we can have total option combinations by
          * multiplying the number of options in each category
          */
+        
         int totalOptionCombos = 1;
 
         for ( DataElementCategory category : categories )
         {
             totalOptionCombos = totalOptionCombos * category.getCategoryOptions().size();
+        }       
+
+        // ---------------------------------------------------------------------
+        // Determine the number of times each category is going to repeat
+        // ---------------------------------------------------------------------
+        
+        
+        /* Example again Category IPD_OPD, Options I and D
+         *               Category Sex, Options F and M
+         *               Category Age, Options 0-5,5-10,11+
+         *               
+         * Category combination is IPD_OPD+Sex+Age
+         * 
+         * Option combinations ... with the following arrangement in Data Entry
+         *  
+         *   I |  I | I | I | I  |  I | O |  O | O | O | O  |  O    
+         *   F |  F | F | F | F  |  F | M |  M | M | M | M  |  M     
+         *  0-5|5-10|11+|0-5|5-10|11+1|0-5|5-10|11+|0-5|5-10|11+1
+         *  
+         *  If we rearrange our categories like IPD_OPD+Age+Sex - then we will 
+         *  have the same option combinations, but with different arrangement. 
+         *  
+         *   I |  I | I  | I  | I  |  I | O |  O | O  | O  | O  |  O    
+         *  0-5| 0-5|5-10|5-10| 11+| 11+|0-5| 0-5|5-10|5-10| 11+|11+     
+         *  F  |  M | F  | M  |  F |  M |F  |  M | F  | M  |  F |  M 
+         *  
+         *  If we assume that we will draw a data entry table header, the top 
+         *  a category is in the order list, then the more ColSpan its options 
+         *  are going to have
+         *   
+         */
+        
+
+        int categoryColSpan = totalOptionCombos;
+
+        Map<Integer, Integer> categoryRepeat = new HashMap<Integer, Integer>();
+
+        for ( DataElementCategory category : categories )
+        {
+            categoryColSpan = categoryColSpan / category.getCategoryOptions().size();
+
+            categoryRepeat.put( category.getId(), categoryColSpan );
         }
 
         /*
@@ -354,129 +477,30 @@
          * its options 'appearance' number of times. The size of the collection
          * should be equal to total number of options combinations.
          */
-        for ( DataElementCategory category : categories )
-        {
-
-            Collection<DataElementCategoryOption> repeatedOptions = new ArrayList<DataElementCategoryOption>(
-                totalOptionCombos );
-
-            List<DataElementCategoryOption> options = category.getCategoryOptions();
-
-            for ( DataElementCategoryOption option : options )
-            {
-                /*
-                 * Collect each option 'appearance' number of times
-                 */
-                for ( int i = 0; i < (totalOptionCombos / category.getCategoryOptions().size()); i++ )
-                {
-                    repeatedOptions.add( option );
-                }
-            }
-            /*
-             * Each option is collected the required number of times and put it
-             * in its corresponding category
-             */
-            optionsMap.put( category.getId(), repeatedOptions );
-        }
-
-        /*
-         * Iterate through the list of categories every time picking one option
-         * from each of the categories. Because we have put enough number of
-         * options in the category list - better to remove the picked options,
-         * so that we don't get confused how many times to an pick an option -
-         * pick an option only once!
-         */
-
-        Set<DataElementCategoryOptionCombo> optionCombos = new HashSet<DataElementCategoryOptionCombo>(
-            totalOptionCombos );
-
-        for ( int i = 0; i < totalOptionCombos; i++ )
-        {
-            List<DataElementCategoryOption> options = new ArrayList<DataElementCategoryOption>( categories.size() );
-
-            /*
-             * We are going to iterate the list of categories a number of times
-             * better to create a copy and iterate through the copy. we can stop
-             * iterating when we have create the required option combinations.
-             */
-            Collection<DataElementCategory> copyOfCategories = categories;
-
-            Iterator<DataElementCategory> categoryIterator = copyOfCategories.iterator();
-
-            while ( categoryIterator.hasNext() )
-            {
-                DataElementCategory cat = categoryIterator.next();
-
-                /*
-                 * From each category pick an option
-                 */
-                Iterator<DataElementCategoryOption> optionIterator = optionsMap.get( cat.getId() ).iterator();
-
-                DataElementCategoryOption option = optionIterator.next();
-
-                options.add( option );
-
-                /*
-                 * Once we used the option, better to remove it. because we have
-                 * enough number of options
-                 */
-
-                optionIterator.remove();
-            }
-
-            DataElementCategoryOptionCombo optionCombo = new DataElementCategoryOptionCombo();
-
-            optionCombo.setCategoryCombo( categoryCombo );
-
-            optionCombo.setCategoryOptions( options );
-
-            addDataElementCategoryOptionCombo( optionCombo );
-
-            optionCombos.add( optionCombo );
-        }
-
-        if ( categoryCombo.getOptionCombos().size() != optionCombos.size() )
-        {
-            categoryCombo.setOptionCombos( optionCombos );
-
-            dataElementCategoryComboService.updateDataElementCategoryCombo( categoryCombo );
-        }
-    }
-
-    public Collection<Operand> getOperandsByIds( Collection<Integer> dataElementIdentifiers )
-    {
-        Collection<DataElement> dataElements = dataElementService.getDataElements( dataElementIdentifiers );
-
-        return getOperands( dataElements );
-    }
-
-    public Collection<Operand> getOperands( Collection<DataElement> dataElements )
-    {
-        Collection<Operand> operands = new ArrayList<Operand>();
-
-        for ( DataElement dataElement : dataElements )
-        {
-            Set<DataElementCategoryOptionCombo> categoryOptionCombos = dataElement.getCategoryCombo().getOptionCombos();
-
-            if ( categoryOptionCombos.size() > 1 && !(dataElement instanceof CalculatedDataElement) )
-            {
-                for ( DataElementCategoryOptionCombo optionCombo : categoryOptionCombos )
-                {
-                    Operand operand = new Operand( dataElement.getId(), optionCombo.getId(), dataElement.getName()
-                        + optionCombo.getName(), new ArrayList<Integer>( dataElement.getAggregationLevels() ) );
-
-                    operands.add( operand );
-                }
-            }
-            else
-            {
-                Operand operand = new Operand( dataElement.getId(), categoryOptionCombos.iterator().next().getId(),
-                    dataElement.getName(), new ArrayList<Integer>( dataElement.getAggregationLevels() ) );
-
-                operands.add( operand );
-            }
-        }
-
-        return operands;
-    }
+        for ( DataElementCategory cat : categories )
+        {
+            Collection<DataElementCategoryOption> requiredOptions = new ArrayList<DataElementCategoryOption>();
+            Collection<DataElementCategoryOption> options = cat.getCategoryOptions();
+
+            int count = 0;
+
+            while ( count < totalOptionCombos )
+            {
+                for ( DataElementCategoryOption option : options )
+                {
+                    for ( int i = 0; i < categoryRepeat.get( cat.getId() ); i++ )
+                    {
+                        requiredOptions.add( option );
+
+                        count++;
+                    }
+                }
+            }
+
+            optionsMap.put( cat.getId(), requiredOptions );
+        }
+
+        return optionsMap;
+    }   
+
 }

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/OptionsCategoriesDefaultSortOrderPopulator.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/OptionsCategoriesDefaultSortOrderPopulator.java	2009-10-14 07:30:28 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/OptionsCategoriesDefaultSortOrderPopulator.java	2009-10-15 18:07:59 +0000
@@ -67,7 +67,7 @@
         
         statementManager.getHolder().executeUpdate( "update categorycombos_categories set sort_order=0 where sort_order is NULL" );
         
-        LOG.info( "Updated categorycombos_categories" );
+        LOG.info( "Updated categorycombos_categories" );       
         
         statementManager.getHolder().executeUpdate( "update categories_categoryoptions set sort_order=0 where sort_order is NULL" );
         

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataelement/hibernate/DataElementCategoryCombo.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataelement/hibernate/DataElementCategoryCombo.hbm.xml	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataelement/hibernate/DataElementCategoryCombo.hbm.xml	2009-10-15 18:07:59 +0000
@@ -21,12 +21,11 @@
         column="categoryid" foreign-key="fk_categorycombo_categoryid"/> 
     </list>
 
-    <set name="optionCombos" table="categorycombos_optioncombos" inverse="true" cascade="all">
-      <key column="categorycomboid"/>
+    <set name="optionCombos" table="categorycombos_optioncombos" inverse="true" cascade="all">
+      <key column="categorycomboid"/>
       <many-to-many class="org.hisp.dhis.dataelement.DataElementCategoryOptionCombo"
-        column="categoryoptioncomboid" unique="true"/>
-    </set>
-    
+        column="categoryoptioncomboid" unique="true"/>
+    </set>    
     
     </class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/multidimensional/FormAction.java'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/multidimensional/FormAction.java	2009-10-14 06:36:36 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/java/org/hisp/dhis/de/action/multidimensional/FormAction.java	2009-10-15 18:07:59 +0000
@@ -32,8 +32,10 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.hisp.dhis.customvalue.CustomValue;
 import org.hisp.dhis.customvalue.CustomValueService;
@@ -116,14 +118,6 @@
         this.dataValueService = dataValueService;
     }
 
-    private DataElementCategoryOptionComboService dataElementCategoryOptionComboService;
-
-    public void setDataElementCategoryOptionComboService(
-        DataElementCategoryOptionComboService dataElementCategoryOptionComboService )
-    {
-        this.dataElementCategoryOptionComboService = dataElementCategoryOptionComboService;
-    }
-
     private StandardCommentsManager standardCommentsManager;
 
     public void setStandardCommentsManager( StandardCommentsManager standardCommentsManager )
@@ -144,12 +138,19 @@
     {
         this.selectedStateManager = selectedStateManager;
     }
-    
+
     private DataEntryScreenManager dataEntryScreenManager;
 
     public void setDataEntryScreenManager( DataEntryScreenManager dataEntryScreenManager )
     {
         this.dataEntryScreenManager = dataEntryScreenManager;
+    }   
+    
+    private DataElementCategoryOptionComboService dataElementCategoryOptionComboService;
+
+    public void setDataElementCategoryOptionComboService( DataElementCategoryOptionComboService dataElementCategoryOptionComboService )
+    {
+        this.dataElementCategoryOptionComboService = dataElementCategoryOptionComboService;
     }
 
     private I18n i18n;
@@ -265,13 +266,13 @@
         return catColRepeat;
     }
 
-    private Collection<DataElementCategoryOptionCombo> orderdCategoryOptionCombos = new ArrayList<DataElementCategoryOptionCombo>();
+    private Set<DataElementCategoryOptionCombo> orderdCategoryOptionCombos = new LinkedHashSet<DataElementCategoryOptionCombo>();
 
-    public Collection<DataElementCategoryOptionCombo> getOrderdCategoryOptionCombos()
+    public Set<DataElementCategoryOptionCombo> getOrderdCategoryOptionCombos()
     {
         return orderdCategoryOptionCombos;
     }
-    
+
     private Boolean cdeFormExists;
 
     public Boolean getCdeFormExists()
@@ -357,7 +358,7 @@
         Period period = selectedStateManager.getSelectedPeriod();
 
         DataSetLock dataSetLock = dataSetLockService.getDataSetLockByDataSetAndPeriod( dataSet, period );
-        
+
         if ( dataSetLock != null && dataSetLock.getSources().contains( organisationUnit ) )
         {
             disabled = "disabled";
@@ -370,39 +371,39 @@
             return SUCCESS;
         }
 
-        for ( DataElement element : dataElements )
+        /*
+         * Get all optionCombos for each and every dataElement so that we make
+         * sure we pick all the values for each of these optionCombos
+         */
+
+        for ( DataElement de : dataElements )
         {
-            if ( !orderdCategoryOptionCombos.containsAll( element.getCategoryCombo().getOptionCombos() ) )
-            {
-                Collection<DataElementCategoryOptionCombo> optionCombos = dataElementCategoryOptionComboService
-                    .sortDataElementCategoryOptionCombos( element.getCategoryCombo() );
-    
-                for ( DataElementCategoryOptionCombo optionCombo : optionCombos )
-                {
-                    if ( !orderdCategoryOptionCombos.contains( optionCombo ) )
-                    {
-                        orderdCategoryOptionCombos.add( optionCombo );
-                    }
-                }
-            }
-        }
-        
+            orderdCategoryOptionCombos.addAll( dataElementCategoryOptionComboService.sortOptionCombos( de.getCategoryCombo() ) );            
+        }       
+                
         // ---------------------------------------------------------------------
         // Perform ordering of categories and their options so that they could
-        // be displayed as in the paper form. Note that the total number of entry 
-        // cells to be generated are the multiple of options fromo each category.
-        // ---------------------------------------------------------------------
-
-        DataElement sample = dataElements.iterator().next();
-
-        DataElementCategoryCombo decbo = sample.getCategoryCombo();
-        
-        numberOfTotalColumns = orderdCategoryOptionCombos.size();       
+        // be displayed as in the paper form. Note that the total number of
+        // entry
+        // cells to be generated are the multiple of options from each
+        // category.
+        //
+        // For the time being we can only display a dataEntry form containing
+        // dataElements having similar categoryCombo - otherwise use custom
+        // forms
+        //
+        // ---------------------------------------------------------------------       
+
+        DataElement sample = dataElements.iterator().next();       
+
+        DataElementCategoryCombo decbo = sample.getCategoryCombo();        
+
+        numberOfTotalColumns = orderdCategoryOptionCombos.size();
 
         orderedCategories = decbo.getCategories();
 
-        for ( DataElementCategory dec : orderedCategories ) // Get the order of options
-        {
+        for ( DataElementCategory dec : orderedCategories ) 
+        {          
             orderedOptionsMap.put( dec.getId(), dec.getCategoryOptions() );
         }
 
@@ -415,9 +416,9 @@
         Map<Integer, Integer> catRepeat = new HashMap<Integer, Integer>();
 
         for ( DataElementCategory cat : orderedCategories )
-        {
+        {            
             catColSpan = catColSpan / cat.getCategoryOptions().size();
-            int total = numberOfTotalColumns / ( catColSpan * cat.getCategoryOptions().size() );
+            int total = numberOfTotalColumns / (catColSpan * cat.getCategoryOptions().size());
             Collection<Integer> cols = new ArrayList<Integer>( total );
 
             for ( int i = 0; i < total; i++ )
@@ -426,16 +427,15 @@
             }
 
             /*
-             * TODO Cols are made to be a collection simply to facilitate a for loop
-             * in the velocity template - there should be a better way of "for"
-             * doing a loop.
+             * TODO Cols are made to be a collection simply to facilitate a for
+             * loop in the velocity template - there should be a better way of
+             * "for" doing a loop.
              */
 
             catColRepeat.put( cat.getId(), cols );
 
             catRepeat.put( cat.getId(), catColSpan );
         }
-       
 
         // ---------------------------------------------------------------------
         // Get the min/max values
@@ -473,7 +473,8 @@
         // Prepare values for unsaved CalculatedDataElements
         // ---------------------------------------------------------------------
 
-        calculatedValueMap = dataEntryScreenManager.populateValuesForCalculatedDataElements( organisationUnit, dataSet, period );
+        calculatedValueMap = dataEntryScreenManager.populateValuesForCalculatedDataElements( organisationUnit, dataSet,
+            period );
 
         // ---------------------------------------------------------------------
         // Make the standard comments available

=== 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	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/META-INF/dhis/beans.xml	2009-10-15 18:07:59 +0000
@@ -141,13 +141,13 @@
     <property name="minMaxDataElementService"
       ref="org.hisp.dhis.minmax.MinMaxDataElementService"/>
     <property name="selectedStateManager"
-      ref="org.hisp.dhis.de.state.SelectedStateManager"/>
-    <property name="dataElementCategoryOptionComboService"
-      ref="org.hisp.dhis.dataelement.DataElementCategoryOptionComboService"/>
+      ref="org.hisp.dhis.de.state.SelectedStateManager"/>    
     <property name="dataEntryFormService"
       ref="org.hisp.dhis.dataset.DataEntryFormService"/>    
     <property name="systemSettingManager"
       ref="org.hisp.dhis.options.SystemSettingManager"/>  
+    <property name="dataElementCategoryOptionComboService"
+      ref="org.hisp.dhis.dataelement.DataElementCategoryOptionComboService"/>
     <property name="customValueService">
       <ref bean="org.hisp.dhis.customvalue.CustomValueService"/>
     </property>	          

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categorycombo/UpdateDataElementCategoryComboAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categorycombo/UpdateDataElementCategoryComboAction.java	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/java/org/hisp/dhis/dd/action/categorycombo/UpdateDataElementCategoryComboAction.java	2009-10-15 18:07:59 +0000
@@ -35,7 +35,6 @@
 import org.hisp.dhis.dataelement.DataElementCategory;
 import org.hisp.dhis.dataelement.DataElementCategoryCombo;
 import org.hisp.dhis.dataelement.DataElementCategoryComboService;
-import org.hisp.dhis.dataelement.DataElementCategoryOptionComboService;
 import org.hisp.dhis.dataelement.DataElementCategoryService;
 
 import com.opensymphony.xwork2.Action;
@@ -63,17 +62,7 @@
     public void setDataElementCategoryComboService( DataElementCategoryComboService dataElementCategoryComboService )
     {
         this.dataElementCategoryComboService = dataElementCategoryComboService;
-    }
-
-    private DataElementCategoryOptionComboService dataElementCategoryOptionComboService;
-
-    public void setDataElementCategoryOptionComboService(
-        DataElementCategoryOptionComboService dataElementCategoryOptionComboService )
-    {
-        this.dataElementCategoryOptionComboService = dataElementCategoryOptionComboService;
-    }
-
-    
+    }    
 
     // -------------------------------------------------------------------------
     // Input
@@ -123,9 +112,7 @@
 
         dataElementCategoryCombo.setCategories( updatedCategories );
 
-        dataElementCategoryComboService.updateDataElementCategoryCombo( dataElementCategoryCombo );
-            
-        dataElementCategoryOptionComboService.generateOptionCombos( dataElementCategoryCombo );
+        dataElementCategoryComboService.updateDataElementCategoryCombo( dataElementCategoryCombo );       
         
         return SUCCESS;
     }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-datadictionary/src/main/resources/META-INF/dhis/beans.xml	2009-10-15 18:07:59 +0000
@@ -598,10 +598,7 @@
     </property>
     <property name="dataElementCategoryComboService">
       <ref bean="org.hisp.dhis.dataelement.DataElementCategoryComboService"/>
-    </property>    
-    <property name="dataElementCategoryOptionComboService">
-      <ref bean="org.hisp.dhis.dataelement.DataElementCategoryOptionComboService"/>
-    </property>
+    </property>   
   </bean>
   
   <bean id="org.hisp.dhis.dd.action.categorycombo.GetDataElementCategoryComboAction"

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/dataset/action/GenerateDefaultDataSetReportAction.java'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/dataset/action/GenerateDefaultDataSetReportAction.java	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/dataset/action/GenerateDefaultDataSetReportAction.java	2009-10-15 18:07:59 +0000
@@ -275,7 +275,7 @@
                     int colCount = 0;
 
                     Collection<DataElementCategoryOptionCombo> optionCombos = dataElementCategoryOptionComboService
-                        .sortDataElementCategoryOptionCombos( catCombo );
+                        .sortOptionCombos( catCombo );
 
                     collectedDataElements.add( dataElement.getName() );
 

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml	2009-10-13 20:08:57 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml	2009-10-15 18:07:59 +0000
@@ -543,11 +543,11 @@
     <property name="selectedStateManager"
       ref="org.hisp.dhis.reporting.dataset.state.SelectedStateManager"/>    		
     <property name="dataElementOrderManager"
-      ref="org.hisp.dhis.order.manager.DataElementOrderManager"/>    
-    <property name="dataElementCategoryService"
-      ref="org.hisp.dhis.dataelement.DataElementCategoryService"/>
+      ref="org.hisp.dhis.order.manager.DataElementOrderManager"/>   
     <property name="dataValueService"
-      ref="org.hisp.dhis.datavalue.DataValueService"/>		     
+      ref="org.hisp.dhis.datavalue.DataValueService"/>
+    <property name="dataElementCategoryOptionComboService"
+      ref="org.hisp.dhis.dataelement.DataElementCategoryOptionComboService"/>		     
   </bean>
   
   <bean id="org.hisp.dhis.reporting.dataset.action.GetViewFormStateAction"