← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 16210: Impl support for attribute option combos in data export and import

 

------------------------------------------------------------
revno: 16210
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2014-07-22 18:44:27 +0200
message:
  Impl support for attribute option combos in data export and import
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetD.xml
renamed:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValue.java => dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingJsonDataValue.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/DataValue.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingCsvDataValue.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingDataValue.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSet.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/SpringDataValueSetStore.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingDataValueSet.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValueSet.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceTest.java
  dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetB.csv
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingJsonDataValue.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
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java	2014-07-11 23:38:21 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/datavalue/DataValue.java	2014-07-22 16:44:27 +0000
@@ -248,6 +248,16 @@
 
         return result;
     }
+    
+    @Override
+    public String toString()
+    {
+        return "[Data element: " + dataElement.getUid() +
+            ", period: " + period.getUid() +
+            ", source: " + source.getUid() +
+            ", category option combo: " + categoryOptionCombo.getUid() +
+            ", attribute option combo: " + attributeOptionCombo.getUid() + "]";
+    }
 
     // -------------------------------------------------------------------------
     // Getters and setters

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/DataValue.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/DataValue.java	2014-07-10 14:16:24 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/DataValue.java	2014-07-22 16:44:27 +0000
@@ -51,6 +51,8 @@
     protected String orgUnit;
 
     protected String categoryOptionCombo;
+    
+    protected String attributeOptionCombo;
 
     protected String value;
 
@@ -132,6 +134,19 @@
     @JsonProperty
     @JsonView( { DetailedView.class, ExportView.class } )
     @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    public String getAttributeOptionCombo()
+    {
+        return attributeOptionCombo;
+    }
+    
+    public void setAttributeOptionCombo( String attributeOptionCombo )
+    {
+        this.attributeOptionCombo = attributeOptionCombo;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
     public String getValue()
     {
         return value;

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingCsvDataValue.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingCsvDataValue.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingCsvDataValue.java	2014-07-22 16:44:27 +0000
@@ -93,33 +93,39 @@
     }
 
     @Override
+    public String getAttributeOptionCombo()
+    {
+        return attributeOptionCombo = attributeOptionCombo == null ? getValue( 4 ) : attributeOptionCombo;
+    }
+    
+    @Override
     public String getValue()
     {
-        return value = value == null ? getValue( 4 ) : value;
+        return value = value == null ? getValue( 5 ) : value;
     }
 
     @Override
     public String getStoredBy()
     {
-        return storedBy = storedBy == null ? getValue( 5 ) : storedBy;
+        return storedBy = storedBy == null ? getValue( 6 ) : storedBy;
     }
 
     @Override
     public String getLastUpdated()
     {
-        return lastUpdated = lastUpdated == null ? getValue( 6 ) : lastUpdated;
+        return lastUpdated = lastUpdated == null ? getValue( 7 ) : lastUpdated;
     }
 
     @Override
     public String getComment()
     {
-        return comment = comment == null ? getValue( 7 ) : comment;
+        return comment = comment == null ? getValue( 8 ) : comment;
     }
 
     @Override
     public Boolean getFollowup()
     {
-        return followup = followup == null ? valueOf( getValue( 8 ) ) : followup;
+        return followup = followup == null ? valueOf( getValue( 9 ) ) : followup;
     }
 
     //--------------------------------------------------------------------------
@@ -151,6 +157,12 @@
     }
 
     @Override
+    public void setAttributeOptionCombo( String attributeOptionCombo )
+    {
+        values.add( attributeOptionCombo );
+    }
+
+    @Override
     public void setValue( String value )
     {
         values.add( value );
@@ -199,8 +211,8 @@
     {
         String[] headers = {
             "dataelement", "period", "orgunit",
-            "categoryoptioncombo", "value", "storedby",
-            "lastupdated", "comment", "followup" };
+            "categoryoptioncombo", "attributeoptioncombo", "value", 
+            "storedby", "lastupdated", "comment", "followup" };
 
         return headers;
     }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingDataValue.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingDataValue.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingDataValue.java	2014-07-22 16:44:27 +0000
