← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18706: CSV import. Re-implemented CSV import of option sets. Added code field to option set.

 

------------------------------------------------------------
revno: 18706
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2015-03-27 12:01:54 +0100
message:
  CSV import. Re-implemented CSV import of option sets. Added code field to option set.
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata/CsvMetaDataImportTest.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/dataElements.csv
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/optionSets.csv
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/option/DefaultOptionService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/CsvImportService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/DefaultCsvImportService.java
  dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/dxf2/MetaDataImportAction.java
  dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportMetaDataCsvTask.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/AddOptionSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/UpdateOptionSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/ValidateOptionSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/addOptionSetForm.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/option.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/updateOptionSetForm.vm


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

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionService.java	2015-03-27 11:01:54 +0000
@@ -52,6 +52,8 @@
 
     OptionSet getOptionSetByName( String name );
 
+    OptionSet getOptionSetByCode( String code );
+
     void deleteOptionSet( OptionSet optionSet );
 
     Collection<OptionSet> getAllOptionSets();

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/option/DefaultOptionService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/option/DefaultOptionService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/option/DefaultOptionService.java	2015-03-27 11:01:54 +0000
@@ -110,6 +110,12 @@
     }
 
     @Override
+    public OptionSet getOptionSetByCode( String code )
+    {
+        return i18n( i18nService, optionSetStore.getByCode( code ) );
+    }
+
+    @Override
     public void deleteOptionSet( OptionSet optionSet )
     {
         optionSetStore.delete( optionSet );

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/CsvImportService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/CsvImportService.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/CsvImportService.java	2015-03-27 11:01:54 +0000
@@ -31,6 +31,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 
+import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.dxf2.metadata.MetaData;
 
 /**
@@ -38,6 +39,6 @@
  */
 public interface CsvImportService
 {
-    MetaData fromCsv( InputStream input, Class<?> clazz )
+    MetaData fromCsv( InputStream input, Class<? extends IdentifiableObject> clazz )
         throws IOException;
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/DefaultCsvImportService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/DefaultCsvImportService.java	2015-03-11 11:12:19 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/DefaultCsvImportService.java	2015-03-27 11:01:54 +0000
@@ -34,11 +34,14 @@
 import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.lang3.StringUtils;
 import org.hisp.dhis.common.BaseIdentifiableObject;
 import org.hisp.dhis.common.CodeGenerator;
+import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.common.ListMap;
 import org.hisp.dhis.dataelement.CategoryOptionGroup;
 import org.hisp.dhis.dataelement.DataElement;
@@ -80,7 +83,7 @@
     // -------------------------------------------------------------------------
 
     @Override
-    public MetaData fromCsv( InputStream input, Class<?> clazz )
+    public MetaData fromCsv( InputStream input, Class<? extends IdentifiableObject> clazz )
         throws IOException
     {
         CsvReader reader = new CsvReader( input, Charset.forName( "UTF-8" ) );
@@ -118,7 +121,7 @@
         }
         else if ( OptionSet.class.equals( clazz ) )
         {
-            metaData.setOptionSets( getOptionSetsFromCsv( reader ) );
+            setOptionSetsFromCsv( reader, metaData );
         }
 
         return metaData;
@@ -361,41 +364,65 @@
         return list;
     }
 
-    private List<OptionSet> getOptionSetsFromCsv( CsvReader reader )
+    /**
+     * Option set format:
+     * 
+     * <ul>
+     * <li>option set name</li>
+     * <li>option set uid</li>
+     * <li>option set code</li>
+     * <li>option name</li>
+     * <li>option uid</li>
+     * <li>option code</li>
+     * </ul>
+     */
+    private void setOptionSetsFromCsv( CsvReader reader, MetaData metaData )
         throws IOException
     {
-        ListMap<OptionSet, String> listMap = new ListMap<>();
+        ListMap<String, Option> nameOptionMap = new ListMap<>();
+        Map<String, OptionSet> nameOptionSetMap = new HashMap<>();
 
+        // Read option sets and options and put in maps
+        
         while ( reader.readRecord() )
         {
             String[] values = reader.getValues();
 
             if ( values != null && values.length > 0 )
             {
-                OptionSet object = new OptionSet();
-                setIdentifiableObject( object, values );
-                String option = getSafe( values, 3, null, 2000000 );
+                OptionSet optionSet = new OptionSet();
+                setIdentifiableObject( optionSet, values );
+                
+                Option option = new Option();
+                option.setName( getSafe( values, 3, null, 230 ) );
+                option.setUid( getSafe( values, 4, CodeGenerator.generateCode(), 11 ) );
+                option.setCode( getSafe( values, 5, null, 50 ) );
 
-                listMap.putValue( object, option );
+                if ( optionSet.getName() == null || option.getCode() == null )
+                {
+                    continue;
+                }
+                
+                nameOptionSetMap.put( optionSet.getName(), optionSet );
+                
+                nameOptionMap.putValue( optionSet.getName(), option );
+                
+                metaData.getOptions().add( option );
             }
         }
 
-        List<OptionSet> optionSets = new ArrayList<>();
-
-        for ( OptionSet optionSet : listMap.keySet() )
+        // Read option sets from map and set in meta data
+        
+        for ( String optionSetName : nameOptionSetMap.keySet() )
         {
-            List<String> options = new ArrayList<>( listMap.get( optionSet ) );
-            List<Option> optionObj = new ArrayList<>();
-            for ( String opt : options )
-            {
-                Option option = new Option( opt, opt );
-                optionObj.add(option);
-            }
-            optionSet.setOptions( optionObj );
-            optionSets.add( optionSet );
+            OptionSet optionSet = nameOptionSetMap.get( optionSetName );
+            
+            List<Option> options = new ArrayList<>( nameOptionMap.get( optionSetName ) );
+            
+            optionSet.setOptions( options );
+            
+            metaData.getOptionSets().add( optionSet );
         }
-        
-        return optionSets;
     }
 
     // -------------------------------------------------------------------------

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata/CsvMetaDataImportTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata/CsvMetaDataImportTest.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/metadata/CsvMetaDataImportTest.java	2015-03-27 11:01:54 +0000
@@ -0,0 +1,117 @@
+package org.hisp.dhis.dxf2.metadata;
+
+/*
+ * Copyright (c) 2004-2015, 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.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.hisp.dhis.DhisSpringTest;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementService;
+import org.hisp.dhis.dxf2.common.ImportOptions;
+import org.hisp.dhis.dxf2.csv.CsvImportService;
+import org.hisp.dhis.importexport.ImportStrategy;
+import org.hisp.dhis.option.OptionService;
+import org.hisp.dhis.option.OptionSet;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class CsvMetaDataImportTest
+    extends DhisSpringTest
+{
+    @Autowired
+    private DataElementService dataElementService;
+    
+    @Autowired
+    private OptionService optionService;
+    
+    @Autowired
+    private CsvImportService csvImportService;
+    
+    @Autowired
+    private ImportService importService;
+    
+    private InputStream input;
+    
+    private final ImportOptions importOptions = new ImportOptions( ImportStrategy.NEW_AND_UPDATES );
+    
+    @Test
+    public void testDataElementImport()
+        throws Exception
+    {        
+        input = new ClassPathResource( "metadata/dataElements.csv" ).getInputStream();
+        
+        MetaData metaData = csvImportService.fromCsv( input, DataElement.class );
+        
+        assertEquals( 2, metaData.getDataElements().size() );
+        
+        ImportSummary summary = importService.importMetaData( null, metaData, importOptions );
+        
+        assertEquals( 2, summary.getImportCount().getImported() );
+        
+        Collection<DataElement> dataElements = dataElementService.getAllDataElements();
+        
+        assertEquals( 2, dataElements.size() );
+    }
+    
+    @Test
+    public void testOptionSetImport()
+        throws Exception
+    {
+        input = new ClassPathResource( "metadata/optionSets.csv" ).getInputStream();
+
+        MetaData metaData = csvImportService.fromCsv( input, OptionSet.class );
+        
+        assertEquals( 4, metaData.getOptionSets().size() );
+        assertEquals( 3, metaData.getOptionSets().get( 0 ).getOptions().size() );
+        assertEquals( 3, metaData.getOptionSets().get( 1 ).getOptions().size() );
+        assertEquals( 3, metaData.getOptionSets().get( 2 ).getOptions().size() );
+        assertEquals( 3, metaData.getOptionSets().get( 3 ).getOptions().size() );
+
+        ImportSummary summary = importService.importMetaData( null, metaData, importOptions );
+
+        assertEquals( 16, summary.getImportCount().getImported() );
+        
+        List<OptionSet> optionSets = new ArrayList<>( optionService.getAllOptionSets() );
+        
+        assertEquals( 4, optionSets.size() );
+        assertEquals( 3, optionSets.get( 0 ).getOptions().size() );
+        assertEquals( 3, optionSets.get( 1 ).getOptions().size() );
+        assertEquals( 3, optionSets.get( 2 ).getOptions().size() );
+        assertEquals( 3, optionSets.get( 3 ).getOptions().size() );
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata'
=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/dataElements.csv'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/dataElements.csv	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/dataElements.csv	2015-03-27 11:01:54 +0000
@@ -0,0 +1,3 @@
+name,uid,code,shortname,description,formname,domaintype,type,numbertype,texttype,aggregationoperator,categorycombo,url,zero
+"Women participated in skill development training",,"D0001","Women participated development training"
+"Women participated in community organizations",,"D0002","Women participated community organizations"
\ No newline at end of file

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/optionSets.csv'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/optionSets.csv	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/metadata/optionSets.csv	2015-03-27 11:01:54 +0000
@@ -0,0 +1,13 @@
+name,uid,code,optionname,optionuid,optioncode
+"Color",,"COLOR","Blue",,"BLUE"
+"Color",,"COLOR","Green",,"GREEN"
+"Color",,"COLOR","Yellow",,"YELLOW"
+"Sex",,,"Male",,"MALE"
+"Sex",,,"Female",,"FEMALE"
+"Sex",,,"Uknown",,"UNKNOWN"
+"Result",,,"High",,"HIGH"
+"Result",,,"Medium",,"MEDIUM"
+"Result",,,"Low",,"LOW"
+"Impact","cJ82jd8sd32","IMPACT","Great",,"GREAT"
+"Impact","cJ82jd8sd32","IMPACT","Medium",,"MEDIUM"
+"Impact","cJ82jd8sd32","IMPACT","Poor",,"POOR"
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/dxf2/MetaDataImportAction.java'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/dxf2/MetaDataImportAction.java	2015-02-20 15:34:16 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/dxf2/MetaDataImportAction.java	2015-03-27 11:01:54 +0000
@@ -34,6 +34,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.dataelement.CategoryOptionGroup;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOption;
@@ -67,7 +68,7 @@
 public class MetaDataImportAction
     implements Action
 {
-    private static final Map<String, Class<?>> KEY_CLASS_MAP = new HashMap<String, Class<?>>() {{
+    private static final Map<String, Class<? extends IdentifiableObject>> KEY_CLASS_MAP = new HashMap<String, Class<? extends IdentifiableObject>>() {{
        put( "dataelement", DataElement.class );
        put( "dataelementgroup", DataElementGroup.class);
        put( "categoryoption", DataElementCategoryOption.class );

=== modified file 'dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportMetaDataCsvTask.java'
--- dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportMetaDataCsvTask.java	2015-02-17 06:00:52 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportMetaDataCsvTask.java	2015-03-27 11:01:54 +0000
@@ -33,6 +33,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.dxf2.csv.CsvImportService;
 import org.hisp.dhis.dxf2.common.ImportOptions;
 import org.hisp.dhis.dxf2.metadata.ImportService;
@@ -59,12 +60,12 @@
 
     private String userUid;
     
-    private Class<?> clazz;
+    private Class<? extends IdentifiableObject> clazz;
 
     public ImportMetaDataCsvTask( String userUid, ImportService importService, 
         CsvImportService csvImportService,
         ImportOptions importOptions, InputStream inputStream,
-        TaskId taskId, Class<?> clazz )
+        TaskId taskId, Class<? extends IdentifiableObject> clazz )
     {
         this.userUid = userUid;
         this.importService = importService;

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/AddOptionSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/AddOptionSetAction.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/AddOptionSetAction.java	2015-03-27 11:01:54 +0000
@@ -60,6 +60,13 @@
     {
         this.name = name;
     }
+    
+    private String code;
+
+    public void setCode( String code )
+    {
+        this.code = code;
+    }
 
     // -------------------------------------------------------------------------------------------------
     // Action implementation
@@ -70,6 +77,7 @@
         throws Exception
     {
         OptionSet optionSet = new OptionSet( name );
+        optionSet.setCode( code );
         optionSet.setVersion( 1 );
 
         optionService.saveOptionSet( optionSet );

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/UpdateOptionSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/UpdateOptionSetAction.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/UpdateOptionSetAction.java	2015-03-27 11:01:54 +0000
@@ -69,6 +69,13 @@
         this.name = name;
     }
 
+    private String code;
+
+    public void setCode( String code )
+    {
+        this.code = code;
+    }
+
     // -------------------------------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------------------------------
@@ -79,6 +86,7 @@
     {
         OptionSet optionSet = optionService.getOptionSet( id );
         optionSet.setName( name );
+        optionSet.setCode( code );
 
         optionService.updateOptionSet( optionSet );
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/ValidateOptionSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/ValidateOptionSetAction.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/java/org/hisp/dhis/dataadmin/action/option/ValidateOptionSetAction.java	2015-03-27 11:01:54 +0000
@@ -29,6 +29,7 @@
  */
 
 import com.opensymphony.xwork2.Action;
+
 import org.hisp.dhis.i18n.I18n;
 import org.hisp.dhis.option.OptionService;
 import org.hisp.dhis.option.OptionSet;
@@ -87,6 +88,13 @@
         return message;
     }
 
