=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/AdxDataService.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/AdxDataService.java 2016-01-04 02:27:49 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/AdxDataService.java 2016-01-06 11:26:52 +0000 @@ -55,6 +55,7 @@ String DATAVALUE = "dataValue"; String VALUE = "value"; String ANNOTATION = "annotation"; + String ERROR = "error"; //-------------------------------------------------------------------------- // DHIS 2 specific constants === added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/AdxDataSetMetadata.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/AdxDataSetMetadata.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/AdxDataSetMetadata.java 2016-01-06 11:26:52 +0000 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015, UiO + * 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. + * + * 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 HOLDER 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. + */ +package org.hisp.dhis.dxf2.adx; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import org.apache.xerces.util.XMLChar; +import org.hisp.dhis.dataelement.DataElement; +import org.hisp.dhis.dataelement.DataElementCategory; +import org.hisp.dhis.dataelement.DataElementCategoryCombo; +import org.hisp.dhis.dataelement.DataElementCategoryOptionCombo; +import org.hisp.dhis.dataset.DataSet; + +/** + * + * @author bobj + */ +public class AdxDataSetMetadata { + + private final DataSet dataSet; + + // lookup categoryoptions per catoptcombo + private final Map> categoryOptionMap; + + AdxDataSetMetadata(DataSet dataSet) throws AdxException + { + this.dataSet = dataSet; + + categoryOptionMap = new HashMap<>(); + + Set catCombos = new HashSet<>(); + + catCombos.add(dataSet.getCategoryCombo()); + for (DataElement dataElement : dataSet.getDataElements()) + { + catCombos.add(dataElement.getCategoryCombo()); + } + + for (DataElementCategoryCombo categoryCombo : catCombos) + { + for (DataElementCategoryOptionCombo catOptCombo : categoryCombo.getOptionCombos()) + { + addExplodedCategoryAttributes(catOptCombo); + } + } + } + + private void addExplodedCategoryAttributes( DataElementCategoryOptionCombo coc ) + throws AdxException + { + Map categoryAttributes = new HashMap<>(); + + if (!coc.isDefault()) + { + for (DataElementCategory category : coc.getCategoryCombo().getCategories()) + { + String categoryCode = category.getCode(); + if (categoryCode == null || !XMLChar.isValidName(categoryCode)) { + throw new AdxException( + "Category code for " + category.getName() + " is missing or invalid: " + categoryCode); + } + + String catOptCode = category.getCategoryOption(coc).getCode(); + if (catOptCode == null || catOptCode.isEmpty()) { + throw new AdxException( + "CategoryOption code for " + category.getCategoryOption(coc).getName() + " is missing"); + } + + categoryAttributes.put(categoryCode, catOptCode); + } + } + + categoryOptionMap.put(coc.getId(), categoryAttributes); + } + + public Map getExplodedCategoryAttributes( int cocId ) + { + return this.categoryOptionMap.get(cocId); + } + +} === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/DefaultAdxDataService.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/DefaultAdxDataService.java 2016-01-04 02:27:49 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/adx/DefaultAdxDataService.java 2016-01-06 11:26:52 +0000 @@ -127,13 +127,6 @@ @Override public void writeDataValueSet( DataExportParams params, OutputStream out ) { - // TODO: defensive code around possible missing CODEs - - //TODO: Use dhis commons CachingMap - - // caching map used to lookup category attributes per cat opt combo - Map> catOptMap = new HashMap<>(); - XMLWriter adxWriter = XMLFactory.getXMLWriter( out ); adxWriter.openElement( AdxDataService.ROOT ); @@ -141,6 +134,17 @@ for ( DataSet dataSet : params.getDataSets() ) { + AdxDataSetMetadata metadata; + try + { + metadata = new AdxDataSetMetadata(dataSet); + } catch (AdxException ex) + { + log.info("Export failed for dataset: " + dataSet.getName()); + log.info("Error: " + ex.getMessage()); + continue; + } + DataElementCategoryCombo categoryCombo = dataSet.getCategoryCombo(); List categories = categoryCombo.getCategories(); @@ -149,20 +153,8 @@ { Set catopts = aoc.getCategoryOptions(); - Map attributeDimensions; - - int aocId = aoc.getId(); - - if ( catOptMap.containsKey( aocId ) ) - { - attributeDimensions = catOptMap.get( aocId ); - } - else - { - attributeDimensions = getExplodedCategoryAttributes( aoc ); - catOptMap.put( aocId, attributeDimensions ); - } - + Map attributeDimensions = metadata.getExplodedCategoryAttributes(aoc.getId()); + for ( OrganisationUnit orgUnit : params.getOrganisationUnits() ) { for ( Period period : params.getPeriods() ) @@ -182,23 +174,11 @@ { adxWriter.openElement( AdxDataService.DATAVALUE ); - Map dvDimensions = getExplodedCategoryAttributes( dv.getCategoryOptionCombo() ); - adxWriter.writeAttribute( AdxDataService.DATAELEMENT, dv.getDataElement().getCode() ); DataElementCategoryOptionCombo coc = dv.getCategoryOptionCombo(); - Map categoryDimensions; - int cocId = coc.getId(); - if ( catOptMap.containsKey( cocId ) ) - { - categoryDimensions = catOptMap.get( cocId ); - } - else - { - categoryDimensions = getExplodedCategoryAttributes( coc ); - catOptMap.put( cocId, categoryDimensions ); - } + Map categoryDimensions = metadata.getExplodedCategoryAttributes(coc.getId()); for ( String attribute : categoryDimensions.keySet() ) { @@ -555,16 +535,6 @@ log.debug( "DXF attributes: " + attributes ); } - private Map getExplodedCategoryAttributes( DataElementCategoryOptionCombo coc ) - { - Map categoryAttributes = new HashMap<>(); - for ( DataElementCategory category : coc.getCategoryCombo().getCategories() ) - { - categoryAttributes.put( category.getCode(), category.getCategoryOption( coc ).getCode() ); - } - return categoryAttributes; - } - private Map> createCatOptMap() { Map> catOptMap = new HashMap<>();