diff --git a/scripts/database/upgrades/upgrade_v4.8.4_to_v4.9.sql b/scripts/database/upgrades/upgrade_v4.8.4_to_v4.9.sql new file mode 100644 index 00000000000..2e18f27232b --- /dev/null +++ b/scripts/database/upgrades/upgrade_v4.8.4_to_v4.9.sql @@ -0,0 +1 @@ +ALTER TABLE filemetadata ADD COLUMN provfreeform text; diff --git a/src/main/java/edu/harvard/iq/dataverse/FileMetadata.java b/src/main/java/edu/harvard/iq/dataverse/FileMetadata.java index 6d74ca456d4..d099dd73b84 100644 --- a/src/main/java/edu/harvard/iq/dataverse/FileMetadata.java +++ b/src/main/java/edu/harvard/iq/dataverse/FileMetadata.java @@ -75,6 +75,14 @@ public class FileMetadata implements Serializable { @JoinColumn(nullable=false) private DataFile dataFile; + /** + * There are two types of provenance types and this "free-form" type is + * represented in the GUI as text box the user can type into. The other type + * is based on PROV-JSON from the W3C. + */ + @Column(columnDefinition = "TEXT", nullable = true) + private String provFreeForm; + /** * Creates a copy of {@code this}, with identical business logic fields. * E.g., {@link #label} would be duplicated; {@link #version} will not. @@ -124,7 +132,14 @@ public boolean isRestricted() { public void setRestricted(boolean restricted) { this.restricted = restricted; } - + + public String getProvFreeForm() { + return provFreeForm; + } + + public void setProvFreeForm(String provFreeForm) { + this.provFreeForm = provFreeForm; + } /* * File Categories to which this version of the DataFile belongs: diff --git a/src/main/java/edu/harvard/iq/dataverse/api/ProvApi.java b/src/main/java/edu/harvard/iq/dataverse/api/ProvApi.java index afeba1e592d..65e8d809c3c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/ProvApi.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/ProvApi.java @@ -1,5 +1,7 @@ package edu.harvard.iq.dataverse.api; +import edu.harvard.iq.dataverse.DataFile; +import edu.harvard.iq.dataverse.FileMetadata; import java.io.StringReader; import javax.json.Json; import javax.json.JsonException; @@ -10,6 +12,8 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; @Path("files") public class ProvApi extends AbstractApiBean { @@ -50,14 +54,23 @@ public Response addProvJson(String body, @PathParam("id") Long idSupplied) { public Response addProvFreeForm(String body, @PathParam("id") Long idSupplied) { // TODO: Permissions. // TODO: Save prov free form text to FileMetadata table. + DataFile dataFile = fileSvc.find(idSupplied); + if (dataFile == null) { + return error(NOT_FOUND, "Could not file a file based on id " + idSupplied + "."); + } StringReader rdr = new StringReader(body); + JsonObject jsonObj = null; try { - JsonObject jsonObj = Json.createReader(rdr).readObject(); + jsonObj = Json.createReader(rdr).readObject(); } catch (JsonException ex) { - return error(Response.Status.BAD_REQUEST, "A valid JSON object could not be found."); + return error(BAD_REQUEST, "A valid JSON object could not be found."); } + String provFreeForm = jsonObj.getString("text"); + FileMetadata fileMetadata = dataFile.getFileMetadata(); + fileMetadata.setProvFreeForm(provFreeForm); + DataFile savedDataFile = fileSvc.save(dataFile); JsonObjectBuilder response = Json.createObjectBuilder(); - response.add("message", "A valid JSON object was uploaded to the prov-freeform endpoint."); + response.add("message", "Free-form provenance data saved: " + savedDataFile.getFileMetadata().getProvFreeForm()); return ok(response); } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/ProvApiIT.java b/src/test/java/edu/harvard/iq/dataverse/api/ProvApiIT.java index 07460129b6a..7093437546d 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/ProvApiIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/ProvApiIT.java @@ -1,6 +1,7 @@ package edu.harvard.iq.dataverse.api; import com.jayway.restassured.RestAssured; +import com.jayway.restassured.path.json.JsonPath; import com.jayway.restassured.response.Response; import javax.json.Json; import javax.json.JsonArray; @@ -50,6 +51,8 @@ public void testAddProvFile() { .body("data.files[0].label", equalTo("dataverseproject.png")) .statusCode(OK.getStatusCode()); + Long dataFileId = JsonPath.from(authorAddsFile.getBody().asString()).getLong("data.files[0].dataFile.id"); + // TODO: Test that an array fails JsonArray provJsonBadDueToBeingAnArray = Json.createArrayBuilder().add("bad").build(); @@ -58,7 +61,7 @@ public void testAddProvFile() { .add("prov", true) .add("foo", "bar") .build(); - Response uploadProvJson = UtilIT.uploadProvJson(datasetId.toString(), provJsonGood, apiTokenForDepositor); + Response uploadProvJson = UtilIT.uploadProvJson(dataFileId.toString(), provJsonGood, apiTokenForDepositor); uploadProvJson.prettyPrint(); uploadProvJson.then().assertThat() .body("data.message", equalTo("A valid JSON object was uploaded to the prov-json endpoint.")) @@ -67,10 +70,10 @@ public void testAddProvFile() { JsonObject provFreeFormGood = Json.createObjectBuilder() .add("text", "I inherited this file from my grandfather.") .build(); - Response uploadProvFreeForm = UtilIT.uploadProvFreeForm(datasetId.toString(), provFreeFormGood, apiTokenForDepositor); + Response uploadProvFreeForm = UtilIT.uploadProvFreeForm(dataFileId.toString(), provFreeFormGood, apiTokenForDepositor); uploadProvFreeForm.prettyPrint(); uploadProvFreeForm.then().assertThat() - .body("data.message", equalTo("A valid JSON object was uploaded to the prov-freeform endpoint.")) + .body("data.message", equalTo("Free-form provenance data saved: I inherited this file from my grandfather.")) .statusCode(OK.getStatusCode()); }