← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 16157: Refactored csv import as a service

 

------------------------------------------------------------
revno: 16157
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-07-17 15:01:11 +0200
message:
  Refactored csv import as a service
removed:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/CsvObjectUtils.java
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/
  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
modified:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.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


--
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
=== added directory 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv'
=== added 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	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/CsvImportService.java	2014-07-17 13:01:11 +0000
@@ -0,0 +1,43 @@
+package org.hisp.dhis.dxf2.csv;
+
+/*
+ * Copyright (c) 2004-2014, 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.IOException;
+import java.io.InputStream;
+
+import org.hisp.dhis.dxf2.metadata.MetaData;
+
+/**
+ * @author Lars Helge Overland
+ */
+public interface CsvImportService
+{
+    MetaData fromCsv( InputStream input, Class<?> clazz )
+        throws IOException;
+}

=== added 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	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/csv/DefaultCsvImportService.java	2014-07-17 13:01:11 +0000
@@ -0,0 +1,368 @@
+package org.hisp.dhis.dxf2.csv;
+
+/*
+ * Copyright (c) 2004-2014, 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.DateUtils.getMediumDate;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.hisp.dhis.common.BaseIdentifiableObject;
+import org.hisp.dhis.common.CodeGenerator;
+import org.hisp.dhis.common.ListMap;
+import org.hisp.dhis.dataelement.CategoryOptionGroup;
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategoryCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryOption;
+import org.hisp.dhis.dataelement.DataElementCategoryService;
+import org.hisp.dhis.dataelement.DataElementDomain;
+import org.hisp.dhis.dataelement.DataElementGroup;
+import org.hisp.dhis.dxf2.metadata.MetaData;
+import org.hisp.dhis.expression.ExpressionService;
+import org.hisp.dhis.option.OptionSet;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.csvreader.CsvReader;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class DefaultCsvImportService
+    implements CsvImportService
+{
+    @Autowired
+    private DataElementCategoryService categoryService;
+    
+    @Autowired
+    private ExpressionService expressionService;
+
+    // -------------------------------------------------------------------------
+    // CsvImportService implementation
+    // -------------------------------------------------------------------------
+
+    public MetaData fromCsv( InputStream input, Class<?> clazz )
+        throws IOException
+    {
+        CsvReader reader = new CsvReader( input, Charset.forName( "UTF-8" ) );
+        reader.readRecord(); // Ignore first row
+
+        MetaData metaData = new MetaData();
+
+        if ( DataElement.class.equals( clazz ) )
+        {
+            metaData.setDataElements( dataElementsFromCsv( reader, input ) );
+        }
+        else if ( DataElementGroup.class.equals( clazz ) )
+        {
+            metaData.setDataElementGroups( dataElementGroupsFromCsv( reader, input ) );
+        }
+        else if ( DataElementCategoryOption.class.equals( clazz ) )
+        {
+            metaData.setCategoryOptions( categoryOptionsFromCsv( reader, input ) );
+        }
+        else if ( CategoryOptionGroup.class.equals( clazz ) )
+        {
+            metaData.setCategoryOptionGroups( categoryOptionGroupsFromCsv( reader, input ) );
+        }
+        else if ( OrganisationUnit.class.equals( clazz ) )
+        {
+            metaData.setOrganisationUnits( organisationUnitsFromCsv( reader, input ) );
+        }
+        else if ( OrganisationUnitGroup.class.equals( clazz ) )
+        {
+            metaData.setOrganisationUnitGroups( organisationUnitGroupsFromCsv( reader, input ) );
+        }
+        else if ( OptionSet.class.equals( clazz ) )
+        {
+            metaData.setOptionSets( getOptionSetsFromCsv( reader, input ) );
+        }
+
+        return metaData;
+    }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    private List<DataElementCategoryOption> categoryOptionsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        List<DataElementCategoryOption> list = new ArrayList<DataElementCategoryOption>();
+
+        while ( reader.readRecord() )
+        {
+            String[] values = reader.getValues();
+
+            if ( values != null && values.length > 0 )
+            {
+                DataElementCategoryOption object = new DataElementCategoryOption();
+                setIdentifiableObject( object, values );
+                list.add( object );
+            }
+        }
+
+        return list;
+    }
+
+    private List<CategoryOptionGroup> categoryOptionGroupsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        List<CategoryOptionGroup> list = new ArrayList<CategoryOptionGroup>();
+
+        while ( reader.readRecord() )
+        {
+            String[] values = reader.getValues();
+
+            if ( values != null && values.length > 0 )
+            {
+                CategoryOptionGroup object = new CategoryOptionGroup();
+                setIdentifiableObject( object, values );
+                list.add( object );
+            }
+        }
+
+        return list;
+    }
+
+    private List<DataElement> dataElementsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        DataElementCategoryCombo categoryCombo = categoryService.getDefaultDataElementCategoryCombo();
+        
+        List<DataElement> list = new ArrayList<DataElement>();
+
+        while ( reader.readRecord() )
+        {
+            String[] values = reader.getValues();
+
+            if ( values != null && values.length > 0 )
+            {
+                DataElement object = new DataElement();
+                setIdentifiableObject( object, values );
+                object.setShortName( getSafe( values, 3, object.getName(), 50 ) );
+                object.setDescription( getSafe( values, 4, null, null ) );
+                object.setFormName( getSafe( values, 5, null, 230 ) );
+                
+                String domainType = getSafe( values, 6, DataElementDomain.AGGREGATE.getValue(), 16 );
+                object.setDomainType( DataElementDomain.fromValue( domainType ) );
+
+                object.setType( getSafe( values, 7, DataElement.VALUE_TYPE_INT, 16 ) );
+                object.setNumberType( getSafe( values, 8, DataElement.VALUE_TYPE_NUMBER, 16 ) );
+                object.setTextType( getSafe( values, 9, null, 16 ) );
+                object.setAggregationOperator( getSafe( values, 10, DataElement.AGGREGATION_OPERATOR_SUM, 16 ) );                
+                String categoryComboUid = getSafe( values, 11, null, 11 );
+                object.setUrl( getSafe( values, 12, null, 255 ) );
+                object.setZeroIsSignificant( Boolean.valueOf( getSafe( values, 13, "false", null ) ) );
+
+                if ( categoryComboUid != null )
+                {
+                    DataElementCategoryCombo cc = new DataElementCategoryCombo();
+                    cc.setUid( categoryComboUid );
+                    object.setCategoryCombo( cc );
+                }
+                else
+                {
+                    object.setCategoryCombo( categoryCombo );
+                }
+                
+                list.add( object );
+            }
+        }
+
+        return list;
+    }
+
+    private List<DataElementGroup> dataElementGroupsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        List<DataElementGroup> list = new ArrayList<DataElementGroup>();
+
+        while ( reader.readRecord() )
+        {
+            String[] values = reader.getValues();
+
+            if ( values != null && values.length > 0 )
+            {
+                DataElementGroup object = new DataElementGroup();
+                setIdentifiableObject( object, values );
+                list.add( object );
+            }
+        }
+
+        return list;
+    }
+    
+    private List<OrganisationUnit> organisationUnitsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        List<OrganisationUnit> list = new ArrayList<OrganisationUnit>();
+
+        while ( reader.readRecord() )
+        {
+            String[] values = reader.getValues();
+
+            if ( values != null && values.length > 0 )
+            {
+                OrganisationUnit object = new OrganisationUnit();
+                setIdentifiableObject( object, values );
+                String parentUid = getSafe( values, 3, null, 11 );
+                object.setShortName( getSafe( values, 4, object.getName(), 50 ) );
+                object.setDescription( getSafe( values, 5, null, null ) );
+                object.setUuid( getSafe( values, 6, null, 36 ) );
+                object.setOpeningDate( getMediumDate( getSafe( values, 7, "1970-01-01", null ) ) );
+                object.setClosedDate( getMediumDate( getSafe( values, 8, "1970-01-01", null ) ) );
+                object.setActive( true );
+                object.setComment( getSafe( values, 9, null, null ) );
+                object.setFeatureType( getSafe( values, 10, null, 50 ) );
+                object.setCoordinates( getSafe( values, 11, null, null ) );
+                object.setUrl( getSafe( values, 12, null, 255 ) );
+                object.setContactPerson( getSafe( values, 13, null, 255 ) );
+                object.setAddress( getSafe( values, 14, null, 255 ) );
+                object.setEmail( getSafe( values, 15, null, 150 ) );
+                object.setPhoneNumber( getSafe( values, 16, null, 150 ) );
+                                
+                if ( parentUid != null )
+                {
+                    OrganisationUnit parent = new OrganisationUnit();
+                    parent.setUid( parentUid );
+                    object.setParent( parent );
+                }
+
+                list.add( object );
+            }
+        }
+
+        return list;
+    }
+
+    private List<OrganisationUnitGroup> organisationUnitGroupsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        List<OrganisationUnitGroup> list = new ArrayList<OrganisationUnitGroup>();
+
+        while ( reader.readRecord() )
+        {
+            String[] values = reader.getValues();
+
+            if ( values != null && values.length > 0 )
+            {
+                OrganisationUnitGroup object = new OrganisationUnitGroup();
+                setIdentifiableObject( object, values );
+                list.add( object );
+            }
+        }
+
+        return list;
+    }
+
+    private List<OptionSet> getOptionSetsFromCsv( CsvReader reader, InputStream input )
+        throws IOException
+    {
+        ListMap<OptionSet, String> listMap = new ListMap<OptionSet, String>();
+
+        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 );
+
+                listMap.putValue( object, option );
+            }
+        }
+
+        List<OptionSet> optionSets = new ArrayList<OptionSet>();
+
+        for ( OptionSet optionSet : listMap.keySet() )
+        {
+            List<String> options = new ArrayList<String>( listMap.get( optionSet ) );
+            optionSet.setOptions( options );
+            optionSets.add( optionSet );
+        }
+
+        return optionSets;
+    }
+
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
+    /**
+     * Sets the name, uid and code properties on the given object.
+     * 
+     * @param object the object to set identifiable properties.
+     * @param values the array of property values.
+     */
+    private static void setIdentifiableObject( BaseIdentifiableObject object, String[] values )
+    {
+        object.setName( getSafe( values, 0, null, 230 ) );
+        object.setUid( getSafe( values, 1, CodeGenerator.generateCode(), 11 ) );
+        object.setCode( getSafe( values, 2, null, 50 ) );
+    }
+
+    /**
+     * Returns a string from the given array avoiding exceptions.
+     * 
+     * @param values the string array.
+     * @param index the array index of the string to get.
+     * @param defaultValue the default value in case index is out of bounds.
+     * @param maxChars the max number of characters to return for the string.
+     */
+    private static String getSafe( String[] values, int index, String defaultValue, Integer maxChars )
+    {
+        String string = null;
+
+        if ( values == null || index < 0 || index >= values.length )
+        {
+            string = defaultValue;
+        }
+        else
+        {
+            string = values[index];
+        }
+
+        string = StringUtils.defaultIfBlank( string, defaultValue );
+
+        if ( string != null )
+        {
+            return maxChars != null ? StringUtils.substring( string, 0, maxChars ) : string;
+        }
+
+        return null;
+    }
+}

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/CsvObjectUtils.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/CsvObjectUtils.java	2014-07-17 12:43:25 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/utils/CsvObjectUtils.java	1970-01-01 00:00:00 +0000
@@ -1,348 +0,0 @@
-package org.hisp.dhis.dxf2.utils;
-
-/*
- * Copyright (c) 2004-2014, 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.DateUtils.getMediumDate;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.commons.lang.StringUtils;
-import org.hisp.dhis.common.BaseIdentifiableObject;
-import org.hisp.dhis.common.CodeGenerator;
-import org.hisp.dhis.common.ListMap;
-import org.hisp.dhis.dataelement.CategoryOptionGroup;
-import org.hisp.dhis.dataelement.DataElement;
-import org.hisp.dhis.dataelement.DataElementCategoryCombo;
-import org.hisp.dhis.dataelement.DataElementCategoryOption;
-import org.hisp.dhis.dataelement.DataElementDomain;
-import org.hisp.dhis.dataelement.DataElementGroup;
-import org.hisp.dhis.dxf2.metadata.MetaData;
-import org.hisp.dhis.option.OptionSet;
-import org.hisp.dhis.organisationunit.OrganisationUnit;
-import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
-
-import com.csvreader.CsvReader;
-
-/**
- * @author Lars Helge Overland
- */
-public class CsvObjectUtils
-{
-    public static MetaData fromCsv( InputStream input, Class<?> clazz, DataElementCategoryCombo categoryCombo )
-        throws IOException
-    {
-        CsvReader reader = new CsvReader( input, Charset.forName( "UTF-8" ) );
-        reader.readRecord(); // Ignore first row
-
-        MetaData metaData = new MetaData();
-
-        if ( DataElement.class.equals( clazz ) )
-        {
-            metaData.setDataElements( dataElementsFromCsv( reader, input, categoryCombo ) );
-        }
-        else if ( DataElementGroup.class.equals( clazz ) )
-        {
-            metaData.setDataElementGroups( dataElementGroupsFromCsv( reader, input ) );
-        }
-        else if ( DataElementCategoryOption.class.equals( clazz ) )
-        {
-            metaData.setCategoryOptions( categoryOptionsFromCsv( reader, input ) );
-        }
-        else if ( CategoryOptionGroup.class.equals( clazz ) )
-        {
-            metaData.setCategoryOptionGroups( categoryOptionGroupsFromCsv( reader, input ) );
-        }
-        else if ( OrganisationUnit.class.equals( clazz ) )
-        {
-            metaData.setOrganisationUnits( organisationUnitsFromCsv( reader, input ) );
-        }
-        else if ( OrganisationUnitGroup.class.equals( clazz ) )
-        {
-            metaData.setOrganisationUnitGroups( organisationUnitGroupsFromCsv( reader, input ) );
-        }
-        else if ( OptionSet.class.equals( clazz ) )
-        {
-            metaData.setOptionSets( getOptionSetsFromCsv( reader, input ) );
-        }
-
-        return metaData;
-    }
-
-    private static List<DataElementCategoryOption> categoryOptionsFromCsv( CsvReader reader, InputStream input )
-        throws IOException
-    {
-        List<DataElementCategoryOption> list = new ArrayList<DataElementCategoryOption>();
-
-        while ( reader.readRecord() )
-        {
-            String[] values = reader.getValues();
-
-            if ( values != null && values.length > 0 )
-            {
-                DataElementCategoryOption object = new DataElementCategoryOption();
-                setIdentifiableObject( object, values );
-                list.add( object );
-            }
-        }
-
-        return list;
-    }
-
-    private static List<CategoryOptionGroup> categoryOptionGroupsFromCsv( CsvReader reader, InputStream input )
-        throws IOException
-    {
-        List<CategoryOptionGroup> list = new ArrayList<CategoryOptionGroup>();
-
-        while ( reader.readRecord() )
-        {
-            String[] values = reader.getValues();
-
-            if ( values != null && values.length > 0 )
-            {
-                CategoryOptionGroup object = new CategoryOptionGroup();
-                setIdentifiableObject( object, values );
-                list.add( object );
-            }
-        }
-
-        return list;
-    }
-
-    private static List<DataElement> dataElementsFromCsv( CsvReader reader, InputStream input, DataElementCategoryCombo categoryCombo )
-        throws IOException
-    {
-        List<DataElement> list = new ArrayList<DataElement>();
-
-        while ( reader.readRecord() )
-        {
-            String[] values = reader.getValues();
-
-            if ( values != null && values.length > 0 )
-            {
-                DataElement object = new DataElement();
-                setIdentifiableObject( object, values );
-                object.setShortName( getSafe( values, 3, object.getName(), 50 ) );
-                object.setDescription( getSafe( values, 4, null, null ) );
-                object.setFormName( getSafe( values, 5, null, 230 ) );
-                
-                String domainType = getSafe( values, 6, DataElementDomain.AGGREGATE.getValue(), 16 );
-                object.setDomainType( DataElementDomain.fromValue( domainType ) );
-
-                object.setType( getSafe( values, 7, DataElement.VALUE_TYPE_INT, 16 ) );
-                object.setNumberType( getSafe( values, 8, DataElement.VALUE_TYPE_NUMBER, 16 ) );
-                object.setTextType( getSafe( values, 9, null, 16 ) );
-                object.setAggregationOperator( getSafe( values, 10, DataElement.AGGREGATION_OPERATOR_SUM, 16 ) );                
-                String categoryComboUid = getSafe( values, 11, null, 11 );
-                object.setUrl( getSafe( values, 12, null, 255 ) );
-                object.setZeroIsSignificant( Boolean.valueOf( getSafe( values, 13, "false", null ) ) );
-
-                if ( categoryComboUid != null )
-                {
-                    DataElementCategoryCombo cc = new DataElementCategoryCombo();
-                    cc.setUid( categoryComboUid );
-                    object.setCategoryCombo( cc );
-                }
-                else
-                {
-                    object.setCategoryCombo( categoryCombo );
-                }
-                
-                list.add( object );
-            }
-        }
-
-        return list;
-    }
-
-    private static List<DataElementGroup> dataElementGroupsFromCsv( CsvReader reader, InputStream input )
-        throws IOException
-    {
-        List<DataElementGroup> list = new ArrayList<DataElementGroup>();
-
-        while ( reader.readRecord() )
-        {
-            String[] values = reader.getValues();
-
-            if ( values != null && values.length > 0 )
-            {
-                DataElementGroup object = new DataElementGroup();
-                setIdentifiableObject( object, values );
-                list.add( object );
-            }
-        }
-
-        return list;
-    }
-    
-    private static List<OrganisationUnit> organisationUnitsFromCsv( CsvReader reader, InputStream input )
-        throws IOException
-    {
-        List<OrganisationUnit> list = new ArrayList<OrganisationUnit>();
-
-        while ( reader.readRecord() )
-        {
-            String[] values = reader.getValues();
-
-            if ( values != null && values.length > 0 )
-            {
-                OrganisationUnit object = new OrganisationUnit();
-                setIdentifiableObject( object, values );
-                String parentUid = getSafe( values, 3, null, 11 );
-                object.setShortName( getSafe( values, 4, object.getName(), 50 ) );
-                object.setDescription( getSafe( values, 5, null, null ) );
-                object.setUuid( getSafe( values, 6, null, 36 ) );
-                object.setOpeningDate( getMediumDate( getSafe( values, 7, "1970-01-01", null ) ) );
-                object.setClosedDate( getMediumDate( getSafe( values, 8, "1970-01-01", null ) ) );
-                object.setActive( true );
-                object.setComment( getSafe( values, 9, null, null ) );
-                object.setFeatureType( getSafe( values, 10, null, 50 ) );
-                object.setCoordinates( getSafe( values, 11, null, null ) );
-                object.setUrl( getSafe( values, 12, null, 255 ) );
-                object.setContactPerson( getSafe( values, 13, null, 255 ) );
-                object.setAddress( getSafe( values, 14, null, 255 ) );
-                object.setEmail( getSafe( values, 15, null, 150 ) );
-                object.setPhoneNumber( getSafe( values, 16, null, 150 ) );
-                                
-                if ( parentUid != null )
-                {
-                    OrganisationUnit parent = new OrganisationUnit();
-                    parent.setUid( parentUid );
-                    object.setParent( parent );
-                }
-
-                list.add( object );
-            }
-        }
-
-        return list;
-    }
-
-    private static List<OrganisationUnitGroup> organisationUnitGroupsFromCsv( CsvReader reader, InputStream input )
-        throws IOException
-    {
-        List<OrganisationUnitGroup> list = new ArrayList<OrganisationUnitGroup>();
-
-        while ( reader.readRecord() )
-        {
-            String[] values = reader.getValues();
-
-            if ( values != null && values.length > 0 )
-            {
-                OrganisationUnitGroup object = new OrganisationUnitGroup();
-                setIdentifiableObject( object, values );
-                list.add( object );
-            }
-        }
-
-        return list;
-    }
-
-    private static List<OptionSet> getOptionSetsFromCsv( CsvReader reader, InputStream input )
-        throws IOException
-    {
-        ListMap<OptionSet, String> listMap = new ListMap<OptionSet, String>();
-
-        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 );
-
-                listMap.putValue( object, option );
-            }
-        }
-
-        List<OptionSet> optionSets = new ArrayList<OptionSet>();
-
-        for ( OptionSet optionSet : listMap.keySet() )
-        {
-            List<String> options = new ArrayList<String>( listMap.get( optionSet ) );
-            optionSet.setOptions( options );
-            optionSets.add( optionSet );
-        }
-
-        return optionSets;
-    }
-
-    // -------------------------------------------------------------------------
-    // Supportive methods
-    // -------------------------------------------------------------------------
-
-    /**
-     * Sets the name, uid and code properties on the given object.
-     * 
-     * @param object the object to set identifiable properties.
-     * @param values the array of property values.
-     */
-    private static void setIdentifiableObject( BaseIdentifiableObject object, String[] values )
-    {
-        object.setName( getSafe( values, 0, null, 230 ) );
-        object.setUid( getSafe( values, 1, CodeGenerator.generateCode(), 11 ) );
-        object.setCode( getSafe( values, 2, null, 50 ) );
-    }
-
-    /**
-     * Returns a string from the given array avoiding exceptions.
-     * 
-     * @param values the string array.
-     * @param index the array index of the string to get.
-     * @param defaultValue the default value in case index is out of bounds.
-     * @param maxChars the max number of characters to return for the string.
-     */
-    private static String getSafe( String[] values, int index, String defaultValue, Integer maxChars )
-    {
-        String string = null;
-
-        if ( values == null || index < 0 || index >= values.length )
-        {
-            string = defaultValue;
-        }
-        else
-        {
-            string = values[index];
-        }
-
-        string = StringUtils.defaultIfBlank( string, defaultValue );
-
-        if ( string != null )
-        {
-            return maxChars != null ? StringUtils.substring( string, 0, maxChars ) : string;
-        }
-
-        return null;
-    }
-}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-07-11 21:22:57 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-07-17 13:01:11 +0000
@@ -3,6 +3,8 @@
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation=
   "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd";>
 
