=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementService.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementService.java 2015-11-02 03:52:38 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementService.java 2015-11-30 17:16:26 +0000 @@ -38,6 +38,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; /** @@ -309,6 +310,16 @@ ListMap getDataElementCategoryOptionComboMap( Set dataElementUids ); Map getDataElementUidIdMap(); + + /** + * Returns all option codes of the option set associated with the data element + * with the given identifier. Returns empty if the data element does not exist + * or if the data element does not have an option set. + * + * @param id the data element identifier. + * @return a set of option codes. + */ + Optional> getOptionCodesAsSet( int id ); // ------------------------------------------------------------------------- // DataElementGroup === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java 2015-09-09 09:01:21 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java 2015-11-30 17:16:26 +0000 @@ -46,6 +46,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; /** @@ -101,6 +102,11 @@ return options.stream().map( Option::getCode ).collect( Collectors.toList() ); } + public Set getOptionCodesAsSet() + { + return options.stream().map( Option::getCode ).collect( Collectors.toSet() ); + } + public Option getOptionByCode( String code ) { for ( Option option : options ) === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java 2015-11-02 03:52:38 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataelement/DefaultDataElementService.java 2015-11-30 17:16:26 +0000 @@ -46,6 +46,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -386,6 +387,15 @@ return i18n( i18nService, dataElementStore.get( dataSet, key, max ) ); } + @Override + public Optional> getOptionCodesAsSet( int id ) + { + DataElement dataElement = getDataElement( id ); + + return dataElement != null && dataElement.hasOptionSet() ? + Optional.of( dataElement.getOptionSet().getOptionCodesAsSet() ) : Optional.empty(); + } + // ------------------------------------------------------------------------- // DataElementGroup // ------------------------------------------------------------------------- === 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 2015-11-02 17:18:46 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java 2015-11-30 17:16:26 +0000 @@ -43,6 +43,7 @@ import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import org.amplecode.quick.BatchHandler; @@ -587,6 +588,7 @@ CachingMap dataElementOrgUnitMap = new CachingMap<>(); CachingMap dataElementOpenFuturePeriodsMap = new CachingMap<>(); CachingMap orgUnitInHierarchyMap = new CachingMap<>(); + CachingMap>> dataElementOptionsMap = new CachingMap<>(); //---------------------------------------------------------------------- // Load meta-data maps @@ -774,6 +776,15 @@ continue; } + Optional> optionCodes = dataElementOptionsMap.get( dataElement.getUid(), + () -> dataElementService.getOptionCodesAsSet( dataElement.getId() ) ); + + if ( optionCodes.isPresent() && !optionCodes.get().contains( dataValue.getValue() ) ) + { + summary.getConflicts().add( new ImportConflict( dataValue.getValue(), "Data value is not a valid option of the data element option set: " + dataElement.getUid() ) ); + continue; + } + // ----------------------------------------------------------------- // Constraints // ----------------------------------------------------------------- === 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 2015-08-31 08:31:30 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/test/java/org/hisp/dhis/dxf2/datavalueset/DataValueSetServiceTest.java 2015-11-30 17:16:26 +0000 @@ -38,6 +38,7 @@ import java.util.Collection; import org.hisp.dhis.DhisSpringTest; +import org.hisp.dhis.common.IdentifiableObjectManager; import org.hisp.dhis.dataelement.DataElement; import org.hisp.dhis.dataelement.DataElementCategory; import org.hisp.dhis.dataelement.DataElementCategoryCombo; @@ -58,6 +59,8 @@ import org.hisp.dhis.mock.MockCurrentUserService; import org.hisp.dhis.mock.batchhandler.MockBatchHandler; import org.hisp.dhis.mock.batchhandler.MockBatchHandlerFactory; +import org.hisp.dhis.option.Option; +import org.hisp.dhis.option.OptionSet; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.organisationunit.OrganisationUnitService; import org.hisp.dhis.period.MonthlyPeriodType; @@ -85,10 +88,10 @@ private DataElementCategoryService categoryService; @Autowired + private OrganisationUnitService organisationUnitService; + + @Autowired private DataSetService dataSetService; - - @Autowired - private OrganisationUnitService organisationUnitService; @Autowired private PeriodService periodService; @@ -98,6 +101,9 @@ @Autowired private CompleteDataSetRegistrationService registrationService; + + @Autowired + private IdentifiableObjectManager idObjectManager; private DataElementCategoryOptionCombo ocDef; private DataElementCategoryOption categoryOptionA; @@ -107,11 +113,13 @@ private DataElementCategoryCombo categoryComboA; private DataElementCategoryOptionCombo ocA; private DataElementCategoryOptionCombo ocB; - + + private OptionSet osA; private DataElement deA; private DataElement deB; private DataElement deC; private DataElement deD; + private DataElement deE; private DataSet dsA; private OrganisationUnit ouA; private OrganisationUnit ouB; @@ -133,13 +141,18 @@ mockBatchHandlerFactory = new MockBatchHandlerFactory(); mockBatchHandlerFactory.registerBatchHandler( DataValueBatchHandler.class, mockDataValueBatchHandler ); setDependency( dataValueSetService, "batchHandlerFactory", mockBatchHandlerFactory ); - + categoryOptionA = createCategoryOption( 'A' ); categoryOptionB = createCategoryOption( 'B' ); categoryA = createDataElementCategory( 'A', categoryOptionA, categoryOptionB ); categoryComboA = createCategoryCombo( 'A', categoryA ); categoryComboDef = categoryService.getDefaultDataElementCategoryCombo(); ocDef = categoryService.getDefaultDataElementCategoryOptionCombo(); + + osA = new OptionSet( "OptionSetA" ); + osA.getOptions().add( new Option( "Blue", "1" ) ); + osA.getOptions().add( new Option( "Green", "2" ) ); + osA.getOptions().add( new Option( "Yellow", "3" ) ); ocA = createCategoryOptionCombo( categoryComboA, categoryOptionA ); ocB = createCategoryOptionCombo( categoryComboA, categoryOptionB ); @@ -147,6 +160,8 @@ deB = createDataElement( 'B', categoryComboDef ); deC = createDataElement( 'C', categoryComboDef ); deD = createDataElement( 'D', categoryComboDef ); + deE = createDataElement( 'E' ); + deE.setOptionSet( osA ); dsA = createDataSet( 'A', new MonthlyPeriodType() ); dsA.setCategoryCombo( categoryComboDef ); ouA = createOrganisationUnit( 'A' ); @@ -160,6 +175,7 @@ deA.setUid( "f7n9E0hX8qk" ); deB.setUid( "Ix2HsbDMLea" ); deC.setUid( "eY5ehpbEsB7" ); + deE.setUid( "jH26dja2f28" ); dsA.setUid( "pBOMPrpg1QX" ); ouA.setUid( "DiszpKrYNg8" ); ouB.setUid( "BdfsJfj87js" ); @@ -187,6 +203,8 @@ dataElementService.addDataElement( deB ); dataElementService.addDataElement( deC ); dataElementService.addDataElement( deD ); + + idObjectManager.save( osA ); dsA.addDataElement( deA ); dsA.addDataElement( deB ); @@ -593,6 +611,19 @@ assertEquals( ImportStatus.SUCCESS, summary.getStatus() ); } + @Test + public void testImportDataValuesInvalidOptionCode() + throws Exception + { + in = new ClassPathResource( "datavalueset/dataValueSetInvalid.xml" ).getInputStream(); + + ImportSummary summary = dataValueSetService.saveDataValueSet( in ); + + assertEquals( summary.getConflicts().toString(), 1, summary.getConflicts().size() ); + assertEquals( 2, summary.getImportCount().getImported() ); + assertEquals( ImportStatus.SUCCESS, summary.getStatus() ); + } + // ------------------------------------------------------------------------- // Supportive methods // ------------------------------------------------------------------------- === added file 'dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetInvalid.xml' --- dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetInvalid.xml 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/test/resources/datavalueset/dataValueSetInvalid.xml 2015-11-30 17:16:26 +0000 @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file