=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java 2012-04-20 18:31:48 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryCombo.java 2012-04-22 16:16:24 +0000 @@ -152,7 +152,6 @@ } //TODO update category option -> category option combo association - public void generateOptionCombos() { this.optionCombos = new HashSet( generateOptionCombosList() ); === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java 2012-04-20 18:31:48 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataelement/DataElementCategoryOption.java 2012-04-22 16:16:24 +0000 @@ -39,6 +39,7 @@ import org.hisp.dhis.common.Dxf2Namespace; import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.view.DetailedView; +import org.hisp.dhis.common.view.ExportView; import org.hisp.dhis.concept.Concept; import java.util.HashSet; @@ -166,6 +167,10 @@ this.category = category; } + @JsonProperty + @JsonSerialize( contentAs = BaseIdentifiableObject.class ) + @JsonView( {DetailedView.class, ExportView.class} ) + @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE ) public Concept getConcept() { return concept; === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java 2012-04-18 20:24:12 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnit.java 2012-04-22 16:16:24 +0000 @@ -94,15 +94,6 @@ private String url; - @Scanned - private Set groups = new HashSet(); - - @Scanned - private Set dataSets = new HashSet(); - - @Scanned - private Set users = new HashSet(); - private String contactPerson; private String address; @@ -113,6 +104,12 @@ private boolean hasPatients; + private Set groups = new HashSet(); + + private Set dataSets = new HashSet(); + + private Set users = new HashSet(); + /** * Set of the dynamic attributes values that belong to this * organisationUnit. @@ -695,51 +692,6 @@ this.url = url; } - @JsonProperty( value = "organisationUnitGroups" ) - @JsonSerialize( contentAs = BaseIdentifiableObject.class ) - @JsonView( {DetailedView.class} ) - @JacksonXmlElementWrapper( localName = "organisationUnitGroups", namespace = Dxf2Namespace.NAMESPACE ) - @JacksonXmlProperty( localName = "organisationUnitGroup", namespace = Dxf2Namespace.NAMESPACE ) - public Set getGroups() - { - return groups; - } - - public void setGroups( Set groups ) - { - this.groups = groups; - } - - @JsonProperty - @JsonSerialize( contentAs = BaseIdentifiableObject.class ) - @JsonView( {DetailedView.class} ) - @JacksonXmlElementWrapper( localName = "dataSets", namespace = Dxf2Namespace.NAMESPACE ) - @JacksonXmlProperty( localName = "dataSet", namespace = Dxf2Namespace.NAMESPACE ) - public Set getDataSets() - { - return dataSets; - } - - public void setDataSets( Set dataSets ) - { - this.dataSets = dataSets; - } - - @JsonProperty - @JsonSerialize( contentAs = BaseIdentifiableObject.class ) - @JsonView( {DetailedView.class} ) - @JacksonXmlElementWrapper( localName = "users", namespace = Dxf2Namespace.NAMESPACE ) - @JacksonXmlProperty( localName = "user", namespace = Dxf2Namespace.NAMESPACE ) - public Set getUsers() - { - return users; - } - - public void setUsers( Set users ) - { - this.users = users; - } - @JsonProperty @JsonView( {DetailedView.class, ExportView.class} ) @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE ) @@ -818,6 +770,51 @@ this.type = type; } + @JsonProperty( value = "organisationUnitGroups" ) + @JsonSerialize( contentAs = BaseIdentifiableObject.class ) + @JsonView( {DetailedView.class} ) + @JacksonXmlElementWrapper( localName = "organisationUnitGroups", namespace = Dxf2Namespace.NAMESPACE ) + @JacksonXmlProperty( localName = "organisationUnitGroup", namespace = Dxf2Namespace.NAMESPACE ) + public Set getGroups() + { + return groups; + } + + public void setGroups( Set groups ) + { + this.groups = groups; + } + + @JsonProperty + @JsonSerialize( contentAs = BaseIdentifiableObject.class ) + @JsonView( {DetailedView.class} ) + @JacksonXmlElementWrapper( localName = "dataSets", namespace = Dxf2Namespace.NAMESPACE ) + @JacksonXmlProperty( localName = "dataSet", namespace = Dxf2Namespace.NAMESPACE ) + public Set getDataSets() + { + return dataSets; + } + + public void setDataSets( Set dataSets ) + { + this.dataSets = dataSets; + } + + @JsonProperty + @JsonSerialize( contentAs = BaseIdentifiableObject.class ) + @JsonView( {DetailedView.class} ) + @JacksonXmlElementWrapper( localName = "users", namespace = Dxf2Namespace.NAMESPACE ) + @JacksonXmlProperty( localName = "user", namespace = Dxf2Namespace.NAMESPACE ) + public Set getUsers() + { + return users; + } + + public void setUsers( Set users ) + { + this.users = users; + } + @JsonProperty( value = "attributes" ) @JsonView( {DetailedView.class, ExportView.class} ) @JacksonXmlElementWrapper( localName = "attributes", namespace = Dxf2Namespace.NAMESPACE ) === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java 2012-04-20 18:31:48 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitGroupSet.java 2012-04-22 16:16:24 +0000 @@ -57,13 +57,13 @@ private static final Comparator COMPARATOR = new IdentifiableObjectNameComparator(); + private String description; + + private boolean compulsory; + @Scanned private Set organisationUnitGroups = new HashSet(); - private String description; - - private boolean compulsory; - // ------------------------------------------------------------------------- // Constructors // ------------------------------------------------------------------------- === modified file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultImportService.java' --- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultImportService.java 2012-04-21 11:45:47 +0000 +++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultImportService.java 2012-04-22 16:16:24 +0000 @@ -29,6 +29,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.hisp.dhis.cache.HibernateCacheManager; import org.hisp.dhis.dxf2.importsummary.ImportConflict; import org.hisp.dhis.dxf2.importsummary.ImportCount; import org.hisp.dhis.dxf2.importsummary.ImportSummary; @@ -36,6 +37,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -57,6 +59,12 @@ @Autowired( required = false ) private Set importerClasses = new HashSet(); + @Autowired + private ObjectBridge objectBridge; + + @Autowired + private HibernateCacheManager cacheManager; + //------------------------------------------------------------------------------------------------------- // ImportService Implementation //------------------------------------------------------------------------------------------------------- @@ -71,26 +79,41 @@ public ImportSummary importMetaData( MetaData metaData, ImportOptions importOptions ) { ImportSummary importSummary = new ImportSummary(); - - // Imports.. this could be made even more generic, just need to make sure that everything is imported in - // the correct order - + objectBridge.init(); + + Date startDate = new Date(); + + doImport( metaData.getOrganisationUnits(), importOptions, importSummary ); + // doImport( metaData.getOrganisationUnitLevels(), importOptions, importSummary ); + doImport( metaData.getOrganisationUnitGroups(), importOptions, importSummary ); + doImport( metaData.getOrganisationUnitGroupSets(), importOptions, importSummary ); + +/* + doImport( metaData.getUsers(), importOptions, importSummary ); + doImport( metaData.getUserGroups(), importOptions, importSummary ); + doImport( metaData.getUserAuthorityGroups(), importOptions, importSummary ); +*/ + +/* doImport( metaData.getConcepts(), importOptions, importSummary ); doImport( metaData.getConstants(), importOptions, importSummary ); doImport( metaData.getDocuments(), importOptions, importSummary ); doImport( metaData.getAttributeTypes(), importOptions, importSummary ); doImport( metaData.getOptionSets(), importOptions, importSummary ); +*/ - /* +/* + doImport( metaData.getCategoryOptions(), importOptions, importSummary ); doImport( metaData.getCategories(), importOptions, importSummary ); doImport( metaData.getCategoryCombos(), importOptions, importSummary ); - doImport( metaData.getCategoryOptions(), importOptions, importSummary ); doImport( metaData.getCategoryOptionCombos(), importOptions, importSummary ); + doImport( metaData.getDataElements(), importOptions, importSummary ); doImport( metaData.getDataElementGroups(), importOptions, importSummary ); doImport( metaData.getDataElementGroupSets(), importOptions, importSummary ); - */ +*/ +/* doImport( metaData.getIndicatorTypes(), importOptions, importSummary ); doImport( metaData.getIndicators(), importOptions, importSummary ); doImport( metaData.getIndicatorGroups(), importOptions, importSummary ); @@ -101,14 +124,7 @@ doImport( metaData.getMapLegendSets(), importOptions, importSummary ); doImport( metaData.getMapLayers(), importOptions, importSummary ); // doImport( metaData.getMessageConversations(), importOptions, importSummary ); - doImport( metaData.getOrganisationUnits(), importOptions, importSummary ); - // doImport( metaData.getOrganisationUnitLevels(), importOptions, importSummary ); - doImport( metaData.getOrganisationUnitGroups(), importOptions, importSummary ); - doImport( metaData.getOrganisationUnitGroupSets(), importOptions, importSummary ); doImport( metaData.getSqlViews(), importOptions, importSummary ); - doImport( metaData.getUsers(), importOptions, importSummary ); - doImport( metaData.getUserGroups(), importOptions, importSummary ); - doImport( metaData.getUserAuthorityGroups(), importOptions, importSummary ); doImport( metaData.getValidationRules(), importOptions, importSummary ); doImport( metaData.getValidationRuleGroups(), importOptions, importSummary ); @@ -119,6 +135,13 @@ doImport( metaData.getCharts(), importOptions, importSummary ); doImport( metaData.getDataSets(), importOptions, importSummary ); +*/ + Date endDate = new Date(); + log.info( "Started import at " + startDate ); + log.info( "Finished import at " + endDate ); + + objectBridge.destroy(); + cacheManager.clearCache(); return importSummary; } === added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultObjectBridge.java' --- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultObjectBridge.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultObjectBridge.java 2012-04-22 16:16:24 +0000 @@ -0,0 +1,445 @@ +package org.hisp.dhis.dxf2.metadata; + +/* + * Copyright (c) 2012, 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 org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hisp.dhis.common.IdentifiableObject; +import org.hisp.dhis.common.IdentifiableObjectManager; +import org.hisp.dhis.common.NameableObject; +import org.hisp.dhis.organisationunit.OrganisationUnit; +import org.hisp.dhis.organisationunit.OrganisationUnitGroup; +import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet; +import org.hisp.dhis.period.PeriodStore; +import org.hisp.dhis.period.PeriodType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; + +/** + * @author Morten Olav Hansen + */ +@Component +@Transactional( readOnly = true ) +public class DefaultObjectBridge + implements ObjectBridge +{ + private static final Log log = LogFactory.getLog( DefaultObjectBridge.class ); + + //------------------------------------------------------------------------------------------------------- + // Dependencies + //------------------------------------------------------------------------------------------------------- + + @Autowired + private IdentifiableObjectManager manager; + + @Autowired + private PeriodStore periodStore; + + //------------------------------------------------------------------------------------------------------- + // Internal and Semi-Public maps + //------------------------------------------------------------------------------------------------------- + + private Map, Collection> masterMap = new HashMap, Collection>(); + + private Map periodTypeMap = new HashMap(); + + private Map, Map> uidMap = new HashMap, Map>(); + + private Map, Map> codeMap = new HashMap, Map>(); + + private Map, Map> nameMap = new HashMap, Map>(); + + private Map, Map> shortNameMap = new HashMap, Map>(); + + private static final List> registeredTypes = new ArrayList>(); + + private boolean writeEnabled = true; + + //------------------------------------------------------------------------------------------------------- + // Build maps + //------------------------------------------------------------------------------------------------------- + + static + { + registeredTypes.add( PeriodType.class ); + registeredTypes.add( OrganisationUnit.class ); + registeredTypes.add( OrganisationUnitGroup.class ); + registeredTypes.add( OrganisationUnitGroupSet.class ); + } + + @Override + public void init() + { + log.info( "Started updating lookup maps at " + new Date() ); + + for ( Class type : registeredTypes ) + { + populatePeriodTypeMap( type ); + populateIdentifiableObjectMap( type ); + populateIdentifiableObjectMap( type, IdentifiableObject.IdentifiableProperty.UID ); + populateIdentifiableObjectMap( type, IdentifiableObject.IdentifiableProperty.CODE ); + populateIdentifiableObjectMap( type, IdentifiableObject.IdentifiableProperty.NAME ); + populateNameableObjectMap( type, NameableObject.NameableProperty.SHORT_NAME ); + } + + log.info( "Finished updating lookup maps at " + new Date() ); + } + + @Override + public void destroy() + { + masterMap = null; + + uidMap = null; + codeMap = null; + nameMap = null; + shortNameMap = null; + + periodTypeMap = null; + } + + //------------------------------------------------------------------------------------------------------- + // Populate Helpers + //------------------------------------------------------------------------------------------------------- + + @SuppressWarnings( "unchecked" ) + private void populateIdentifiableObjectMap( Class clazz ) + { + Collection map = new ArrayList(); + + if ( IdentifiableObject.class.isAssignableFrom( clazz ) ) + { + map = manager.getAll( (Class) clazz ); + } + + if ( map != null ) + { + masterMap.put( clazz, map ); + } + } + + @SuppressWarnings( "unchecked" ) + private void populateIdentifiableObjectMap( Class clazz, IdentifiableObject.IdentifiableProperty property ) + { + Map map = new HashMap(); + + if ( IdentifiableObject.class.isAssignableFrom( clazz ) ) + { + map = (Map) manager.getIdMap( (Class) clazz, property ); + } + + if ( map != null ) + { + if ( property == IdentifiableObject.IdentifiableProperty.UID ) + { + uidMap.put( (Class) clazz, map ); + } + else if ( property == IdentifiableObject.IdentifiableProperty.CODE ) + { + codeMap.put( (Class) clazz, map ); + } + else if ( property == IdentifiableObject.IdentifiableProperty.NAME ) + { + nameMap.put( (Class) clazz, map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + private void populateNameableObjectMap( Class clazz, NameableObject.NameableProperty property ) + { + Map map = null; + + if ( NameableObject.class.isAssignableFrom( clazz ) ) + { + map = (Map) manager.getIdMap( (Class) clazz, property ); + } + + if ( map != null ) + { + if ( property == NameableObject.NameableProperty.SHORT_NAME ) + { + shortNameMap.put( (Class) clazz, map ); + } + } + } + + private void populatePeriodTypeMap( Class clazz ) + { + Collection periodTypes = new ArrayList(); + + if ( PeriodType.class.isAssignableFrom( clazz ) ) + { + for ( PeriodType periodType : periodStore.getAllPeriodTypes() ) + { + periodTypes.add( periodType ); + periodTypeMap.put( periodType.getName(), periodType ); + } + } + + masterMap.put( clazz, periodTypes ); + } + + //------------------------------------------------------------------------------------------------------- + // ObjectBridge Implementation + //------------------------------------------------------------------------------------------------------- + + @Override + @Transactional( readOnly = false ) + public void saveObject( Object object ) + { + if ( IdentifiableObject.class.isInstance( object ) ) + { + if ( writeEnabled ) + { + manager.save( (IdentifiableObject) object ); + } + } + else + { + log.warn( "Trying to save unsupported type.. object discarded." ); + } + } + + @Override + @Transactional( readOnly = false ) + public void updateObject( Object object ) + { + if ( IdentifiableObject.class.isInstance( object ) ) + { + if ( writeEnabled ) + { + manager.update( (IdentifiableObject) object ); + } + + _updateInternalMaps( object ); + } + else + { + log.warn( "Trying to update unsupported type.. object discarded." ); + } + } + + @Override + @SuppressWarnings( "unchecked" ) + public T getObject( T object ) + { + Collection objects = _findMatches( object ); + + if ( objects.size() == 1 ) + { + return objects.iterator().next(); + } + else if ( objects.size() > 1 ) + { + log.warn( "Multiple objects found.. object discarded, returning null." ); + } + else + { + log.warn( "No object found, returning null." ); + } + + return null; + } + + @Override + public Collection getObjects( T object ) + { + return _findMatches( object ); + } + + @Override + @SuppressWarnings( "unchecked" ) + public Collection getAllObjects( Class clazz ) + { + return (Collection) masterMap.get( clazz ); + } + + public Map, Collection> getMasterMap() + { + return masterMap; + } + + public void setMasterMap( Map, Collection> masterMap ) + { + this.masterMap = masterMap; + } + + @Override + public void setWriteEnabled( boolean enabled ) + { + this.writeEnabled = enabled; + } + + @Override + public boolean isWriteEnabled() + { + return writeEnabled; + } + + //------------------------------------------------------------------------------------------------------- + // Internal Methods + //------------------------------------------------------------------------------------------------------- + + @SuppressWarnings( "unchecked" ) + private Collection _findMatches( T object ) + { + Collection objects = new HashSet(); + + if ( PeriodType.class.isInstance( object ) ) + { + PeriodType periodType = (PeriodType) object; + periodType = periodTypeMap.get( periodType.getName() ); + + if ( periodType != null ) + { + objects.add( (T) periodType ); + } + } + + if ( IdentifiableObject.class.isInstance( object ) ) + { + IdentifiableObject identifiableObject = (IdentifiableObject) object; + + if ( identifiableObject.getUid() != null ) + { + IdentifiableObject match = uidMap.get( identifiableObject.getClass() ).get( identifiableObject.getUid() ); + + if ( match != null ) + { + objects.add( (T) match ); + } + } + + if ( identifiableObject.getCode() != null ) + { + IdentifiableObject match = codeMap.get( identifiableObject.getClass() ).get( identifiableObject.getCode() ); + + if ( match != null ) + { + objects.add( (T) match ); + } + } + + if ( identifiableObject.getName() != null ) + { + IdentifiableObject match = nameMap.get( identifiableObject.getClass() ).get( identifiableObject.getName() ); + + if ( match != null ) + { + objects.add( (T) match ); + } + } + } + + if ( NameableObject.class.isInstance( object ) ) + { + NameableObject nameableObject = (NameableObject) object; + + if ( nameableObject.getShortName() != null ) + { + IdentifiableObject match = shortNameMap.get( nameableObject.getClass() ).get( nameableObject.getShortName() ); + + if ( match != null ) + { + objects.add( (T) match ); + } + } + } + + return objects; + } + + private void _updateInternalMaps( T object ) + { + if ( IdentifiableObject.class.isInstance( object ) ) + { + IdentifiableObject identifiableObject = (IdentifiableObject) object; + + if ( identifiableObject.getUid() != null ) + { + Map map = uidMap.get( identifiableObject.getClass() ); + + if ( map == null ) + { + // might be dynamically sub-classed by javassist or cglib, fetch superclass and try again + map = uidMap.get( identifiableObject.getClass().getSuperclass() ); + } + + map.put( identifiableObject.getUid(), identifiableObject ); + } + + if ( identifiableObject.getCode() != null ) + { + Map map = codeMap.get( identifiableObject.getClass() ); + + if ( map == null ) + { + // might be dynamically sub-classed by javassist or cglib, fetch superclass and try again + map = uidMap.get( identifiableObject.getClass().getSuperclass() ); + } + + map.put( identifiableObject.getCode(), identifiableObject ); + } + + if ( identifiableObject.getName() != null ) + { + Map map = uidMap.get( identifiableObject.getClass() ); + + if ( map == null ) + { + // might be dynamically sub-classed by javassist or cglib, fetch superclass and try again + map = uidMap.get( identifiableObject.getClass().getSuperclass() ); + } + + map.put( identifiableObject.getName(), identifiableObject ); + } + } + + if ( NameableObject.class.isInstance( object ) ) + { + NameableObject nameableObject = (NameableObject) object; + + if ( nameableObject.getShortName() != null ) + { + Map map = shortNameMap.get( nameableObject.getClass() ); + + if ( map == null ) + { + // might be dynamically sub-classed by javassist or cglib, fetch superclass and try again + map = shortNameMap.get( nameableObject.getClass().getSuperclass() ); + } + + map.put( nameableObject.getShortName(), nameableObject ); + } + } + } +} === modified file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ExportOptions.java' --- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ExportOptions.java 2012-04-01 12:24:57 +0000 +++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ExportOptions.java 2012-04-22 16:16:24 +0000 @@ -49,14 +49,14 @@ // means it can be used as a simple argument in controller methods. //-------------------------------------------------------------------------- + private boolean users = true; + + private boolean userAuthorityGroups = true; + + private boolean userGroups = true; + private boolean attributeTypes = true; - private boolean users = false; - - private boolean userAuthorityGroups = false; - - private boolean userGroups = false; - private boolean messageConversations = false; private boolean dataElements = true; @@ -107,7 +107,7 @@ private boolean reportTables = true; - private boolean documents = false; + private boolean documents = true; private boolean constants = true; === added file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ObjectBridge.java' --- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ObjectBridge.java 1970-01-01 00:00:00 +0000 +++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ObjectBridge.java 2012-04-22 16:16:24 +0000 @@ -0,0 +1,99 @@ +package org.hisp.dhis.dxf2.metadata; + +/* + * Copyright (c) 2012, 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.util.Collection; + +/** + * Acts as a bridge between the importer and the persistence/cache layer. + *

