← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 16992: import/export of csv, wip

 

------------------------------------------------------------
revno: 16992
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2014-10-08 13:12:13 +0700
message:
  import/export of csv, wip
removed:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventUtils.java
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/ImportEventsTask.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/DefaultCsvEventService.java
modified:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JacksonEventService.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventDataValue.java
  dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventController.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-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java	2014-09-17 14:51:26 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/AbstractEventService.java	2014-10-08 06:12:13 +0000
@@ -30,14 +30,21 @@
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.hibernate.SessionFactory;
+import org.hisp.dhis.common.CodeGenerator;
 import org.hisp.dhis.common.IdentifiableObject;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementService;
 import org.hisp.dhis.dxf2.events.trackedentity.TrackedEntityInstance;
 import org.hisp.dhis.dxf2.importsummary.ImportConflict;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
+import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
+import org.hisp.dhis.dxf2.timer.SystemNanoTimer;
+import org.hisp.dhis.dxf2.timer.Timer;
 import org.hisp.dhis.event.EventStatus;
 import org.hisp.dhis.i18n.I18nManager;
 import org.hisp.dhis.organisationunit.OrganisationUnit;
@@ -51,9 +58,11 @@
 import org.hisp.dhis.program.ProgramStageInstanceService;
 import org.hisp.dhis.program.ProgramStageService;
 import org.hisp.dhis.program.ProgramStatus;
+import org.hisp.dhis.scheduling.TaskId;
+import org.hisp.dhis.system.notification.NotificationLevel;
+import org.hisp.dhis.system.notification.Notifier;
 import org.hisp.dhis.system.util.DateUtils;
 import org.hisp.dhis.system.util.ValidationUtils;
-import org.hisp.dhis.common.CodeGenerator;
 import org.hisp.dhis.trackedentity.TrackedEntityInstanceService;
 import org.hisp.dhis.trackedentitycomment.TrackedEntityComment;
 import org.hisp.dhis.trackedentitycomment.TrackedEntityCommentService;
