=== 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 @@ com.fasterxml.jackson.dataformat jackson-dataformat-xml + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + === 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 + */ +@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 + */ +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 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 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 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 @@ jackson-dataformat-xml ${jackson.version} + + com.fasterxml.jackson.dataformat + jackson-dataformat-csv + ${jackson.version} +