@@ -39,6 +39,7 @@
     private static final String FIELD_DATAVALUE = "dataValue";
     private static final String FIELD_DATAELEMENT = "dataElement";
     private static final String FIELD_CATEGORY_OPTION_COMBO = "categoryOptionCombo";
+    private static final String FIELD_ATTRIBUTE_OPTION_COMBO = "attributeOptionCombo";
     private static final String FIELD_PERIOD = "period";
     private static final String FIELD_ORGUNIT = "orgUnit";
     private static final String FIELD_VALUE = "value";
@@ -94,7 +95,13 @@
     {
         return categoryOptionCombo = categoryOptionCombo == null ? reader.getAttributeValue( FIELD_CATEGORY_OPTION_COMBO ) : categoryOptionCombo;
     }
-
+    
+    @Override
+    public String getAttributeOptionCombo()
+    {
+        return attributeOptionCombo = attributeOptionCombo == null ? reader.getAttributeValue( FIELD_ATTRIBUTE_OPTION_COMBO ) : attributeOptionCombo;
+    }
+    
     @Override
     public String getValue()
     {
@@ -154,6 +161,12 @@
     }
 
     @Override
+    public void setAttributeOptionCombo( String attributeOptionCombo )
+    {
+        writer.writeAttribute( FIELD_ATTRIBUTE_OPTION_COMBO, attributeOptionCombo );
+    }
+    
+    @Override
     public void setValue( String value )
     {
         writer.writeAttribute( FIELD_VALUE, value );

=== renamed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValue.java' => 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingJsonDataValue.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValue.java	2014-07-10 14:16:24 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalue/StreamingJsonDataValue.java	2014-07-22 16:44:27 +0000
@@ -1,4 +1,4 @@
-package org.hisp.dhis.dxf2.datavalueset;
+package org.hisp.dhis.dxf2.datavalue;
 
 /*
  * Copyright (c) 2004-2014, University of Oslo
@@ -29,6 +29,7 @@
  */
 
 import com.fasterxml.jackson.core.JsonGenerator;
+
 import org.hisp.dhis.dxf2.datavalue.DataValue;
 
 import java.io.IOException;
@@ -79,6 +80,12 @@
     }
 
     @Override
+    public void setAttributeOptionCombo( String attributeOptionCombo )
+    {
+        writeObjectField( "attributeOptionCombo", attributeOptionCombo );
+    }
+    
+    @Override
     public void setValue( String value )
     {
         writeObjectField( "value", value );

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSet.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSet.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DataValueSet.java	2014-07-22 16:44:27 +0000
@@ -33,6 +33,7 @@
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
 import org.hisp.dhis.common.DxfNamespaces;
 import org.hisp.dhis.common.view.DetailedView;
 import org.hisp.dhis.common.view.ExportView;
@@ -69,6 +70,8 @@
 
     protected String orgUnit;
 
+    protected String attributeOptionCombo;
+
     protected List<DataValue> dataValues = new ArrayList<DataValue>();
 
     //--------------------------------------------------------------------------
@@ -187,6 +190,19 @@
         this.orgUnit = orgUnit;
     }
 
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0)
+    public String getAttributeOptionCombo()
+    {
+        return attributeOptionCombo;
+    }
+    
+    public void setAttributeOptionCombo( String attributeOptionCombo )
+    {
+        this.attributeOptionCombo = attributeOptionCombo;
+    }
+
     @JsonProperty(value = "dataValues")
     @JsonView({ DetailedView.class, ExportView.class })
     @JacksonXmlElementWrapper(localName = "dataValues", namespace = DxfNamespaces.DXF_2_0)

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java	2014-07-22 14:33:46 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java	2014-07-22 16:44:27 +0000
@@ -420,26 +420,39 @@
 
         importOptions = importOptions != null ? importOptions : ImportOptions.getDefaultImportOptions();
 