+    private String code;
+
+    public void setCode( String code )
+    {
+        this.code = code;
+    }
+
     // -------------------------------------------------------------------------
     // Action implementation
     // -------------------------------------------------------------------------
@@ -94,7 +102,7 @@
     @Override
     public String execute()
     {
-        if ( name != null )
+        if ( name != null && !name.trim().isEmpty() )
         {
             OptionSet match = optionService.getOptionSetByName( name );
 
@@ -105,6 +113,19 @@
                 return ERROR;
             }
         }
+        
+
+        if ( code != null && !code.trim().isEmpty() )
+        {
+            OptionSet match = optionService.getOptionSetByCode( code );
+
+            if ( match != null && (id == null || match.getId() != id) )
+            {
+                message = i18n.getString( "code_in_use" );
+
+                return ERROR;
+            }            
+        }
 
         message = "ok";
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/addOptionSetForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/addOptionSetForm.vm	2014-08-29 11:13:12 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/addOptionSetForm.vm	2015-03-27 11:01:54 +0000
@@ -30,6 +30,10 @@
       <td><label>$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
       <td colspan="3"><input type="text" id="name" name="name" class="{validate:{required:true,minlength:2}}"></td>
     </tr>
+    <tr>
+      <td><label>$i18n.getString( "code" )</label></td>
+      <td colspan="3"><input type="text" id="code" name="code" class="{validate:{minlength:2}}"></td>
+    </tr>
 	<tr>
 	  <td></td>
 	  <td colspan="3">

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/option.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/option.vm	2015-02-06 13:00:03 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/option.vm	2015-03-27 11:01:54 +0000
@@ -61,8 +61,8 @@
           data-can-manage="$security.canManage( $option )"
           data-can-update="$security.canUpdate( $option )"
           data-can-delete="$security.canDelete( $option )">
-          <td>$encoder.htmlEncode( $!option.displayName )</td>
-          <td>$encoder.htmlEncode( $!option.code )</td>
+          <td>$!encoder.htmlEncode( $option.displayName )</td>
+          <td>$!encoder.htmlEncode( $option.code )</td>
       </tr>
       #end
       </tbody>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/updateOptionSetForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/updateOptionSetForm.vm	2014-08-29 11:13:12 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataadmin/src/main/webapp/dhis-web-maintenance-dataadmin/updateOptionSetForm.vm	2015-03-27 11:01:54 +0000
@@ -25,6 +25,10 @@
       <td><label>$i18n.getString( "name" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
       <td ><input type="text" id="name" name="name" value='$optionSet.name' class="{validate:{required:true,minlength:2}}" /></td>
     </tr>
+    <tr>
+      <td><label>$i18n.getString( "code" )</label></td>
+      <td ><input type="text" id="code" name="code" value='$!optionSet.code' class="{validate:{minlength:2}}" /></td>
+    </tr>
 	<tr>
 	  <td></td>
 	  <td colspan="2">