+ * The flag {@code writeEnabled} is used to indicate if writing to the persistence layer + * is enabled or not. + * + * @author Morten Olav Hansen + */ +public interface ObjectBridge +{ + void init(); // FIXME rename or remove.. @PostConstruct worked badly here, some kind of workaround would be nice + void destroy(); // FIXME + + /** + * Save object. Will save to persistence layer if {@code writeEnabled} is {@code true}. + * + * @param object Object to write + */ + void saveObject( Object object ); + + /** + * Update object. Will save to persistence layer if {@code writeEnabled} is {@code true}. + * + * @param object + */ + void updateObject( Object object ); + + /** + * Get an object from the internal store. This object might not be a persisted object + * depending on the flag {@code writeEnabled}. + * + * @param object Object to match against + * @return Matched object or {@code null} if matched > 1 or no match found + */ + T getObject( T object ); + + /** + * Return all matches for a given object. These objects might not be a persisted object + * depending on the flag {@code writeEnabled}. + * + * @param object Object to match against + * @return A collection of matched objects + */ + Collection getObjects( T object ); + + /** + * Get all objects for a specified class. These objects might not be a persisted object + * depending on the flag {@code writeEnabled}. + * + * @param clazz Clazz to match against + * @return Collection of matches + */ + Collection getAllObjects( Class clazz ); + + /** + * Enable or disable writing to the persistence store. + * + * @param enabled {@code boolean} turning writing on or off + */ + void setWriteEnabled( boolean enabled ); + + /** + * Is persistence storage enabled? + * + * @return {@code boolean} indicating status of {@code writeEnabled} + */ + boolean isWriteEnabled(); +} === modified file 'dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java' --- dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java 2012-04-21 11:45:47 +0000 +++ dhis-2/dhis-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java 2012-04-22 16:16:24 +0000 @@ -29,19 +29,21 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.hisp.dhis.common.*; +import org.hisp.dhis.common.BaseIdentifiableObject; +import org.hisp.dhis.common.CodeGenerator; +import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.common.annotation.Scanned; import org.hisp.dhis.dxf2.importsummary.ImportConflict; import org.hisp.dhis.dxf2.importsummary.ImportCount; import org.hisp.dhis.dxf2.metadata.ImportOptions; import org.hisp.dhis.dxf2.metadata.Importer; +import org.hisp.dhis.dxf2.metadata.ObjectBridge; import org.hisp.dhis.dxf2.utils.OrganisationUnitUtils; import org.hisp.dhis.importexport.ImportStrategy; import org.hisp.dhis.organisationunit.OrganisationUnit; import org.hisp.dhis.organisationunit.comparator.OrganisationUnitComparator; import org.hisp.dhis.period.Period; import org.hisp.dhis.period.PeriodService; -import org.hisp.dhis.period.PeriodStore; import org.hisp.dhis.period.PeriodType; import org.hisp.dhis.system.util.ReflectionUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -64,13 +66,10 @@ //------------------------------------------------------------------------------------------------------- @Autowired - protected IdentifiableObjectManager manager; - - @Autowired private PeriodService periodService; @Autowired - private PeriodStore periodStore; + private ObjectBridge objectBridge; //------------------------------------------------------------------------------------------------------- // Constructor @@ -79,13 +78,10 @@ public DefaultIdentifiableObjectImporter( Class importerClass ) { this.importerClass = importerClass; - this.nameable = NameableObject.class.isAssignableFrom( importerClass ); } private final Class importerClass; - private final boolean nameable; - //------------------------------------------------------------------------------------------------------- // Current import counts //------------------------------------------------------------------------------------------------------- @@ -97,23 +93,6 @@ protected int ignored; //------------------------------------------------------------------------------------------------------- - // Mappings from identifier (uid, name, code) to a db object. - // - // WARNING: These maps might be out-of-date, depending on if new inserts has been made after the were - // fetched. - //------------------------------------------------------------------------------------------------------- - - protected Map uidMap; - - protected Map codeMap; - - protected Map nameMap; - - protected Map shortNameMap; - - private Map periodTypeMap = new HashMap(); - - //------------------------------------------------------------------------------------------------------- // Generic implementations of newObject and updatedObject //------------------------------------------------------------------------------------------------------- @@ -126,11 +105,6 @@ */ protected ImportConflict newObject( T object, ImportOptions options ) { - if ( options.isDryRun() ) - { - return null; - } - // make sure that the internalId is 0, so that the system will generate a ID object.setId( 0 ); object.setUid( CodeGenerator.generateCode() ); @@ -141,13 +115,12 @@ updateIdentifiableObjects( object, scanIdentifiableObjects( object ) ); - manager.save( object ); + objectBridge.saveObject( object ); updateIdentifiableObjectCollections( object, identifiableObjectCollections ); updatePeriodTypes( object ); - manager.update( object ); - updateIdMaps( object ); + objectBridge.updateObject( object ); log.info( "Save successful." ); log.info( object ); @@ -165,11 +138,6 @@ */ protected ImportConflict updatedObject( T object, T oldObject, ImportOptions options ) { - if ( options.isDryRun() ) - { - return null; - } - log.info( "Starting update of object " + getDisplayName( oldObject ) + " (" + oldObject.getClass().getSimpleName() + ")" ); updateIdentifiableObjects( object, scanIdentifiableObjects( object ) ); @@ -178,7 +146,7 @@ oldObject.mergeWith( object ); updatePeriodTypes( oldObject ); - manager.update( oldObject ); + objectBridge.updateObject( oldObject ); log.info( "Update successful." ); @@ -193,9 +161,7 @@ if ( PeriodType.class.isAssignableFrom( field.getType() ) ) { PeriodType periodType = ReflectionUtils.invokeGetterMethod( field.getName(), object ); - - periodType = periodTypeMap.get( periodType.getName() ); - + periodType = objectBridge.getObject( periodType ); ReflectionUtils.invokeSetterMethod( field.getName(), object, periodType ); } } @@ -216,8 +182,6 @@ return conflicts; } - populatePeriodTypeMap(); - reset(); // FIXME a bit too static.. implement "pre handler" for types? @@ -243,7 +207,6 @@ @Override public ImportConflict importObject( T object, ImportOptions options ) { - populatePeriodTypeMap(); reset(); return importObjectLocal( object, options ); @@ -265,42 +228,6 @@ // Protected methods //------------------------------------------------------------------------------------------------------- - protected void populatePeriodTypeMap() - { - for ( PeriodType periodType : periodStore.getAllPeriodTypes() ) - { - periodTypeMap.put( periodType.getName(), periodType ); - } - } - - protected void updateIdMaps( T object ) - { - if ( object.getUid() != null ) - { - uidMap.put( object.getUid(), object ); - } - - if ( object.getCode() != null ) - { - codeMap.put( object.getCode(), object ); - } - - if ( object.getName() != null ) - { - nameMap.put( object.getName(), object ); - } - - if ( nameable ) - { - NameableObject nameableObject = (NameableObject) object; - - if ( nameableObject.getShortName() != null ) - { - shortNameMap.put( nameableObject.getShortName(), object ); - } - } - } - /** * @param object Object to get display name for * @return A usable display name @@ -327,21 +254,11 @@ // Helpers //------------------------------------------------------------------------------------------------------- - @SuppressWarnings( "unchecked" ) private void reset() { imported = 0; updated = 0; ignored = 0; - - uidMap = manager.getIdMap( importerClass, IdentifiableObject.IdentifiableProperty.UID ); - codeMap = manager.getIdMap( importerClass, IdentifiableObject.IdentifiableProperty.CODE ); - nameMap = manager.getIdMap( importerClass, IdentifiableObject.IdentifiableProperty.NAME ); - - if ( nameable ) - { - shortNameMap = (Map) manager.getIdMap( (Class) importerClass, NameableObject.NameableProperty.SHORT_NAME ); - } } private ImportConflict importObjectLocal( T object, ImportOptions options ) @@ -363,7 +280,7 @@ private ImportConflict startImport( T object, ImportOptions options ) { - T oldObject = getObject( object ); + T oldObject = objectBridge.getObject( object ); ImportConflict conflict; if ( ImportStrategy.NEW.equals( options.getImportStrategy() ) ) @@ -419,19 +336,6 @@ private ImportConflict validateIdentifiableObject( T object, ImportOptions options ) { - T uidObject = uidMap.get( object.getUid() ); - T codeObject = codeMap.get( object.getCode() ); - T nameObject = nameMap.get( object.getName() ); - - T shortNameObject = null; - - if ( nameable ) - { - NameableObject nameableObject = (NameableObject) object; - - shortNameObject = shortNameMap.get( nameableObject.getShortName() ); - } - ImportConflict conflict = null; if ( ImportStrategy.NEW.equals( options.getImportStrategy() ) ) @@ -445,7 +349,7 @@ else if ( ImportStrategy.NEW_AND_UPDATES.equals( options.getImportStrategy() ) ) { // if we have a match on at least one of the objects, then assume update - if ( uidObject != null || codeObject != null || nameObject != null || shortNameObject != null ) + if ( objectBridge.getObjects( object ).size() > 0 ) { conflict = validateForUpdatesStrategy( object ); } @@ -460,48 +364,14 @@ private ImportConflict validateForUpdatesStrategy( T object ) { - T uidObject = uidMap.get( object.getUid() ); - T codeObject = codeMap.get( object.getCode() ); - T nameObject = nameMap.get( object.getName() ); - - T shortNameObject = null; - - if ( nameable ) - { - NameableObject nameableObject = (NameableObject) object; - - shortNameObject = shortNameMap.get( nameableObject.getShortName() ); - } - ImportConflict conflict = null; - - Set nonNullObjects = new HashSet(); - - if ( uidObject != null ) - { - nonNullObjects.add( uidObject ); - } - - if ( codeObject != null ) - { - nonNullObjects.add( codeObject ); - } - - if ( nameObject != null ) - { - nonNullObjects.add( nameObject ); - } - - if ( shortNameObject != null ) - { - nonNullObjects.add( shortNameObject ); - } - - if ( nonNullObjects.isEmpty() ) + Collection objects = objectBridge.getObjects( object ); + + if ( objects.isEmpty() ) { conflict = reportLookupConflict( object ); } - else if ( nonNullObjects.size() > 1 ) + else if ( objects.size() > 1 ) { conflict = reportMoreThanOneConflict( object ); } @@ -511,22 +381,10 @@ private ImportConflict validateForNewStrategy( T object ) { - T uidObject = uidMap.get( object.getUid() ); - T codeObject = codeMap.get( object.getCode() ); - T nameObject = nameMap.get( object.getName() ); - - T shortNameObject = null; - - if ( nameable ) - { - NameableObject nameableObject = (NameableObject) object; - - shortNameObject = shortNameMap.get( nameableObject.getShortName() ); - } - ImportConflict conflict = null; + Collection objects = objectBridge.getObjects( object ); - if ( uidObject != null || codeObject != null || nameObject != null || shortNameObject != null ) + if ( objects.size() > 0 ) { conflict = reportConflict( object ); } @@ -549,45 +407,6 @@ return new ImportConflict( getDisplayName( object ), "Object already exists." ); } - private T getObject( T object ) - { - T matchedObject = uidMap.get( object.getUid() ); - - if ( matchedObject != null ) - { - return matchedObject; - } - - matchedObject = codeMap.get( object.getCode() ); - - if ( matchedObject != null ) - { - return matchedObject; - } - - matchedObject = nameMap.get( object.getName() ); - - if ( matchedObject != null ) - { - return matchedObject; - } - - if ( nameable ) - { - NameableObject nameableObject = (NameableObject) object; - - matchedObject = shortNameMap.get( nameableObject.getShortName() ); - - if ( matchedObject != null ) - { - return matchedObject; - } - } - - return matchedObject; - } - - // FIXME slow! some kind of global idMap is needed here, that will also update itself from several importers private IdentifiableObject findObjectByReference( IdentifiableObject identifiableObject ) { IdentifiableObject match = null; @@ -596,22 +415,10 @@ if ( Period.class.isAssignableFrom( identifiableObject.getClass() ) ) { Period period = (Period) identifiableObject; - match = periodService.reloadPeriod( period ); - } - else if ( identifiableObject.getUid() != null ) - { - match = manager.get( identifiableObject.getClass(), identifiableObject.getUid() ); - } - else if ( identifiableObject.getCode() != null ) - { - match = manager.getByCode( identifiableObject.getClass(), identifiableObject.getCode() ); - } - else if ( identifiableObject.getName() != null ) - { - match = manager.getByName( identifiableObject.getClass(), identifiableObject.getName() ); + return periodService.reloadPeriod( period ); } - return match; + return objectBridge.getObject( identifiableObject ); } private Map scanIdentifiableObjects( IdentifiableObject identifiableObject ) === modified file 'dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml' --- dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml 2012-04-19 16:40:00 +0000 +++ dhis-2/dhis-dxf2/src/main/resources/META-INF/dhis/beans.xml 2012-04-22 16:16:24 +0000 @@ -36,7 +36,8 @@ value="org.hisp.dhis.dataelement.DataElementCategoryOption" /> - + @@ -49,7 +50,8 @@ - + @@ -106,7 +108,8 @@ - + @@ -115,12 +118,14 @@ value="org.hisp.dhis.organisationunit.OrganisationUnit" /> - + - + @@ -153,7 +158,8 @@ - +