+        // ---------------------------------------------------------------------
+        // Options
+        // ---------------------------------------------------------------------
+
         IdentifiableProperty dataElementIdScheme = dataValueSet.getDataElementIdScheme() != null ? IdentifiableProperty.valueOf( dataValueSet.getDataElementIdScheme().toUpperCase() ) : importOptions.getDataElementIdScheme();
         IdentifiableProperty orgUnitIdScheme = dataValueSet.getOrgUnitIdScheme() != null ? IdentifiableProperty.valueOf( dataValueSet.getOrgUnitIdScheme().toUpperCase() ) : importOptions.getOrgUnitIdScheme();
         boolean dryRun = dataValueSet.getDryRun() != null ? dataValueSet.getDryRun() : importOptions.isDryRun();
         ImportStrategy strategy = dataValueSet.getStrategy() != null ? ImportStrategy.valueOf( dataValueSet.getStrategy() ) : importOptions.getImportStrategy();
         boolean skipExistingCheck = importOptions.isSkipExistingCheck();
 
+        // ---------------------------------------------------------------------
+        // Object maps
+        // ---------------------------------------------------------------------
+
         Map<String, DataElement> dataElementMap = identifiableObjectManager.getIdMap( DataElement.class, dataElementIdScheme );
         Map<String, OrganisationUnit> orgUnitMap = orgUnitIdScheme == UUID ? getUuidOrgUnitMap() : identifiableObjectManager.getIdMap( OrganisationUnit.class, orgUnitIdScheme );
         Map<String, DataElementCategoryOptionCombo> categoryOptionComboMap = identifiableObjectManager.getIdMap( DataElementCategoryOptionCombo.class, IdentifiableProperty.UID );
         Map<String, Period> periodMap = new HashMap<String, Period>();
 
+        // ---------------------------------------------------------------------
+        // Data value set
+        // ---------------------------------------------------------------------
+
+        DataElementCategoryOptionCombo fallbackCategoryOptionCombo = categoryService.getDefaultDataElementCategoryOptionCombo();
+
         DataSet dataSet = dataValueSet.getDataSet() != null ? identifiableObjectManager.getObject( DataSet.class, IdentifiableProperty.UID, dataValueSet.getDataSet() ) : null;
+        
         Date completeDate = getDefaultDate( dataValueSet.getCompleteDate() );
-
+        
         Period outerPeriod = PeriodType.getPeriodFromIsoString( trimToNull( dataValueSet.getPeriod() ) );
 
         OrganisationUnit outerOrgUnit;
 
-        DataElementCategoryOptionCombo fallbackCategoryOptionCombo = categoryService.getDefaultDataElementCategoryOptionCombo();
-
         if ( orgUnitIdScheme.equals( IdentifiableProperty.UUID ) )
         {
             outerOrgUnit = dataValueSet.getOrgUnit() == null ? null : organisationUnitService.getOrganisationUnitByUuid( trimToNull( dataValueSet.getOrgUnit() ) );
@@ -449,6 +462,9 @@
             outerOrgUnit = dataValueSet.getOrgUnit() != null ? identifiableObjectManager.getObject( OrganisationUnit.class, orgUnitIdScheme, trimToNull( dataValueSet.getOrgUnit() ) ) : null;
         }
 