+  <bean id="org.hisp.dhis.dxf2.csv.CsvImportService" class="org.hisp.dhis.dxf2.csv.DefaultCsvImportService" />
+
   <bean id="org.hisp.dhis.dxf2.render.RenderService" class="org.hisp.dhis.dxf2.render.DefaultRenderService" />
 
   <bean id="org.hisp.dhis.dxf2.objectfilter.ObjectFilterService" class="org.hisp.dhis.dxf2.objectfilter.DefaultObjectFilterService" />

=== modified file 'dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java'
--- dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java	2014-07-17 12:43:25 +0000
+++ dhis-2/dhis-services/dhis-service-importexport/src/main/java/org/hisp/dhis/importexport/importer/ValidationRuleImporter.java	2014-07-17 13:01:11 +0000
@@ -37,7 +37,6 @@
 
 /**
  * @author Lars Helge Overland
- * @version $Id: AbstractValidationRuleConverter.java 4646 2008-02-26 14:54:29Z larshelg $
  */
 public class ValidationRuleImporter
     extends AbstractImporter<ValidationRule> implements Importer<ValidationRule>

=== 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	2014-06-29 22:17:35 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/dxf2/MetaDataImportAction.java	2014-07-17 13:01:11 +0000
@@ -34,11 +34,11 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.dataelement.CategoryOptionGroup;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryOption;
 import org.hisp.dhis.dataelement.DataElementGroup;
