dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #33277
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 16975: CSV event export, wip
------------------------------------------------------------
revno: 16975
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2014-10-07 13:35:04 +0700
message:
CSV event export, wip
added:
dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/
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/CsvEventUtils.java
modified:
dhis-2/dhis-services/dhis-service-dxf2/pom.xml
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/messageconverter/RenderServiceMessageConverter.java
dhis-2/pom.xml
--
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/pom.xml'
--- dhis-2/dhis-services/dhis-service-dxf2/pom.xml 2014-07-23 14:53:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/pom.xml 2014-10-07 06:35:04 +0000
@@ -51,6 +51,10 @@
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-csv</artifactId>
+ </dependency>
</dependencies>
<properties>
=== added directory 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv'
=== added 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 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventDataValue.java 2014-10-07 06:35:04 +0000
@@ -0,0 +1,322 @@
+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.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+import org.hisp.dhis.event.EventStatus;
+import org.springframework.util.Assert;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+@JsonPropertyOrder( {
+ "event",
+ "status",
+ "program",
+ "programInstance",
+ "programStage",
+ "enrollment",
+ "enrollmentStatus",
+ "orgUnit",
+ "trackedEntityInstance",
+ "eventDate",
+ "dueDate",
+ "latitude",
+ "longitude",
+ "followUp",
+ "dataElement",
+ "value",
+ "providedElsewhere",
+ "storedBy"
+} )
+public class CsvEventDataValue
+{
+ private String event;
+
+ private EventStatus status = EventStatus.ACTIVE;
+
+ private String program;
+
+ private String programInstance;
+
+ private String programStage;
+
+ private String enrollment;
+
+ private EventStatus enrollmentStatus;
+
+ private String orgUnit;
+
+ private String trackedEntityInstance;
+
+ private String eventDate;
+
+ private String dueDate;
+
+ private Double latitude;
+
+ private Double longitude;
+
+ private Boolean followup;
+
+ private String dataElement;
+
+ private String value;
+
+ private Boolean providedElsewhere = false;
+
+ private String storedBy;
+
+ public CsvEventDataValue()
+ {
+ }
+
+ public CsvEventDataValue( CsvEventDataValue dataValue )
+ {
+ Assert.notNull( dataValue, "A non-null CsvOutputEventDataValue must be given as a parameter." );
+
+ this.event = dataValue.getEvent();
+ this.status = dataValue.getStatus();
+ this.program = dataValue.getProgram();
+ this.programInstance = dataValue.getProgramInstance();
+ this.programStage = dataValue.getProgramStage();
+ this.enrollment = dataValue.getEnrollment();
+ this.enrollmentStatus = dataValue.getEnrollmentStatus();
+ this.orgUnit = dataValue.getOrgUnit();
+ this.trackedEntityInstance = dataValue.getTrackedEntityInstance();
+ this.eventDate = dataValue.getEventDate();
+ this.dueDate = dataValue.getDueDate();
+ this.latitude = dataValue.getLatitude();
+ this.longitude = dataValue.getLongitude();
+ this.followup = dataValue.getFollowup();
+ this.dataElement = dataValue.getDataElement();
+ this.value = dataValue.getValue();
+ this.providedElsewhere = dataValue.getProvidedElsewhere();
+ this.storedBy = dataValue.getStoredBy();
+ }
+
+ @JsonProperty
+ public String getEvent()
+ {
+ return event;
+ }
+
+ public void setEvent( String event )
+ {
+ this.event = event;
+ }
+
+ @JsonProperty
+ public EventStatus getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus( EventStatus status )
+ {
+ this.status = status;
+ }
+
+ @JsonProperty
+ public String getProgram()
+ {
+ return program;
+ }
+
+ public void setProgram( String program )
+ {
+ this.program = program;
+ }
+
+ @JsonProperty
+ public String getProgramInstance()
+ {
+ return programInstance;
+ }
+
+ public void setProgramInstance( String programInstance )
+ {
+ this.programInstance = programInstance;
+ }
+
+ @JsonProperty
+ public String getProgramStage()
+ {
+ return programStage;
+ }
+
+ public void setProgramStage( String programStage )
+ {
+ this.programStage = programStage;
+ }
+
+ @JsonProperty
+ public String getEnrollment()
+ {
+ return enrollment;
+ }
+
+ public void setEnrollment( String enrollment )
+ {
+ this.enrollment = enrollment;
+ }
+
+ @JsonProperty
+ public EventStatus getEnrollmentStatus()
+ {
+ return enrollmentStatus;
+ }
+
+ public void setEnrollmentStatus( EventStatus enrollmentStatus )
+ {
+ this.enrollmentStatus = enrollmentStatus;
+ }
+
+ @JsonProperty
+ public String getOrgUnit()
+ {
+ return orgUnit;
+ }
+
+ public void setOrgUnit( String orgUnit )
+ {
+ this.orgUnit = orgUnit;
+ }
+
+ @JsonProperty
+ public String getTrackedEntityInstance()
+ {
+ return trackedEntityInstance;
+ }
+
+ public void setTrackedEntityInstance( String trackedEntityInstance )
+ {
+ this.trackedEntityInstance = trackedEntityInstance;
+ }
+
+ @JsonProperty
+ public String getEventDate()
+ {
+ return eventDate;
+ }
+
+ public void setEventDate( String eventDate )
+ {
+ this.eventDate = eventDate;
+ }
+
+ @JsonProperty
+ public String getDueDate()
+ {
+ return dueDate;
+ }
+
+ public void setDueDate( String dueDate )
+ {
+ this.dueDate = dueDate;
+ }
+
+ @JsonProperty
+ public Double getLatitude()
+ {
+ return latitude;
+ }
+
+ public void setLatitude( Double latitude )
+ {
+ this.latitude = latitude;
+ }
+
+ @JsonProperty
+ public Double getLongitude()
+ {
+ return longitude;
+ }
+
+ public void setLongitude( Double longitude )
+ {
+ this.longitude = longitude;
+ }
+
+ @JsonProperty
+ public Boolean getFollowup()
+ {
+ return followup;
+ }
+
+ public void setFollowup( Boolean followup )
+ {
+ this.followup = followup;
+ }
+
+ @JsonProperty
+ public String getDataElement()
+ {
+ return dataElement;
+ }
+
+ public void setDataElement( String dataElement )
+ {
+ this.dataElement = dataElement;
+ }
+
+ @JsonProperty
+ public String getValue()
+ {
+ return value;
+ }
+
+ public void setValue( String value )
+ {
+ this.value = value;
+ }
+
+ @JsonProperty
+ public Boolean getProvidedElsewhere()
+ {
+ return providedElsewhere;
+ }
+
+ public void setProvidedElsewhere( Boolean providedElsewhere )
+ {
+ this.providedElsewhere = providedElsewhere;
+ }
+
+ @JsonProperty
+ public String getStoredBy()
+ {
+ return storedBy;
+ }
+
+ public void setStoredBy( String storedBy )
+ {
+ this.storedBy = storedBy;
+ }
+}
=== added 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 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/events/event/csv/CsvEventUtils.java 2014-10-07 06:35:04 +0000
@@ -0,0 +1,113 @@
+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.ObjectWriter;
+import com.fasterxml.jackson.dataformat.csv.CsvMapper;
+import com.fasterxml.jackson.dataformat.csv.CsvSchema;
+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 java.io.IOException;
+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 );
+
+ public static CsvMapper getCsvMapper()
+ {
+ return csvMapper;
+ }
+
+ public static CsvSchema getCsvSchema()
+ {
+ return csvSchema;
+ }
+
+ public static void writeEvents( OutputStream outputStream, Events events, boolean withHeaders ) throws IOException
+ {
+ ObjectWriter writer = getCsvMapper().writer( getCsvSchema().withUseHeader( withHeaders ) );
+
+ List<CsvEventDataValue> dataValues = new ArrayList<>();
+
+ for ( Event event : events.getEvents() )
+ {
+ CsvEventDataValue templateDataValue = new CsvEventDataValue();
+ templateDataValue.setEvent( event.getEvent() );
+ templateDataValue.setProgram( event.getProgram() == null ? events.getProgram() : event.getProgram() );
+ templateDataValue.setProgramInstance( events.getProgramInstance() );
+ templateDataValue.setProgramStage( event.getProgramStage() );
+ templateDataValue.setEnrollment( event.getEnrollment() );
+ templateDataValue.setEnrollmentStatus( event.getEnrollmentStatus() );
+ templateDataValue.setOrgUnit( event.getOrgUnit() );
+ templateDataValue.setTrackedEntityInstance( event.getTrackedEntityInstance() );
+ 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() );
+ }
+
+ templateDataValue.setFollowup( event.getFollowup() );
+
+ 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 );
+ }
+
+ private CsvEventUtils()
+ {
+ }
+}
=== 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-04 02:37:01 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventController.java 2014-10-07 06:35:04 +0000
@@ -38,6 +38,7 @@
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.report.EventRowService;
import org.hisp.dhis.dxf2.events.report.EventRows;
import org.hisp.dhis.dxf2.events.trackedentity.TrackedEntityInstance;
@@ -125,6 +126,81 @@
// READ
// -------------------------------------------------------------------------
+ @RequestMapping( value = "", method = RequestMethod.GET, produces = { "application/csv", "text/csv" } )
+ @PreAuthorize( "hasRole('ALL') or hasRole('F_TRACKED_ENTITY_DATAVALUE_ADD')" )
+ public void getCsvEvents(
+ @RequestParam( required = false ) String program,
+ @RequestParam( required = false ) String programStage,
+ @RequestParam( required = false ) ProgramStatus programStatus,
+ @RequestParam( required = false ) Boolean followUp,
+ @RequestParam( required = false ) String trackedEntityInstance,
+ @RequestParam( required = false ) String orgUnit,
+ @RequestParam( required = false ) OrganisationUnitSelectionMode ouMode,
+ @RequestParam( required = false ) @DateTimeFormat( pattern = "yyyy-MM-dd" ) Date startDate,
+ @RequestParam( required = false ) @DateTimeFormat( pattern = "yyyy-MM-dd" ) Date endDate,
+ @RequestParam( required = false ) EventStatus status,
+ @RequestParam( required = false, defaultValue = "true") boolean withHeaders,
+ @RequestParam Map<String, String> parameters, Model model, HttpServletResponse response, HttpServletRequest request ) throws IOException
+ {
+ WebOptions options = new WebOptions( parameters );
+
+ Program pr = manager.get( Program.class, program );
+ ProgramStage prs = manager.get( ProgramStage.class, programStage );
+ List<OrganisationUnit> organisationUnits = new ArrayList<>();
+ TrackedEntityInstance tei = null;
+ OrganisationUnit rootOrganisationUnit = null;
+
+ if ( trackedEntityInstance != null )
+ {
+ tei = trackedEntityInstanceService.getTrackedEntityInstance( trackedEntityInstance );
+
+ if ( tei == null )
+ {
+ ContextUtils.conflictResponse( response, "Invalid trackedEntityInstance ID." );
+ return;
+ }
+ }
+
+ if ( orgUnit != null )
+ {
+ rootOrganisationUnit = manager.get( OrganisationUnit.class, orgUnit );
+
+ if ( rootOrganisationUnit == null )
+ {
+ ContextUtils.conflictResponse( response, "Invalid orgUnit ID." );
+ return;
+ }
+ }
+
+ if ( rootOrganisationUnit != null )
+ {
+ if ( OrganisationUnitSelectionMode.DESCENDANTS.equals( ouMode ) )
+ {
+ organisationUnits.addAll( organisationUnitService.getOrganisationUnitWithChildren( rootOrganisationUnit.getUid() ) );
+ }
+ else if ( OrganisationUnitSelectionMode.CHILDREN.equals( ouMode ) )
+ {
+ organisationUnits.add( rootOrganisationUnit );
+ organisationUnits.addAll( rootOrganisationUnit.getChildren() );
+ }
+ else // SELECTED
+ {
+ organisationUnits.add( rootOrganisationUnit );
+ }
+ }
+
+ Events events = eventService.getEvents( pr, prs, programStatus, followUp, organisationUnits, tei, startDate, endDate, status );
+
+ if ( options.hasPaging() )
+ {
+ Pager pager = new Pager( options.getPage(), events.getEvents().size(), options.getPageSize() );
+ events.setPager( pager );
+ events.setEvents( PagerUtils.pageCollection( events.getEvents(), pager ) );
+ }
+
+ CsvEventUtils.writeEvents( response.getOutputStream(), events, withHeaders );
+ }
+
@RequestMapping( value = "", method = RequestMethod.GET )
@PreAuthorize( "hasRole('ALL') or hasRole('F_TRACKED_ENTITY_DATAVALUE_ADD')" )
public String getEvents(
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/RenderServiceMessageConverter.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/RenderServiceMessageConverter.java 2014-08-05 04:03:02 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/messageconverter/RenderServiceMessageConverter.java 2014-10-07 06:35:04 +0000
@@ -63,11 +63,11 @@
{
MediaType mediaType = inputMessage.getHeaders().getContentType();
- if ( mediaType.getSubtype().equals( "json" ) )
+ if ( isJson( mediaType ) )
{
return renderService.fromJson( inputMessage.getBody(), clazz );
}
- else if ( mediaType.getSubtype().equals( "xml" ) )
+ else if ( isXml( mediaType ) )
{
return renderService.fromXml( inputMessage.getBody(), clazz );
}
@@ -80,13 +80,24 @@
{
MediaType mediaType = outputMessage.getHeaders().getContentType();
- if ( mediaType.getSubtype().equals( "json" ) )
+ if ( isJson( mediaType ) )
{
renderService.toJson( outputMessage.getBody(), object );
}
- else if ( mediaType.getSubtype().equals( "xml" ) )
+ else if ( isXml( mediaType ) )
{
renderService.toXml( outputMessage.getBody(), object );
}
}
+
+ private boolean isXml( MediaType mediaType )
+ {
+ return (mediaType.getType().equals( "application" ) || mediaType.getType().equals( "text" ))
+ && mediaType.getSubtype().equals( "xml" );
+ }
+
+ private boolean isJson( MediaType mediaType )
+ {
+ return mediaType.getType().equals( "application" ) && mediaType.getSubtype().equals( "json" );
+ }
}
=== modified file 'dhis-2/pom.xml'
--- dhis-2/pom.xml 2014-09-24 17:24:34 +0000
+++ dhis-2/pom.xml 2014-10-07 06:35:04 +0000
@@ -920,6 +920,11 @@
<artifactId>jackson-dataformat-xml</artifactId>
<version>${jackson.version}</version>
</dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.dataformat</groupId>
+ <artifactId>jackson-dataformat-csv</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
<!-- GeoTools -->
<dependency>