=== modified file 'dhis-2/dhis-api/pom.xml' --- dhis-2/dhis-api/pom.xml 2013-10-17 06:57:37 +0000 +++ dhis-2/dhis-api/pom.xml 2013-12-12 13:27:33 +0000 @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 @@ -38,7 +38,7 @@ net.sf.jasperreports jasperreports - + net.sf.jasperreports jasperreports-fonts @@ -60,9 +60,13 @@ smslib - org.springframework + org.springframework spring-jdbc + + com.google.guava + guava + === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/importexport/ImportStrategy.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/importexport/ImportStrategy.java 2013-08-23 15:56:19 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/importexport/ImportStrategy.java 2013-12-12 13:27:33 +0000 @@ -30,11 +30,11 @@ /** * @author Lars Helge Overland - * @version $Id: ImportStrategy.java 4646 2008-02-26 14:54:29Z larshelg $ */ public enum ImportStrategy { NEW_AND_UPDATES, NEW, - UPDATES + UPDATES, + DELETES } === 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 2013-12-10 18:10:47 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/datavalueset/DefaultDataValueSetService.java 2013-12-12 13:27:33 +0000 @@ -28,26 +28,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -import static org.hisp.dhis.importexport.ImportStrategy.NEW; -import static org.hisp.dhis.importexport.ImportStrategy.NEW_AND_UPDATES; -import static org.hisp.dhis.importexport.ImportStrategy.UPDATES; -import static org.hisp.dhis.system.notification.NotificationLevel.ERROR; -import static org.hisp.dhis.system.notification.NotificationLevel.INFO; -import static org.hisp.dhis.system.util.ConversionUtils.wrap; -import static org.hisp.dhis.system.util.DateUtils.getDefaultDate; -import static org.hisp.dhis.common.IdentifiableObject.IdentifiableProperty.UUID; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Writer; -import java.nio.charset.Charset; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - +import com.csvreader.CsvReader; import org.amplecode.quick.BatchHandler; import org.amplecode.quick.BatchHandlerFactory; import org.amplecode.staxwax.factory.XMLFactory; @@ -85,7 +66,23 @@ import org.hisp.dhis.user.CurrentUserService; import org.springframework.beans.factory.annotation.Autowired; -import com.csvreader.CsvReader; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.hisp.dhis.common.IdentifiableObject.IdentifiableProperty.UUID; +import static org.hisp.dhis.importexport.ImportStrategy.*; +import static org.hisp.dhis.system.notification.NotificationLevel.ERROR; +import static org.hisp.dhis.system.notification.NotificationLevel.INFO; +import static org.hisp.dhis.system.util.ConversionUtils.wrap; +import static org.hisp.dhis.system.util.DateUtils.getDefaultDate; /** * @author Lars Helge Overland @@ -129,7 +126,7 @@ @Autowired private Notifier notifier; - + //-------------------------------------------------------------------------- // DataValueSet implementation //-------------------------------------------------------------------------- @@ -172,7 +169,7 @@ { throw new IllegalArgumentException( "At least one period must be specified" ); } - + dataValueSetStore.writeDataValueSetXml( null, null, null, null, getDataElements( dataSets ), periods, getOrgUnits( orgUnits ), out ); } @@ -184,7 +181,7 @@ { throw new IllegalArgumentException( "At least one period must be specified" ); } - + dataValueSetStore.writeDataValueSetCsv( getDataElements( dataSets ), periods, getOrgUnits( orgUnits ), writer ); } @@ -317,7 +314,7 @@ DataElementCategoryOptionCombo fallbackCategoryOptionCombo = categoryService.getDefaultDataElementCategoryOptionCombo(); String currentUser = currentUserService.getCurrentUsername(); - + BatchHandler batchHandler = batchHandlerFactory.createBatchHandler( DataValueBatchHandler.class ).init(); int importCount = 0; @@ -377,7 +374,7 @@ } String commentValid = ValidationUtils.commentIsValid( dataValue.getComment() ); - + if ( commentValid != null ) { summary.getConflicts().add( new ImportConflict( DataValue.class.getSimpleName(), commentValid ) ); @@ -443,14 +440,14 @@ int ignores = totalCount - importCount - updateCount; - summary.setDataValueCount( new ImportCount( importCount, updateCount, ignores ) ); + summary.setDataValueCount( new ImportCount( importCount, updateCount, ignores, 0 ) ); summary.setStatus( ImportStatus.SUCCESS ); summary.setDescription( "Import process completed successfully" ); notifier.notify( id, INFO, "Import done", true ).addTaskSummary( id, summary ); dataValueSet.close(); - + return summary; } @@ -536,14 +533,14 @@ private Map getUuidOrgUnitMap() { Map orgUnitMap = new HashMap(); - + Collection allOrganisationUnits = organisationUnitService.getAllOrganisationUnits(); for ( OrganisationUnit organisationUnit : allOrganisationUnits ) { orgUnitMap.put( organisationUnit.getUuid(), organisationUnit ); } - + return orgUnitMap; - } + } } === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportCount.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportCount.java 2013-08-23 16:05:01 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/importsummary/ImportCount.java 2013-12-12 13:27:33 +0000 @@ -33,7 +33,7 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import org.hisp.dhis.common.DxfNamespaces; -@JacksonXmlRootElement( localName = "count", namespace = DxfNamespaces.DXF_2_0 ) +@JacksonXmlRootElement(localName = "count", namespace = DxfNamespaces.DXF_2_0) public class ImportCount { private int imported; @@ -42,19 +42,22 @@ private int ignored; + private int deleted; + public ImportCount() { } - public ImportCount( int imported, int updated, int ignored ) + public ImportCount( int imported, int updated, int ignored, int deleted ) { this.imported = imported; this.updated = updated; this.ignored = ignored; + this.deleted = deleted; } @JsonProperty - @JacksonXmlProperty( isAttribute = true ) + @JacksonXmlProperty(isAttribute = true) public int getImported() { return imported; @@ -66,7 +69,7 @@ } @JsonProperty - @JacksonXmlProperty( isAttribute = true ) + @JacksonXmlProperty(isAttribute = true) public int getUpdated() { return updated; @@ -78,7 +81,7 @@ } @JsonProperty - @JacksonXmlProperty( isAttribute = true ) + @JacksonXmlProperty(isAttribute = true) public int getIgnored() { return ignored; @@ -89,6 +92,18 @@ this.ignored = ignored; } + @JsonProperty + @JacksonXmlProperty(isAttribute = true) + public int getDeleted() + { + return deleted; + } + + public void setDeleted( int deleted ) + { + this.deleted = deleted; + } + @Override public String toString() { @@ -110,6 +125,11 @@ ignored++; } + public void incrementDeleted() + { + deleted++; + } + public void incrementImported( int n ) { imported += n; @@ -124,4 +144,9 @@ { ignored += n; } + + public void incrementDeleted( int n ) + { + deleted += n; + } } === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultImportService.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultImportService.java 2013-12-11 12:28:53 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultImportService.java 2013-12-12 13:27:33 +0000 @@ -28,13 +28,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +import com.google.common.collect.Lists; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.SessionFactory; import org.hisp.dhis.cache.HibernateCacheManager; -import org.hisp.dhis.common.IdentifiableObject; import org.hisp.dhis.dxf2.timer.SystemNanoTimer; import org.hisp.dhis.dxf2.timer.Timer; +import org.hisp.dhis.importexport.ImportStrategy; import org.hisp.dhis.scheduling.TaskId; import org.hisp.dhis.system.notification.NotificationLevel; import org.hisp.dhis.system.notification.Notifier; @@ -50,7 +51,6 @@ import java.util.Date; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; import static org.springframework.util.Assert.notNull; @@ -68,7 +68,7 @@ // Dependencies //------------------------------------------------------------------------------------------------------- - @Autowired(required = false) + @Autowired( required = false ) private Set importerClasses = new HashSet(); @Autowired @@ -126,9 +126,20 @@ objectBridge.setPreheatCache( importOptions.isPreheatCache() ); objectBridge.init(); - for ( Map.Entry, String> entry : ExchangeClasses.getImportMap().entrySet() ) - { - Object value = ReflectionUtils.invokeGetterMethod( entry.getValue(), metaData ); + List types; + + if ( ImportStrategy.DELETES.equals( importOptions.getImportStrategy() ) ) + { + types = Lists.reverse( Lists.newArrayList( ExchangeClasses.getImportMap().values() ) ); + } + else + { + types = Lists.newArrayList( ExchangeClasses.getImportMap().values() ); + } + + for ( String type : types ) + { + Object value = ReflectionUtils.invokeGetterMethod( type, metaData ); if ( value != null ) { @@ -138,7 +149,7 @@ if ( !objects.isEmpty() ) { - String message = "Importing " + objects.size() + " " + StringUtils.capitalize( entry.getValue() ); + String message = "Importing " + objects.size() + " " + StringUtils.capitalize( type ); if ( taskId != null ) { @@ -160,12 +171,12 @@ } else { - log.warn( "Getter for '" + entry.getValue() + "' did not return a collection." ); + log.warn( "Getter for '" + type + "' did not return a collection." ); } } else { - log.warn( "Can not find getter for '" + entry.getValue() + "'." ); + log.warn( "Can not find getter for '" + type + "'." ); } } === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultObjectBridge.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultObjectBridge.java 2013-12-11 12:28:53 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/DefaultObjectBridge.java 2013-12-12 13:27:33 +0000 @@ -301,6 +301,24 @@ } @Override + public void deleteObject( Object object ) + { + if ( _typeSupported( object.getClass() ) && IdentifiableObject.class.isInstance( object ) ) + { + if ( writeEnabled ) + { + manager.delete( (IdentifiableObject) object ); + } + + // _updateInternalMaps( object ); + } + else + { + log.warn( "Trying to delete unsupported type + " + object.getClass() + " with object " + object + " object discarded." ); + } + } + + @Override public T getObject( T object ) { Set objects = _findMatches( object ); === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ImportSummary.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ImportSummary.java 2013-08-23 16:05:01 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ImportSummary.java 2013-12-12 13:27:33 +0000 @@ -41,7 +41,7 @@ /** * @author Morten Olav Hansen */ -@JacksonXmlRootElement( localName = "importSummary", namespace = DxfNamespaces.DXF_2_0) +@JacksonXmlRootElement(localName = "importSummary", namespace = DxfNamespaces.DXF_2_0) public class ImportSummary { private ImportCount importCount = new ImportCount(); @@ -54,7 +54,7 @@ } @JsonProperty - @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) public ImportCount getImportCount() { return importCount; @@ -66,8 +66,8 @@ } @JsonProperty - @JacksonXmlElementWrapper( localName = "typeSummaries", namespace = DxfNamespaces.DXF_2_0) - @JacksonXmlProperty( localName = "typeSummary", namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlElementWrapper(localName = "typeSummaries", namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlProperty(localName = "typeSummary", namespace = DxfNamespaces.DXF_2_0) public List getImportTypeSummaries() { return importTypeSummaries; @@ -87,6 +87,7 @@ this.importCount.incrementImported( importCount.getImported() ); this.importCount.incrementUpdated( importCount.getUpdated() ); this.importCount.incrementIgnored( importCount.getIgnored() ); + this.importCount.incrementDeleted( importCount.getDeleted() ); } public void incrementImported( int n ) @@ -104,6 +105,11 @@ importCount.incrementIgnored( n ); } + public void incrementDeleted( int n ) + { + importCount.incrementDeleted( n ); + } + @Override public String toString() { === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ImportTypeSummary.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ImportTypeSummary.java 2013-08-23 16:05:01 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ImportTypeSummary.java 2013-12-12 13:27:33 +0000 @@ -43,7 +43,7 @@ /** * @author Morten Olav Hansen */ -@JacksonXmlRootElement( localName = "typeSummary", namespace = DxfNamespaces.DXF_2_0) +@JacksonXmlRootElement(localName = "typeSummary", namespace = DxfNamespaces.DXF_2_0) public class ImportTypeSummary extends ImportSummary { @@ -59,7 +59,7 @@ } @JsonProperty - @JacksonXmlProperty( isAttribute = true ) + @JacksonXmlProperty(isAttribute = true) public String getType() { return type; @@ -71,7 +71,7 @@ } @JsonProperty - @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlProperty(namespace = DxfNamespaces.DXF_2_0) public ImportCount getImportCount() { return importCount; @@ -83,8 +83,8 @@ } @JsonProperty - @JacksonXmlElementWrapper( localName = "conflicts", namespace = DxfNamespaces.DXF_2_0) - @JacksonXmlProperty( localName = "conflict", namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlElementWrapper(localName = "conflicts", namespace = DxfNamespaces.DXF_2_0) + @JacksonXmlProperty(localName = "conflict", namespace = DxfNamespaces.DXF_2_0) public List getImportConflicts() { return importConflicts; @@ -114,6 +114,11 @@ importCount.incrementIgnored(); } + public void incrementDeleted() + { + importCount.incrementDeleted(); + } + @Override public String toString() { === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ObjectBridge.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ObjectBridge.java 2013-12-11 12:28:53 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/ObjectBridge.java 2013-12-12 13:27:33 +0000 @@ -53,11 +53,18 @@ /** * Update object. Will save to persistence layer if {@code writeEnabled} is {@code true}. * - * @param object + * @param object Object to update */ void updateObject( Object object ); /** + * Delete object. Will delete from persistence layer if {@code writeEnabled} is {@code true}. + * + * @param object Object to delete + */ + void deleteObject( Object object ); + + /** * Get an object from the internal store. This object might not be a persisted object * depending on the flag {@code writeEnabled}. * === modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java' --- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java 2013-12-10 16:38:55 +0000 +++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/metadata/importers/DefaultIdentifiableObjectImporter.java 2013-12-12 13:27:33 +0000 @@ -110,7 +110,7 @@ @Autowired private SessionFactory sessionFactory; - @Autowired( required = false ) + @Autowired(required = false) private List> objectHandlers; //------------------------------------------------------------------------------------------------------- @@ -395,10 +395,39 @@ } //------------------------------------------------------------------------------------------------------- - // Generic implementations of newObject and updatedObject + // Generic implementations of deleteObject, newObject, updatedObject //------------------------------------------------------------------------------------------------------- /** + * Called every time a idObject is to be deleted. + * + * @param user User to check + * @param persistedObject The current version of the idObject + * @return An ImportConflict instance if there was a conflict, otherwise null + */ + protected boolean deleteObject( User user, T persistedObject ) + { + if ( !SharingUtils.canDelete( user, persistedObject ) ) + { + summaryType.getImportConflicts().add( + new ImportConflict( ImportUtils.getDisplayName( persistedObject ), "You do not have delete access to class type." ) ); + + log.debug( "You do not have delete access to class type." ); + + return false; + } + + log.debug( "Trying to delete object => " + ImportUtils.getDisplayName( persistedObject ) + " (" + persistedObject.getClass().getSimpleName() + ")" ); + + objectBridge.deleteObject( persistedObject ); + + log.debug( "Delete successful." ); + + return true; + } + + + /** * Called every time a new idObject is to be imported. * * @param user User to check @@ -573,6 +602,7 @@ { this.options = options; this.summaryType = new ImportTypeSummary( importerClass.getSimpleName() ); + this.summaryType.setDataValueCount( null ); if ( objects.isEmpty() ) { @@ -598,6 +628,7 @@ { this.options = options; this.summaryType = new ImportTypeSummary( importerClass.getSimpleName() ); + this.summaryType.setDataValueCount( null ); ObjectHandlerUtils.preObjectHandlers( object, objectHandlers ); importObjectLocal( user, object ); @@ -629,7 +660,7 @@ private void startImport( User user, T object ) { - T oldObject = objectBridge.getObject( object ); + T persistedObject = objectBridge.getObject( object ); if ( ImportStrategy.NEW.equals( options.getImportStrategy() ) ) { @@ -640,7 +671,7 @@ } else if ( ImportStrategy.UPDATES.equals( options.getImportStrategy() ) ) { - if ( updateObject( user, object, oldObject ) ) + if ( updateObject( user, object, persistedObject ) ) { summaryType.incrementUpdated(); } @@ -651,9 +682,9 @@ } else if ( ImportStrategy.NEW_AND_UPDATES.equals( options.getImportStrategy() ) ) { - if ( oldObject != null ) + if ( persistedObject != null ) { - if ( updateObject( user, object, oldObject ) ) + if ( updateObject( user, object, persistedObject ) ) { summaryType.incrementUpdated(); } @@ -674,6 +705,19 @@ } } } + else if ( ImportStrategy.DELETES.equals( options.getImportStrategy() ) ) + { + sessionFactory.getCurrentSession().flush(); + + if ( deleteObject( user, persistedObject ) ) + { + summaryType.incrementDeleted(); + } + else + { + summaryType.incrementIgnored(); + } + } } private boolean validateIdentifiableObject( T object ) @@ -681,6 +725,12 @@ ImportConflict conflict = null; boolean success = true; + if ( ImportStrategy.DELETES.equals( options.getImportStrategy() ) ) + { + success = validateForDeleteStrategy( object ); + return success; + } + if ( object.getName() == null || object.getName().length() == 0 ) { conflict = new ImportConflict( ImportUtils.getDisplayName( object ), "Empty name for object " + object ); @@ -765,6 +815,30 @@ return true; } + private boolean validateForDeleteStrategy( T object ) + { + ImportConflict conflict = null; + Collection objects = objectBridge.getObjects( object ); + + if ( objects.isEmpty() ) + { + conflict = reportLookupConflict( object ); + } + else if ( objects.size() > 1 ) + { + conflict = reportMoreThanOneConflict( object ); + } + + if ( conflict != null ) + { + summaryType.getImportConflicts().add( conflict ); + + return false; + } + + return true; + } + private IdentifiableObject findObjectByReference( IdentifiableObject identifiableObject ) { if ( identifiableObject == null ) === modified file 'dhis-2/pom.xml' --- dhis-2/pom.xml 2013-12-07 14:11:15 +0000 +++ dhis-2/pom.xml 2013-12-12 13:27:33 +0000 @@ -928,6 +928,12 @@ test + + com.google.guava + guava + 14.0.1 + +