@@ -79,45 +88,55 @@
 public abstract class AbstractEventService
     implements EventService
 {
+    private static final Log log = LogFactory.getLog( AbstractEventService.class );
+
     // -------------------------------------------------------------------------
     // Dependencies
     // -------------------------------------------------------------------------
 
     @Autowired
-    private ProgramService programService;
-
-    @Autowired
-    private ProgramStageService programStageService;
-
-    @Autowired
-    private ProgramInstanceService programInstanceService;
-
-    @Autowired
-    private ProgramStageInstanceService programStageInstanceService;
-
-    @Autowired
-    private OrganisationUnitService organisationUnitService;
-
-    @Autowired
-    private DataElementService dataElementService;
+    protected ProgramService programService;
+
+    @Autowired
+    protected ProgramStageService programStageService;
+
+    @Autowired
+    protected ProgramInstanceService programInstanceService;
+
+    @Autowired
+    protected ProgramStageInstanceService programStageInstanceService;
+
+    @Autowired
+    protected OrganisationUnitService organisationUnitService;
+
+    @Autowired
+    protected DataElementService dataElementService;
 
     @Autowired
     protected CurrentUserService currentUserService;
 
     @Autowired
-    private TrackedEntityDataValueService dataValueService;
-
-    @Autowired
-    private TrackedEntityInstanceService entityInstanceService;
-
-    @Autowired
-    private TrackedEntityCommentService commentService;
-
-    @Autowired
-    private EventStore eventStore;
-
-    @Autowired
-    private I18nManager i18nManager;
+    protected TrackedEntityDataValueService dataValueService;
+
+    @Autowired
+    protected TrackedEntityInstanceService entityInstanceService;
+
+    @Autowired
+    protected TrackedEntityCommentService commentService;
+
+    @Autowired
+    protected EventStore eventStore;
+
+    @Autowired
+    protected I18nManager i18nManager;
+
+    @Autowired
+    protected Notifier notifier;
+
+    @Autowired
+    protected SessionFactory sessionFactory;
+
+    protected final int FLUSH_FREQUENCY = 20;
 
     private static final ObjectMapper objectMapper = new ObjectMapper();
 
@@ -127,6 +146,55 @@
 
     @Override
     @Transactional
+    public ImportSummaries addEvents( List<Event> events, ImportOptions importOptions )
+    {
+        ImportSummaries importSummaries = new ImportSummaries();
+
+        int counter = 0;
+
+        for ( Event event : events )
+        {
+            importSummaries.addImportSummary( addEvent( event, importOptions ) );
+
+            if ( counter % FLUSH_FREQUENCY == 0 )
+            {
+                sessionFactory.getCurrentSession().flush();
+                sessionFactory.getCurrentSession().clear();
+            }
+
+            counter++;
+        }
+
+        return importSummaries;
+    }
+
+    @Override
+    @Transactional
+    public ImportSummaries addEvents( List<Event> events, ImportOptions importOptions, TaskId taskId )
+    {
+        notifier.clear( taskId ).notify( taskId, "Importing events" );
+
+        Timer<Long> timer = new SystemNanoTimer().start();
+
+        ImportSummaries importSummaries = addEvents( events, importOptions );
+
+        timer.stop();
+
+        if ( taskId != null )
+        {
+            notifier.notify( taskId, NotificationLevel.INFO, "Import done. Completed in " + timer.toString() + ".", true ).
+                addTaskSummary( taskId, importSummaries );
+        }
+        else
+        {
+            log.info( "Import done. Completed in " + timer.toString() + "." );
+        }
+
+        return importSummaries;
+    }
+
+    @Override
+    @Transactional
     public ImportSummary addEvent( Event event )
     {
         return addEvent( event, null );
@@ -719,7 +787,7 @@
 
     private ProgramStageInstance createProgramStageInstance( ProgramStage programStage,
 
-    ProgramInstance programInstance, OrganisationUnit organisationUnit, Date dueDate, Date executionDate, int status,
+        ProgramInstance programInstance, OrganisationUnit organisationUnit, Date dueDate, Date executionDate, int status,
         Coordinate coordinate, String storedBy, String programStageInstanceUid )
     {
         ProgramStageInstance programStageInstance = new ProgramStageInstance();
@@ -737,7 +805,7 @@
 
     private void updateProgramStageInstance( ProgramStage programStage, ProgramInstance programInstance,
 
-    OrganisationUnit organisationUnit, Date dueDate, Date executionDate, int status, Coordinate coordinate,
+        OrganisationUnit organisationUnit, Date dueDate, Date executionDate, int status, Coordinate coordinate,
         String storedBy, ProgramStageInstance programStageInstance )
     {
         programStageInstance.setProgramInstance( programInstance );

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java	2014-07-02 16:24:42 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/EventService.java	2014-10-08 06:12:13 +0000
@@ -71,6 +71,10 @@
 
     ImportSummary addEvent( Event event, ImportOptions importOptions );
 
+    ImportSummaries addEvents( List<Event> events, ImportOptions importOptions );
+
+    ImportSummaries addEvents( List<Event> events, ImportOptions importOptions, TaskId taskId );
+
     ImportSummary addEventXml( InputStream inputStream ) throws IOException;
 
     ImportSummary addEventXml( InputStream inputStream, ImportOptions importOptions ) throws IOException;
@@ -98,9 +102,9 @@
     void updateEvent( Event event, boolean singleValue );
 
     void updateEvent( Event event, boolean singleValue, ImportOptions importOptions );
-    
+
     void updateEventForNote( Event event );
-    
+
     void updateEventForEventDate( Event event );
 
     // -------------------------------------------------------------------------

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/ImportEventsTask.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/ImportEventsTask.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/ImportEventsTask.java	2014-10-08 06:12:13 +0000
@@ -0,0 +1,69 @@
+package org.hisp.dhis.dxf2.events.event;
+
+/*
+ * Copyright (c) 2004-2014, 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.hisp.dhis.dxf2.metadata.ImportOptions;
+import org.hisp.dhis.scheduling.TaskId;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.util.List;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class ImportEventsTask
+    implements Runnable
+{
+    private final List<Event> events;
+
+    private final EventService eventService;
+
+    private final ImportOptions importOptions;
+
+    private final TaskId taskId;
+
+    private final Authentication authentication;
+
+    public ImportEventsTask( List<Event> events, EventService eventService, ImportOptions importOptions, TaskId taskId )
+    {
+        this.events = events;
+        this.eventService = eventService;
+        this.importOptions = importOptions;
+        this.taskId = taskId;
+        this.authentication = SecurityContextHolder.getContext().getAuthentication();
+    }
+
+    @Override
+    public void run()
+    {
+        SecurityContextHolder.getContext().setAuthentication( authentication );
+        eventService.addEvents( events, importOptions, taskId );
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JacksonEventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JacksonEventService.java	2014-09-23 07:15:21 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/JacksonEventService.java	2014-10-08 06:12:13 +0000
@@ -33,7 +33,6 @@
 import com.fasterxml.jackson.dataformat.xml.XmlMapper;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.hibernate.SessionFactory;
 import org.hisp.dhis.dxf2.importsummary.ImportSummaries;
 import org.hisp.dhis.dxf2.importsummary.ImportSummary;
 import org.hisp.dhis.dxf2.metadata.ImportOptions;
@@ -41,8 +40,6 @@
 import org.hisp.dhis.dxf2.timer.Timer;
 import org.hisp.dhis.scheduling.TaskId;
 import org.hisp.dhis.system.notification.NotificationLevel;
-import org.hisp.dhis.system.notification.Notifier;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StreamUtils;
 
@@ -60,14 +57,6 @@
 {
     private static final Log log = LogFactory.getLog( JacksonEventService.class );
 
-    @Autowired
-    private Notifier notifier;
-
-    @Autowired
-    private SessionFactory sessionFactory;
-
-    private final int FLUSH_FREQUENCY = 20;
-
     // -------------------------------------------------------------------------
     // EventService Impl
     // -------------------------------------------------------------------------
@@ -76,25 +65,25 @@
 
     private final static ObjectMapper jsonMapper = new ObjectMapper();
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromXml( InputStream inputStream, Class<?> clazz ) throws IOException
     {
         return (T) xmlMapper.readValue( inputStream, clazz );
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromXml( String input, Class<?> clazz ) throws IOException
     {
         return (T) xmlMapper.readValue( input, clazz );
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromJson( InputStream inputStream, Class<?> clazz ) throws IOException
     {
         return (T) jsonMapper.readValue( inputStream, clazz );
     }
 
-    @SuppressWarnings( "unchecked" )
+    @SuppressWarnings("unchecked")
     private static <T> T fromJson( String input, Class<?> clazz ) throws IOException
     {
         return (T) jsonMapper.readValue( input, clazz );
@@ -136,21 +125,7 @@
         try
         {
             Events events = fromXml( input, Events.class );
-
-            int counter = 0;
-
-            for ( Event event : events.getEvents() )
-            {
-                importSummaries.addImportSummary( addEvent( event, importOptions ) );
-
-                if ( counter % FLUSH_FREQUENCY == 0 )
-                {
-                    sessionFactory.getCurrentSession().flush();
-                    sessionFactory.getCurrentSession().clear();
-                }
-
-                counter++;
-            }
+            importSummaries = addEvents( events.getEvents(), importOptions );
         }
         catch ( Exception ex )
         {
@@ -212,21 +187,7 @@
         try
         {
             Events events = fromJson( input, Events.class );
-
-            int counter = 0;
-
-            for ( Event event : events.getEvents() )
-            {
-                importSummaries.addImportSummary( addEvent( event, importOptions ) );
-
-                if ( counter % FLUSH_FREQUENCY == 0 )
-                {
-                    sessionFactory.getCurrentSession().flush();
-                    sessionFactory.getCurrentSession().clear();
-                }
-
-                counter++;
-            }
+            importSummaries = addEvents( events.getEvents(), importOptions );
         }
         catch ( Exception ex )
         {

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventDataValue.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventDataValue.java	2014-10-08 05:11:14 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventDataValue.java	2014-10-08 06:12:13 +0000
@@ -40,6 +40,8 @@
 @JsonPropertyOrder( {
     "event",
     "status",
+    "program",
+    "programStage",
     "enrollment",
     "eventDate",
     "dueDate",
@@ -56,6 +58,10 @@
 
     private String status;
 
+    private String program;
+
+    private String programStage;
+
     private String enrollment;
 
     private String eventDate;
@@ -84,6 +90,8 @@
 
         this.event = dataValue.getEvent();
         this.status = dataValue.getStatus();
+        this.program = dataValue.getProgram();
+        this.programStage = dataValue.getProgramStage();
         this.enrollment = dataValue.getEnrollment();
         this.eventDate = dataValue.getEventDate();
         this.dueDate = dataValue.getDueDate();
@@ -118,6 +126,28 @@
     }
 
     @JsonProperty
+    public String getProgram()
+    {
+        return program;
+    }
+
+    public void setProgram( String program )
+    {
+        this.program = program;
+    }
+
+    @JsonProperty
+    public String getProgramStage()
+    {
+        return programStage;
+    }
+
+    public void setProgramStage( String programStage )
+    {
+        this.programStage = programStage;
+    }
+
+    @JsonProperty
     public String getEnrollment()
     {
         return enrollment;
@@ -219,11 +249,11 @@
     @Override
     public int hashCode()
     {
-        return Objects.hash( event, status, enrollment, eventDate, dueDate, latitude, longitude, dataElement, value, providedElsewhere, storedBy );
+        return Objects.hash( event, status, program, programStage, enrollment, eventDate, dueDate, latitude, longitude, dataElement,
+            value, storedBy, providedElsewhere );
     }
 
-    @Override
-    public boolean equals( Object obj )
+    @Override public boolean equals( Object obj )
     {
         if ( this == obj )
         {
@@ -236,17 +266,13 @@
 
         final CsvEventDataValue other = (CsvEventDataValue) obj;
 
-        return Objects.equals( this.event, other.event )
-            && Objects.equals( this.status, other.status )
-            && Objects.equals( this.enrollment, other.enrollment )
-            && Objects.equals( this.eventDate, other.eventDate )
-            && Objects.equals( this.dueDate, other.dueDate )
-            && Objects.equals( this.latitude, other.latitude )
-            && Objects.equals( this.longitude, other.longitude )
-            && Objects.equals( this.dataElement, other.dataElement )
-            && Objects.equals( this.value, other.value )
-            && Objects.equals( this.storedBy, other.storedBy )
-            && Objects.equals( this.providedElsewhere, other.providedElsewhere );
+        return Objects.equals( this.event, other.event ) && Objects.equals( this.status, other.status ) && Objects.equals( this.program,
+            other.program ) && Objects.equals( this.programStage, other.programStage ) && Objects.equals( this.enrollment,
+            other.enrollment ) && Objects.equals( this.eventDate, other.eventDate ) && Objects.equals( this.dueDate,
+            other.dueDate ) && Objects.equals( this.latitude, other.latitude ) && Objects.equals( this.longitude,
+            other.longitude ) && Objects.equals( this.dataElement, other.dataElement ) && Objects.equals( this.value,
+            other.value ) && Objects.equals( this.storedBy, other.storedBy ) && Objects.equals( this.providedElsewhere,
+            other.providedElsewhere );
     }
 
     @Override
@@ -255,6 +281,8 @@
         return com.google.common.base.Objects.toStringHelper( this )
             .add( "event", event )
             .add( "status", status )
+            .add( "program", program )
+            .add( "programStage", programStage )
             .add( "enrollment", enrollment )
             .add( "eventDate", eventDate )
             .add( "dueDate", dueDate )

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventService.java	2014-10-08 06:12:13 +0000
@@ -0,0 +1,45 @@
+package org.hisp.dhis.dxf2.events.event.csv;
+
+/*
+ * Copyright (c) 2004-2014, 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.hisp.dhis.dxf2.events.event.Events;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public interface CsvEventService
+{
+    void writeEvents( OutputStream outputStream, Events events, boolean withHeader ) throws IOException;
+
+    Events readEvents( InputStream inputStream, boolean skipFirst ) throws IOException;
+}

=== removed file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventUtils.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventUtils.java	2014-10-08 05:11:14 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventUtils.java	1970-01-01 00:00:00 +0000
@@ -1,160 +0,0 @@
-package org.hisp.dhis.dxf2.events.event.csv;
-
-/*
- * Copyright (c) 2004-2014, 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 com.fasterxml.jackson.databind.MappingIterator;
-import com.fasterxml.jackson.databind.ObjectReader;
-import com.fasterxml.jackson.databind.ObjectWriter;
-import com.fasterxml.jackson.dataformat.csv.CsvMapper;
-import com.fasterxml.jackson.dataformat.csv.CsvParser;
-import com.fasterxml.jackson.dataformat.csv.CsvSchema;
-import org.hisp.dhis.dxf2.events.event.Coordinate;
-import org.hisp.dhis.dxf2.events.event.DataValue;
-import org.hisp.dhis.dxf2.events.event.Event;
-import org.hisp.dhis.dxf2.events.event.Events;
-import org.hisp.dhis.event.EventStatus;
-import org.springframework.util.StringUtils;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
- */
-public final class CsvEventUtils
-{
-    private static CsvMapper csvMapper = new CsvMapper();
-
-    private static CsvSchema csvSchema = csvMapper.schemaFor( CsvEventDataValue.class ).withLineSeparator( "\n" );
-
-    static
-    {
-        csvMapper.enable( CsvParser.Feature.WRAP_AS_ARRAY );
-    }
-
-    public static CsvMapper getCsvMapper()
-    {
-        return csvMapper;
-    }
-
-    public static CsvSchema getCsvSchema()
-    {
-        return csvSchema;
-    }
-
-    public static void writeEvents( OutputStream outputStream, Events events, boolean withHeader ) throws IOException
-    {
-        ObjectWriter writer = getCsvMapper().writer( getCsvSchema().withUseHeader( withHeader ) );
-
-        List<CsvEventDataValue> dataValues = new ArrayList<>();
-
-        for ( Event event : events.getEvents() )
-        {
-            CsvEventDataValue templateDataValue = new CsvEventDataValue();
-            templateDataValue.setEvent( event.getEvent() );
-            templateDataValue.setStatus( event.getStatus() != null ? event.getStatus().name() : null );
-            templateDataValue.setEnrollment( event.getEnrollment() );
-            templateDataValue.setEventDate( event.getEventDate() );
-            templateDataValue.setDueDate( event.getDueDate() );
-            templateDataValue.setStoredBy( event.getStoredBy() );
-
-            if ( event.getCoordinate() != null )
-            {
-                templateDataValue.setLatitude( event.getCoordinate().getLatitude() );
-                templateDataValue.setLongitude( event.getCoordinate().getLongitude() );
-            }
-
-            for ( DataValue value : event.getDataValues() )
-            {
-                CsvEventDataValue dataValue = new CsvEventDataValue( templateDataValue );
-                dataValue.setDataElement( value.getDataElement() );
-                dataValue.setValue( value.getValue() );
-                dataValue.setProvidedElsewhere( value.getProvidedElsewhere() );
-
-                if ( value.getStoredBy() != null )
-                {
-                    dataValue.setStoredBy( value.getStoredBy() );
-                }
-
-                dataValues.add( dataValue );
-            }
-        }
-
-        writer.writeValue( outputStream, dataValues );
-    }
-
-    public static Events readEvents( InputStream inputStream, boolean skipFirst ) throws IOException
-    {
-        Events events = new Events();
-
-        ObjectReader reader = getCsvMapper()
-            .reader( CsvEventDataValue.class ).with( getCsvSchema().withSkipFirstDataRow( skipFirst ) );
-
-        MappingIterator<CsvEventDataValue> iterator = reader.readValues( inputStream );
-        Event event = new Event();
-        event.setEvent( "not_valid" );
-
-        while ( iterator.hasNext() )
-        {
-            CsvEventDataValue dataValue = iterator.next();
-
-            if ( !event.getEvent().equals( dataValue.getEvent() ) )
-            {
-                event = new Event();
-                event.setEvent( dataValue.getEvent() );
-                event.setStatus( StringUtils.isEmpty( dataValue.getStatus() ) ? EventStatus.ACTIVE : Enum.valueOf( EventStatus.class, dataValue.getStatus() ) );
-                event.setEnrollment( dataValue.getEnrollment() );
-                event.setEventDate( event.getEventDate() );
-                event.setDueDate( event.getDueDate() );
-
-                if ( dataValue.getLongitude() != null && dataValue.getLatitude() != null )
-                {
-                    event.setCoordinate( new Coordinate( dataValue.getLongitude(), dataValue.getLatitude() ) );
-                }
-
-                events.getEvents().add( event );
-            }
-
-            DataValue value = new DataValue( dataValue.getDataElement(), dataValue.getValue() );
-            value.setStoredBy( dataValue.getStoredBy() );
-            value.setProvidedElsewhere( dataValue.getProvidedElsewhere() );
-
-            event.getDataValues().add( value );
-        }
-
-        return events;
-    }
-
-    private CsvEventUtils()
-    {
-    }
-}

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/DefaultCsvEventService.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/DefaultCsvEventService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/DefaultCsvEventService.java	2014-10-08 06:12:13 +0000
@@ -0,0 +1,157 @@
+package org.hisp.dhis.dxf2.events.event.csv;
+
+/*
+ * Copyright (c) 2004-2014, 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 com.fasterxml.jackson.databind.MappingIterator;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.dataformat.csv.CsvMapper;
+import com.fasterxml.jackson.dataformat.csv.CsvParser;
+import com.fasterxml.jackson.dataformat.csv.CsvSchema;
+import org.hisp.dhis.common.IdentifiableObjectManager;
+import org.hisp.dhis.dxf2.events.event.Coordinate;
+import org.hisp.dhis.dxf2.events.event.DataValue;
+import org.hisp.dhis.dxf2.events.event.Event;
+import org.hisp.dhis.dxf2.events.event.Events;
+import org.hisp.dhis.event.EventStatus;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.StringUtils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class DefaultCsvEventService implements CsvEventService
+{
+    private static CsvMapper csvMapper = new CsvMapper();
+
+    private static CsvSchema csvSchema = csvMapper.schemaFor( CsvEventDataValue.class ).withLineSeparator( "\n" );
+
+    @Autowired
+    private IdentifiableObjectManager manager;
+
+    static
+    {
+        csvMapper.enable( CsvParser.Feature.WRAP_AS_ARRAY );
+    }
+
+    @Override
+    public void writeEvents( OutputStream outputStream, Events events, boolean withHeader ) throws IOException
+    {
+        ObjectWriter writer = csvMapper.writer( csvSchema.withUseHeader( withHeader ) );
+
+        List<CsvEventDataValue> dataValues = new ArrayList<>();
+
+        for ( Event event : events.getEvents() )
+        {
+            CsvEventDataValue templateDataValue = new CsvEventDataValue();
+            templateDataValue.setEvent( event.getEvent() );
+            templateDataValue.setStatus( event.getStatus() != null ? event.getStatus().name() : null );
+            templateDataValue.setProgram( event.getProgram() );
+            templateDataValue.setProgramStage( event.getProgramStage() );
+            templateDataValue.setEnrollment( event.getEnrollment() );
+            templateDataValue.setEventDate( event.getEventDate() );
+            templateDataValue.setDueDate( event.getDueDate() );
+            templateDataValue.setStoredBy( event.getStoredBy() );
+
+            if ( event.getCoordinate() != null )
+            {
+                templateDataValue.setLatitude( event.getCoordinate().getLatitude() );
+                templateDataValue.setLongitude( event.getCoordinate().getLongitude() );
+            }
+
+            for ( DataValue value : event.getDataValues() )
+            {
+                CsvEventDataValue dataValue = new CsvEventDataValue( templateDataValue );
+                dataValue.setDataElement( value.getDataElement() );
+                dataValue.setValue( value.getValue() );
+                dataValue.setProvidedElsewhere( value.getProvidedElsewhere() );
+
+                if ( value.getStoredBy() != null )
+                {
+                    dataValue.setStoredBy( value.getStoredBy() );
+                }
+
+                dataValues.add( dataValue );
+            }
+        }
+
+        writer.writeValue( outputStream, dataValues );
+    }
+
+    @Override
+    public Events readEvents( InputStream inputStream, boolean skipFirst ) throws IOException
+    {
+        Events events = new Events();
+
+        ObjectReader reader = csvMapper
+            .reader( CsvEventDataValue.class ).with( csvSchema.withSkipFirstDataRow( skipFirst ) );
+
+        MappingIterator<CsvEventDataValue> iterator = reader.readValues( inputStream );
+        Event event = new Event();
+        event.setEvent( "not_valid" );
+
+        while ( iterator.hasNext() )
+        {
+            CsvEventDataValue dataValue = iterator.next();
+
+            if ( !event.getEvent().equals( dataValue.getEvent() ) )
+            {
+                event = new Event();
+                event.setEvent( dataValue.getEvent() );
+                event.setStatus( StringUtils.isEmpty( dataValue.getStatus() ) ? EventStatus.ACTIVE : Enum.valueOf( EventStatus.class, dataValue.getStatus() ) );
+                event.setProgram( dataValue.getProgram() );
+                event.setProgramStage( dataValue.getProgramStage() );
+                event.setEnrollment( dataValue.getEnrollment() );
+                event.setEventDate( event.getEventDate() );
+                event.setDueDate( event.getDueDate() );
+
+                if ( dataValue.getLongitude() != null && dataValue.getLatitude() != null )
+                {
+                    event.setCoordinate( new Coordinate( dataValue.getLongitude(), dataValue.getLatitude() ) );
+                }
+
+                events.getEvents().add( event );
+            }
+
+            DataValue value = new DataValue( dataValue.getDataElement(), dataValue.getValue() );
+            value.setStoredBy( dataValue.getStoredBy() );
+            value.setProvidedElsewhere( dataValue.getProvidedElsewhere() );
+
+            event.getDataValues().add( value );
+        }
+
+        return events;
+    }
+}

=== modified file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-09-25 07:28:28 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/resources/META-INF/dhis/beans.xml	2014-10-08 06:12:13 +0000
@@ -3,6 +3,8 @@
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; xsi:schemaLocation=
   "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd";>
 
+  <bean id="org.hisp.dhis.dxf2.events.event.csv.CsvEventService" class="org.hisp.dhis.dxf2.events.event.csv.DefaultCsvEventService" />
+
   <bean id="org.hisp.dhis.dxf2.csv.CsvImportService" class="org.hisp.dhis.dxf2.csv.DefaultCsvImportService" />
 
   <bean id="org.hisp.dhis.dxf2.render.RenderService" class="org.hisp.dhis.dxf2.render.DefaultRenderService" />
@@ -28,7 +30,7 @@
   <bean id="org.hisp.dhis.dxf2.events.event.EventStore" class="org.hisp.dhis.dxf2.events.event.JdbcEventStore" />
 
   <bean id="org.hisp.dhis.dxf2.events.event.EventService" class="org.hisp.dhis.dxf2.events.event.JacksonEventService" />
-  
+
   <bean id="org.hisp.dhis.dxf2.events.report.EventRowService" class="org.hisp.dhis.dxf2.events.report.AbstractEventRowService" />
 
   <bean id="org.hisp.dhis.dxf2.events.person.PersonService"

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventController.java	2014-10-08 05:11:14 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventController.java	2014-10-08 06:12:13 +0000
@@ -38,7 +38,8 @@
 import org.hisp.dhis.dxf2.events.event.EventService;
 import org.hisp.dhis.dxf2.events.event.Events;
 import org.hisp.dhis.dxf2.events.event.ImportEventTask;
-import org.hisp.dhis.dxf2.events.event.csv.CsvEventUtils;
+import org.hisp.dhis.dxf2.events.event.ImportEventsTask;
+import org.hisp.dhis.dxf2.events.event.csv.CsvEventService;
 import org.hisp.dhis.dxf2.events.report.EventRowService;
 import org.hisp.dhis.dxf2.events.report.EventRows;
 import org.hisp.dhis.dxf2.events.trackedentity.TrackedEntityInstance;
@@ -111,6 +112,9 @@
     private EventService eventService;
 
     @Autowired
+    private CsvEventService csvEventService;
+
+    @Autowired
     private EventRowService eventRowService;
 
     @Autowired
@@ -198,7 +202,7 @@
             events.setEvents( PagerUtils.pageCollection( events.getEvents(), pager ) );
         }
 
-        CsvEventUtils.writeEvents( response.getOutputStream(), events, !skipHeader );
+        csvEventService.writeEvents( response.getOutputStream(), events, !skipHeader );
     }
 
     @RequestMapping( value = "", method = RequestMethod.GET )
@@ -492,7 +496,20 @@
         @RequestParam( required = false, defaultValue = "false" ) boolean skipFirst,
         HttpServletResponse response, HttpServletRequest request, ImportOptions importOptions ) throws IOException
     {
-        CsvEventUtils.readEvents( request.getInputStream(), skipFirst );
+        Events events = csvEventService.readEvents( request.getInputStream(), skipFirst );
+
+        if ( !importOptions.isAsync() )
+        {
+            ImportSummaries importSummaries = eventService.addEvents( events.getEvents(), importOptions );
+            JacksonUtils.toJson( response.getOutputStream(), importSummaries );
+        }
+        else
+        {
+            TaskId taskId = new TaskId( TaskCategory.EVENT_IMPORT, currentUserService.getCurrentUser() );
+            scheduler.executeTask( new ImportEventsTask( events.getEvents(), eventService, importOptions, taskId ) );
+            response.setHeader( "Location", ContextUtils.getRootPath( request ) + "/system/tasks/" + TaskCategory.EVENT_IMPORT );
+            response.setStatus( HttpServletResponse.SC_NO_CONTENT );
+        }
     }
 
     // -------------------------------------------------------------------------