+        DataElementCategoryOptionCombo outerAttrOptionCombo = dataValueSet.getAttributeOptionCombo() != null ? 
+            identifiableObjectManager.getObject( DataElementCategoryOptionCombo.class, IdentifiableProperty.UID, trimToNull( dataValueSet.getAttributeOptionCombo() ) ) : null;
+        
         if ( dataSet != null && completeDate != null )
         {
             notifier.notify( id, "Completing data set" );
@@ -458,7 +474,7 @@
         {
             summary.setDataSetComplete( Boolean.FALSE.toString() );
         }
-
+        
         String currentUser = currentUserService.getCurrentUsername();
 
         BatchHandler<DataValue> batchHandler = batchHandlerFactory.createBatchHandler( DataValueBatchHandler.class ).init();
@@ -467,6 +483,10 @@
         int updateCount = 0;
         int totalCount = 0;
 
+        // ---------------------------------------------------------------------
+        // Data values
+        // ---------------------------------------------------------------------
+
         notifier.notify( id, "Importing data values" );
         log.info( "importing data values" );
 
@@ -479,9 +499,10 @@
             totalCount++;
 
             DataElement dataElement = dataElementMap.get( trimToNull( dataValue.getDataElement() ) );
-            DataElementCategoryOptionCombo categoryOptionCombo = categoryOptionComboMap.get( trimToNull( dataValue.getCategoryOptionCombo() ) );
             Period period = outerPeriod != null ? outerPeriod : PeriodType.getPeriodFromIsoString( trimToNull( dataValue.getPeriod() ) );
             OrganisationUnit orgUnit = outerOrgUnit != null ? outerOrgUnit : orgUnitMap.get( trimToNull( dataValue.getOrgUnit() ) );
+            DataElementCategoryOptionCombo categoryOptionCombo = categoryOptionComboMap.get( trimToNull( dataValue.getCategoryOptionCombo() ) );
+            DataElementCategoryOptionCombo attrOptionCombo = outerAttrOptionCombo != null ? outerAttrOptionCombo : categoryOptionComboMap.get( trimToNull( dataValue.getAttributeOptionCombo() ) );
 
             if ( dataElement == null )
             {
@@ -505,6 +526,11 @@
             {
                 categoryOptionCombo = fallbackCategoryOptionCombo;
             }
+            
+            if ( attrOptionCombo == null )
+            {
+                attrOptionCombo = fallbackCategoryOptionCombo;
+            }
 
             if ( dataValue.getValue() == null && dataValue.getComment() == null )
             {
@@ -541,7 +567,7 @@
             internalValue.setPeriod( period );
             internalValue.setSource( orgUnit );
             internalValue.setCategoryOptionCombo( categoryOptionCombo );
-            internalValue.setAttributeOptionCombo( fallbackCategoryOptionCombo ); // TODO
+            internalValue.setAttributeOptionCombo( attrOptionCombo );
             internalValue.setValue( trimToNull( dataValue.getValue() ) );
 
             if ( dataValue.getStoredBy() == null || dataValue.getStoredBy().trim().isEmpty() )

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/SpringDataValueSetStore.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/SpringDataValueSetStore.java	2014-07-10 16:06:48 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/SpringDataValueSetStore.java	2014-07-22 16:44:27 +0000
@@ -100,13 +100,14 @@
         DataValueSet dataValueSet = new StreamingJsonDataValueSet( outputStream );
         
         final String sql =
-            "select de.uid as deuid, pe.startdate, pt.name, ou.uid as ouuid, coc.uid as cocuid, dv.value, dv.storedby, dv.created, dv.lastupdated, dv.comment, dv.followup " +
+            "select de.uid as deuid, pe.startdate, pt.name, ou.uid as ouuid, coc.uid as cocuid, aoc.uid as aocuid, dv.value, dv.storedby, dv.created, dv.lastupdated, dv.comment, dv.followup " +
             "from datavalue dv " +
             "join dataelement de on (dv.dataelementid=de.dataelementid) " +
             "join period pe on (dv.periodid=pe.periodid) " +
             "join periodtype pt on (pe.periodtypeid=pt.periodtypeid) " +
             "join organisationunit ou on (dv.sourceid=ou.organisationunitid) " +
             "join categoryoptioncombo coc on (dv.categoryoptioncomboid=coc.categoryoptioncomboid) " +
+            "join categoryoptioncombo aoc on (dv.attributeoptioncomboid=aoc.categoryoptioncomboid) " +
             "where dv.lastupdated >= '" + DateUtils.getLongDateString( lastUpdated ) + "'";
         
         SqlRowSet rowSet = jdbcTemplate.queryForRowSet( sql );
@@ -147,6 +148,7 @@
             dataValue.setPeriod( isoPeriod.getIsoDate() );
             dataValue.setOrgUnit( rowSet.getString( "ouuid" ) );
             dataValue.setCategoryOptionCombo( rowSet.getString( "cocuid" ) );
+            dataValue.setAttributeOptionCombo( rowSet.getString( "aocuid" ) );
             dataValue.setValue( rowSet.getString( "value" ) );
             dataValue.setStoredBy( rowSet.getString( "storedby" ) );
             dataValue.setCreated( DateUtils.getLongDateString( rowSet.getDate( "created" ) ) );
@@ -162,13 +164,14 @@
     private String getDataValueSql( Collection<DataElement> dataElements, Collection<Period> periods, Collection<OrganisationUnit> orgUnits )
     {
         return
-            "select de.uid as deuid, pe.startdate, pt.name, ou.uid as ouuid, coc.uid as cocuid, dv.value, dv.storedby, dv.created, dv.lastupdated, dv.comment, dv.followup " +
+            "select de.uid as deuid, pe.startdate, pt.name, ou.uid as ouuid, coc.uid as cocuid, aoc.uid as aocuid, dv.value, dv.storedby, dv.created, dv.lastupdated, dv.comment, dv.followup " +
             "from datavalue dv " +
             "join dataelement de on (dv.dataelementid=de.dataelementid) " +
             "join period pe on (dv.periodid=pe.periodid) " +
             "join periodtype pt on (pe.periodtypeid=pt.periodtypeid) " +
             "join organisationunit ou on (dv.sourceid=ou.organisationunitid) " +
             "join categoryoptioncombo coc on (dv.categoryoptioncomboid=coc.categoryoptioncomboid) " +
+            "join categoryoptioncombo aoc on (dv.attributeoptioncomboid=aoc.categoryoptioncomboid) " +
             "where dv.dataelementid in (" + getCommaDelimitedString( getIdentifiers( DataElement.class, dataElements ) ) + ") " +
             "and dv.periodid in (" + getCommaDelimitedString( getIdentifiers( Period.class, periods ) ) + ") " +
             "and dv.sourceid in (" + getCommaDelimitedString( getIdentifiers( OrganisationUnit.class, orgUnits ) ) + ")";

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingDataValueSet.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingDataValueSet.java	2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingDataValueSet.java	2014-07-22 16:44:27 +0000
@@ -51,6 +51,7 @@
     private static final String FIELD_COMPLETEDATE = "completeDate";
     private static final String FIELD_PERIOD = "period";
     private static final String FIELD_ORGUNIT = "orgUnit";
+    private static final String FIELD_ATTRIBUTE_OPTION_COMBO = "attributeOptionCombo";
 
     private XMLWriter writer;
 
@@ -128,6 +129,12 @@
     }
 
     @Override
+    public String getAttributeOptionCombo()
+    {
+        return attributeOptionCombo = attributeOptionCombo == null ? reader.getAttributeValue( FIELD_ATTRIBUTE_OPTION_COMBO ) : attributeOptionCombo;
+    }
+    
+    @Override
     public boolean hasNextDataValue()
     {
         return reader.moveToStartElement( FIELD_DATAVALUE, FIELD_DATAVALUESET );
@@ -178,7 +185,7 @@
     {
         writer.writeAttribute( FIELD_ORGUNIT, orgUnit );
     }
-
+    
     @Override
     public DataValue getDataValueInstance()
     {

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValueSet.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValueSet.java	2014-05-05 18:01:22 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/StreamingJsonDataValueSet.java	2014-07-22 16:44:27 +0000
@@ -29,11 +29,13 @@
  */
 
 import com.fasterxml.jackson.core.JsonGenerator;
+
 import org.hisp.dhis.dxf2.datavalue.DataValue;
 import org.hisp.dhis.dxf2.utils.JacksonUtils;
 
 import java.io.IOException;
 import java.io.OutputStream;
+import org.hisp.dhis.dxf2.datavalue.StreamingJsonDataValue;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -92,6 +94,12 @@
     }
 
     @Override
+    public void setAttributeOptionCombo( String attributeOptionCombo )
+    {
+        writeObjectField( "attributeOptionCombo", attributeOptionCombo );
+    }
+
+    @Override
     public DataValue getDataValueInstance()
     {
         if ( !startedArray )

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceTest.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceTest.java	2014-06-23 21:31:31 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceTest.java	2014-07-22 16:44:27 +0000
@@ -40,6 +40,9 @@
 
 import org.hisp.dhis.DhisTest;
 import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.dataelement.DataElementCategory;
+import org.hisp.dhis.dataelement.DataElementCategoryCombo;
+import org.hisp.dhis.dataelement.DataElementCategoryOption;
 import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo;
 import org.hisp.dhis.dataelement.DataElementCategoryService;
 import org.hisp.dhis.dataelement.DataElementService;
@@ -56,6 +59,7 @@
 import org.hisp.dhis.period.MonthlyPeriodType;
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
+import org.hisp.dhis.period.PeriodType;
 import org.junit.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ClassPathResource;
@@ -86,16 +90,24 @@
     
     @Autowired
     private CompleteDataSetRegistrationService registrationService;
+
+    private DataElementCategoryOptionCombo ocDef;
+    private DataElementCategoryOption categoryOptionA;
+    private DataElementCategoryOption categoryOptionB;
+    private DataElementCategory categoryA;
+    private DataElementCategoryCombo categoryComboA;
+    private DataElementCategoryOptionCombo ocA;
+    private DataElementCategoryOptionCombo ocB;
     
     private DataElement deA;
     private DataElement deB;
     private DataElement deC;
+    private DataElement deD;
     private DataSet dsA;
     private OrganisationUnit ouA;
     private OrganisationUnit ouB;
     private Period peA;
     private Period peB;
-    private DataElementCategoryOptionCombo optionComboA;
     
     @Override
     public boolean emptyDatabaseAfterTest()
@@ -106,16 +118,26 @@
     @Override
     public void setUpTest()
     {
+        categoryOptionA = createCategoryOption( 'A' );
+        categoryOptionB = createCategoryOption( 'B' );
+        categoryA = createDataElementCategory( 'A', categoryOptionA, categoryOptionB );
+        categoryComboA = createCategoryCombo( 'A', categoryA );
+        ocDef = categoryService.getDefaultDataElementCategoryOptionCombo();
+        
+        ocA = createCategoryOptionCombo( categoryComboA, categoryOptionA );
+        ocB = createCategoryOptionCombo( categoryComboA, categoryOptionB );
         deA = createDataElement( 'A' );
         deB = createDataElement( 'B' );
         deC = createDataElement( 'C' );
+        deD = createDataElement( 'D' );
         dsA = createDataSet( 'A', new MonthlyPeriodType() );
         ouA = createOrganisationUnit( 'A' );
         ouB = createOrganisationUnit( 'B' );
-        peA = createPeriod( getDate( 2012, 1, 1 ), getDate( 2012, 1, 31 ) );
-        peB = createPeriod( getDate( 2012, 2, 1 ), getDate( 2012, 2, 29 ) );
-        optionComboA = categoryService.getDefaultDataElementCategoryOptionCombo();
-        
+        peA = createPeriod( PeriodType.getByNameIgnoreCase( MonthlyPeriodType.NAME ), getDate( 2012, 1, 1 ), getDate( 2012, 1, 31 ) );
+        peB = createPeriod( PeriodType.getByNameIgnoreCase( MonthlyPeriodType.NAME ), getDate( 2012, 2, 1 ), getDate( 2012, 2, 29 ) );
+
+        ocA.setUid( "kjuiHgy67hg" );
+        ocB.setUid( "Gad33qy67g5" );
         deA.setUid( "f7n9E0hX8qk" );
         deB.setUid( "Ix2HsbDMLea" );
         deC.setUid( "eY5ehpbEsB7" );
@@ -123,21 +145,32 @@
         ouA.setUid( "DiszpKrYNg8" );
         ouB.setUid( "BdfsJfj87js" );
 
+        ocA.setCode( "OC_A" );
+        ocB.setCode( "OC_B" );
         deA.setCode( "DE_A" );
         deB.setCode( "DE_B" );
         deC.setCode( "DE_C" );
+        deD.setCode( "DE_D" );
         dsA.setCode( "DS_A" );
         ouA.setCode( "OU_A" );
         ouB.setCode( "OU_B" );
+
+        categoryService.addDataElementCategoryOption( categoryOptionA );
+        categoryService.addDataElementCategoryOption( categoryOptionB );
+        categoryService.addDataElementCategory( categoryA );
+        categoryService.addDataElementCategoryCombo( categoryComboA );
+        categoryService.addDataElementCategoryOptionCombo( ocA );
+        categoryService.addDataElementCategoryOptionCombo( ocB );
         
         dataElementService.addDataElement( deA );
         dataElementService.addDataElement( deB );
         dataElementService.addDataElement( deC );
+        dataElementService.addDataElement( deD );
         dataSetService.addDataSet( dsA );
         organisationUnitService.addOrganisationUnit( ouA );
         organisationUnitService.addOrganisationUnit( ouB );
         periodService.addPeriod( peA );
-        periodService.addPeriod( peB );
+        periodService.addPeriod( peB );        
     }
     
     @Test
@@ -153,11 +186,11 @@
         
         assertNotNull( dataValues );
         assertEquals( 3, dataValues.size() );
-        assertTrue( dataValues.contains( new DataValue( deA, peA, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deB, peA, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deC, peA, ouA, optionComboA, optionComboA ) ) );
+        assertTrue( dataValues.contains( new DataValue( deA, peA, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deB, peA, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deC, peA, ouA, ocDef, ocDef ) ) );
         
-        CompleteDataSetRegistration registration = registrationService.getCompleteDataSetRegistration( dsA, peA, ouA, optionComboA );
+        CompleteDataSetRegistration registration = registrationService.getCompleteDataSetRegistration( dsA, peA, ouA, ocDef );
         
         assertNotNull( registration );
         assertEquals( dsA, registration.getDataSet() );
@@ -204,18 +237,18 @@
 
         assertNotNull( dataValues );
         assertEquals( 12, dataValues.size() );
-        assertTrue( dataValues.contains( new DataValue( deA, peA, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deA, peA, ouB, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deA, peB, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deA, peB, ouB, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deB, peA, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deB, peA, ouB, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deB, peB, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deB, peB, ouB, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deC, peA, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deC, peA, ouB, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deC, peB, ouA, optionComboA, optionComboA ) ) );
-        assertTrue( dataValues.contains( new DataValue( deC, peB, ouB, optionComboA, optionComboA ) ) );        
+        assertTrue( dataValues.contains( new DataValue( deA, peA, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deA, peA, ouB, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deA, peB, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deA, peB, ouB, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deB, peA, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deB, peA, ouB, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deB, peB, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deB, peB, ouB, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deC, peA, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deC, peA, ouB, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deC, peB, ouA, ocDef, ocDef ) ) );
+        assertTrue( dataValues.contains( new DataValue( deC, peB, ouB, ocDef, ocDef ) ) );        
     }
     
     @Test
@@ -257,4 +290,19 @@
         assertNotNull( dataValues );
         assertEquals( 3, dataValues.size() );
     }
+    
+    @Test
+    public void testImportDataValuesWithAttributeOptionCombo()
+        throws Exception
+    {
+        dataValueSetService.saveDataValueSet( new ClassPathResource( "datavalueset/dataValueSetD.xml" ).getInputStream() );
+        
+        Collection<DataValue> dataValues = dataValueService.getAllDataValues();
+        
+        assertNotNull( dataValues );
+        assertEquals( 3, dataValues.size() );
+        assertTrue( dataValues.contains( new DataValue( deA, peA, ouA, ocDef, ocA ) ) );
+        assertTrue( dataValues.contains( new DataValue( deB, peA, ouA, ocDef, ocA ) ) );
+        assertTrue( dataValues.contains( new DataValue( deC, peA, ouA, ocDef, ocA ) ) );        
+    }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetB.csv'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetB.csv	2012-04-15 14:52:54 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetB.csv	2014-07-22 16:44:27 +0000
@@ -1,13 +1,13 @@
-"dataelelement","period","orgunit","categoryoptioncombo","value","storedby","timestamp","comment","followup"
-"f7n9E0hX8qk","201201","DiszpKrYNg8","","10001","john","2012-01-01","comment","false"
-"f7n9E0hX8qk","201201","BdfsJfj87js","","10002","john","2012-01-01","comment","false"
-"f7n9E0hX8qk","201202","DiszpKrYNg8","","10003","john","2012-01-01","comment","false"
-"f7n9E0hX8qk","201202","BdfsJfj87js","","10004","john","2012-01-01","comment","false"
-"Ix2HsbDMLea","201201","DiszpKrYNg8","","10005","john","2012-01-01","comment","false"
-"Ix2HsbDMLea","201201","BdfsJfj87js","","10006","john","2012-01-01","comment","false"
-"Ix2HsbDMLea","201202","DiszpKrYNg8","","10007","john","2012-01-01","comment","false"
-"Ix2HsbDMLea","201202","BdfsJfj87js","","10008","john","2012-01-01","comment","false"
-"eY5ehpbEsB7","201201","DiszpKrYNg8","","10009","john","2012-01-01","comment","false"
-"eY5ehpbEsB7","201201","BdfsJfj87js","","10010","john","2012-01-01","comment","false"
-"eY5ehpbEsB7","201202","DiszpKrYNg8","","10011","john","2012-01-01","comment","false"
-"eY5ehpbEsB7","201202","BdfsJfj87js","","10012","john","2012-01-01","comment","false"
\ No newline at end of file
+"dataelelement","period","orgunit","categoryoptioncombo","attributeoptioncombo","value","storedby","timestamp","comment","followup"
+"f7n9E0hX8qk","201201","DiszpKrYNg8","","","10001","john","2012-01-01","comment","false"
+"f7n9E0hX8qk","201201","BdfsJfj87js","","","10002","john","2012-01-01","comment","false"
+"f7n9E0hX8qk","201202","DiszpKrYNg8","","","10003","john","2012-01-01","comment","false"
+"f7n9E0hX8qk","201202","BdfsJfj87js","","","10004","john","2012-01-01","comment","false"
+"Ix2HsbDMLea","201201","DiszpKrYNg8","","","10005","john","2012-01-01","comment","false"
+"Ix2HsbDMLea","201201","BdfsJfj87js","","","10006","john","2012-01-01","comment","false"
+"Ix2HsbDMLea","201202","DiszpKrYNg8","","","10007","john","2012-01-01","comment","false"
+"Ix2HsbDMLea","201202","BdfsJfj87js","","","10008","john","2012-01-01","comment","false"
+"eY5ehpbEsB7","201201","DiszpKrYNg8","","","10009","john","2012-01-01","comment","false"
+"eY5ehpbEsB7","201201","BdfsJfj87js","","","10010","john","2012-01-01","comment","false"
+"eY5ehpbEsB7","201202","DiszpKrYNg8","","","10011","john","2012-01-01","comment","false"
+"eY5ehpbEsB7","201202","BdfsJfj87js","","","10012","john","2012-01-01","comment","false"
\ No newline at end of file

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetD.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetD.xml	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetD.xml	2014-07-22 16:44:27 +0000
@@ -0,0 +1,5 @@
+<dataValueSet xmlns="http://dhis2.org/schema/dxf/2.0"; dataSet="pBOMPrpg1QX" completeDate="2012-01-09" period="201201" orgUnit="DiszpKrYNg8" attributeOptionCombo="kjuiHgy67hg">
+    <dataValue dataElement="f7n9E0hX8qk" value="10001" storedBy="john" timestamp="2012-01-01" comment="comment" followup="false"/>
+    <dataValue dataElement="Ix2HsbDMLea" value="10002" storedBy="john" timestamp="2012-01-02" comment="comment" followup="false"/>
+    <dataValue dataElement="eY5ehpbEsB7" value="10003" storedBy="john" timestamp="2012-01-03" comment="comment" followup="false"/>
+</dataValueSet>
\ No newline at end of file