+import org.hisp.dhis.dxf2.csv.CsvImportService;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
 import org.hisp.dhis.dxf2.metadata.ImportService;
 import org.hisp.dhis.importexport.ImportStrategy;
@@ -82,8 +82,8 @@
     private ImportService importService;
     
     @Autowired
-    private IdentifiableObjectManager identifiableObjectManager;
-
+    private CsvImportService csvImportService;
+    
     @Autowired
     private CurrentUserService currentUserService;
 
@@ -163,7 +163,7 @@
         
         if ( "csv".equals( importFormat ) && classKey != null && KEY_CLASS_MAP.get( classKey ) != null )
         {
-            scheduler.executeTask( new ImportMetaDataCsvTask( userId, importService, identifiableObjectManager, 
+            scheduler.executeTask( new ImportMetaDataCsvTask( userId, importService, csvImportService,
                 importOptions, in, taskId, KEY_CLASS_MAP.get( classKey ) ) );
         }
         else

=== 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	2014-06-29 22:17:35 +0000
+++ dhis-2/dhis-web/dhis-web-importexport/src/main/java/org/hisp/dhis/importexport/action/util/ImportMetaDataCsvTask.java	2014-07-17 13:01:11 +0000
@@ -33,12 +33,10 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hisp.dhis.common.IdentifiableObjectManager;
-import org.hisp.dhis.dataelement.DataElementCategoryCombo;
+import org.hisp.dhis.dxf2.csv.CsvImportService;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
 import org.hisp.dhis.dxf2.metadata.ImportService;
 import org.hisp.dhis.dxf2.metadata.MetaData;
-import org.hisp.dhis.dxf2.utils.CsvObjectUtils;
 import org.hisp.dhis.scheduling.TaskId;
 
 /**
@@ -50,8 +48,8 @@
     private static final Log log = LogFactory.getLog( ImportMetaDataTask.class );
 
     private ImportService importService;
-
-    private IdentifiableObjectManager identifiableObjectManager;
+    
+    private CsvImportService csvImportService;
     
     private ImportOptions importOptions;
 
@@ -64,13 +62,13 @@
     private Class<?> clazz;
 
     public ImportMetaDataCsvTask( String userUid, ImportService importService, 
-        IdentifiableObjectManager identifiableObjectManager,
+        CsvImportService csvImportService,
         ImportOptions importOptions, InputStream inputStream,
         TaskId taskId, Class<?> clazz )
     {
         this.userUid = userUid;
         this.importService = importService;
-        this.identifiableObjectManager = identifiableObjectManager;
+        this.csvImportService = csvImportService;
         this.importOptions = importOptions;
         this.inputStream = inputStream;
         this.taskId = taskId;
@@ -81,13 +79,10 @@
     public void run()
     {
         MetaData metaData = null;
-        
-        DataElementCategoryCombo categoryCombo = identifiableObjectManager.getByName( 
-            DataElementCategoryCombo.class, DataElementCategoryCombo.DEFAULT_CATEGORY_COMBO_NAME );
-        
+                
         try
         {
-            metaData = CsvObjectUtils.fromCsv( inputStream, clazz, categoryCombo );
+            metaData = csvImportService.fromCsv( inputStream, clazz );
         }
         catch ( IOException ex )
         {