Skip to content

Commit

Permalink
Merge pull request #3550 from IQSS/2431-2461-3483-3547-native-api-pub…
Browse files Browse the repository at this point in the history
…lish

Native API publish: POST, no 0.1, DOIs #2431 #2461 #3483 #3547
  • Loading branch information
kcondon authored Jan 13, 2017
2 parents da4bbc6 + b9e8183 commit 4f1a073
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 41 deletions.
2 changes: 2 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ Publishes the dataset whose id is passed. The new dataset version number is dete

POST http://$SERVER/api/datasets/$id/actions/:publish?type=$type&key=$apiKey

.. note:: POST should be used to publish a dataset. GET is supported for backward compatibility but is deprecated and may be removed: https://github.com/IQSS/dataverse/issues/2431

Deletes the draft version of dataset ``$id``. Only the draft version can be deleted::

DELETE http://$SERVER/api/datasets/$id/versions/:draft?key=$apiKey
Expand Down
69 changes: 39 additions & 30 deletions src/main/java/edu/harvard/iq/dataverse/api/Datasets.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
@Path("datasets")
public class Datasets extends AbstractApiBean {

private static final Logger LOGGER = Logger.getLogger(Datasets.class.getName());
private static final Logger logger = Logger.getLogger(Datasets.class.getCanonicalName());

private static final String PERSISTENT_ID_KEY=":persistentId";

Expand Down Expand Up @@ -148,7 +148,7 @@ public Response exportDataset(@QueryParam("persistentId") String persistentId, @
// (the way Access API streams its output).
// -- L.A., 4.5

LOGGER.fine("xml to return: " + xml);
logger.fine("xml to return: " + xml);
String mediaType = MediaType.TEXT_PLAIN;
if (instance.isXMLFormat(exporter)){
mediaType = MediaType.APPLICATION_XML;
Expand Down Expand Up @@ -334,7 +334,7 @@ public Response updateDraftVersion( String jsonBody, @PathParam("id") String id,
return ok( json(managedVersion) );

} catch (JsonParseException ex) {
LOGGER.log(Level.SEVERE, "Semantic error parsing dataset version Json: " + ex.getMessage(), ex);
logger.log(Level.SEVERE, "Semantic error parsing dataset version Json: " + ex.getMessage(), ex);
return error( Response.Status.BAD_REQUEST, "Error parsing dataset version: " + ex.getMessage() );

} catch (WrappedResponse ex) {
Expand All @@ -343,36 +343,45 @@ public Response updateDraftVersion( String jsonBody, @PathParam("id") String id,
}
}

/**
* @deprecated This was shipped as a GET but should have been a POST, see https://github.com/IQSS/dataverse/issues/2431
*/
@GET
@Path("{id}/actions/:publish")
public Response publishDataset( @PathParam("id") String id, @QueryParam("type") String type ) {
@Path("{id}/actions/:publish")
@Deprecated
public Response publishDataseUsingGetDeprecated( @PathParam("id") String id, @QueryParam("type") String type ) {
logger.info("publishDataseUsingGetDeprecated called on id " + id + ". Encourage use of POST rather than GET, which is deprecated.");
return publishDataset(id, type);
}

@POST
@Path("{id}/actions/:publish")
public Response publishDataset(@PathParam("id") String id, @QueryParam("type") String type) {
try {
if ( type == null ) {
return error( Response.Status.BAD_REQUEST, "Missing 'type' parameter (either 'major' or 'minor').");
if (type == null) {
return error(Response.Status.BAD_REQUEST, "Missing 'type' parameter (either 'major' or 'minor').");
}

type = type.toLowerCase();
boolean isMinor;
switch ( type ) {
case "minor": isMinor = true; break;
case "major": isMinor = false; break;
default: return error( Response.Status.BAD_REQUEST, "Illegal 'type' parameter value '" + type + "'. It needs to be either 'major' or 'minor'.");
switch (type) {
case "minor":
isMinor = true;
break;
case "major":
isMinor = false;
break;
default:
return error(Response.Status.BAD_REQUEST, "Illegal 'type' parameter value '" + type + "'. It needs to be either 'major' or 'minor'.");
}
long dsId;
try {
dsId = Long.parseLong(id);
} catch ( NumberFormatException nfe ) {
return error( Response.Status.BAD_REQUEST, "Bad dataset id. Please provide a number.");
}

Dataset ds = datasetService.find(dsId);

return ( ds == null ) ? notFound("Can't find dataset with id '" + id + "'")
: ok( json(execCommand(new PublishDatasetCommand(ds,
createDataverseRequest(findAuthenticatedUserOrDie()),
isMinor))) );

} catch (WrappedResponse ex) {

Dataset ds = findDatasetOrDie(id);

return ok(json(execCommand(new PublishDatasetCommand(ds,
createDataverseRequest(findAuthenticatedUserOrDie()),
isMinor))));

} catch (WrappedResponse ex) {
return ex.getResponse();
}
}
Expand Down Expand Up @@ -420,7 +429,7 @@ public Response getDdi(@QueryParam("id") long id, @QueryParam("persistentId") St
return error(Response.Status.FORBIDDEN, "Not a superuser");
}

LOGGER.fine("looking up " + persistentId);
logger.fine("looking up " + persistentId);
Dataset dataset = datasetService.findByGlobalId(persistentId);
if (dataset == null) {
return error(Response.Status.NOT_FOUND, "A dataset with the persistentId " + persistentId + " could not be found.");
Expand All @@ -439,7 +448,7 @@ public Response getDdi(@QueryParam("id") long id, @QueryParam("persistentId") St
ddiExportService.exportDataset(dataset.getId(), outputStream, null, null);
xml = outputStream.toString();
}
LOGGER.fine("xml to return: " + xml);
logger.fine("xml to return: " + xml);

return Response.ok()
.entity(xml)
Expand Down Expand Up @@ -473,7 +482,7 @@ public Response createAssignment(String userOrGroup, @PathParam("identifier") St
return ok(
json(execCommand(new AssignRoleCommand(assignee, theRole, dataset, createDataverseRequest(findUserOrDie()), privateUrlToken))));
} catch (WrappedResponse ex) {
LOGGER.log(Level.WARNING, "Can''t create assignment: {0}", ex.getMessage());
logger.log(Level.WARNING, "Can''t create assignment: {0}", ex.getMessage());
return ex.getResponse();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ public Dataset execute(CommandContext ctxt) throws CommandException {
throw new IllegalCommandException("Latest version of dataset " + theDataset.getIdentifier() + " is already released. Only draft versions can be released.", this);
}

// prevent publishing of 0.1 version
if (minorRelease && theDataset.getVersions().size() == 1 && theDataset.getLatestVersion().isDraft()) {
throw new IllegalCommandException("Cannot publish as minor version. Re-try as major release.", this);
}

if (minorRelease && !theDataset.getLatestVersion().isMinorUpdate()) {
throw new IllegalCommandException("Cannot release as minor version. Re-try as major release.", this);
}
Expand Down
23 changes: 21 additions & 2 deletions src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import java.util.UUID;
import static javax.ws.rs.core.Response.Status.NO_CONTENT;
import static junit.framework.Assert.assertEquals;
import org.hamcrest.CoreMatchers;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;

Expand Down Expand Up @@ -91,11 +90,31 @@ public void testCreatePublishDestroyDataset() {
createDatasetResponse.prettyPrint();
Integer datasetId = JsonPath.from(createDatasetResponse.body().asString()).getInt("data.id");

Response getDatasetJsonBeforePublishing = UtilIT.nativeGet(datasetId, apiToken);
getDatasetJsonBeforePublishing.prettyPrint();
String protocol = JsonPath.from(getDatasetJsonBeforePublishing.getBody().asString()).getString("data.protocol");
String authority = JsonPath.from(getDatasetJsonBeforePublishing.getBody().asString()).getString("data.authority");
String identifier = JsonPath.from(getDatasetJsonBeforePublishing.getBody().asString()).getString("data.identifier");
String datasetPersistentId = protocol + ":" + authority + "/" + identifier;

Response publishDataverse = UtilIT.publishDataverseViaSword(dataverseAlias, apiToken);
assertEquals(200, publishDataverse.getStatusCode());
Response publishDataset = UtilIT.publishDatasetViaNativeApi(datasetId, "major", apiToken);
Response attemptToPublishZeroDotOne = UtilIT.publishDatasetViaNativeApiDeprecated(datasetPersistentId, "minor", apiToken);
attemptToPublishZeroDotOne.prettyPrint();
attemptToPublishZeroDotOne.then().assertThat()
.body("message", equalTo("Cannot publish as minor version. Re-try as major release."))
.statusCode(403);

Response publishDataset = UtilIT.publishDatasetViaNativeApi(datasetPersistentId, "major", apiToken);
assertEquals(200, publishDataset.getStatusCode());

Response getDatasetJsonAfterPublishing = UtilIT.nativeGet(datasetId, apiToken);
getDatasetJsonAfterPublishing.prettyPrint();
getDatasetJsonAfterPublishing.then().assertThat()
.body("data.latestVersion.versionNumber", equalTo(1))
.body("data.latestVersion.versionMinorNumber", equalTo(0))
.statusCode(OK.getStatusCode());

Response deleteDatasetResponse = UtilIT.destroyDataset(datasetId, apiToken);
deleteDatasetResponse.prettyPrint();
assertEquals(200, deleteDatasetResponse.getStatusCode());
Expand Down
4 changes: 0 additions & 4 deletions src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -1165,10 +1165,6 @@ private Response publishDatasetViaNative(long datasetId, String apiToken) {
/**
* This should probably be a POST rather than a GET:
* https://github.com/IQSS/dataverse/issues/2431
*
* Allows version less than v1.0 to be published (i.e. v0.1):
* https://github.com/IQSS/dataverse/issues/2461
*
*/
return given()
.header(keyString, apiToken)
Expand Down
23 changes: 18 additions & 5 deletions src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.path.xml.XmlPath.from;
import java.math.BigDecimal;
import java.util.List;
import javax.json.JsonValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
Expand Down Expand Up @@ -426,13 +424,28 @@ static Response publishDatasetViaSword(String persistentId, String apiToken) {
.post(swordConfiguration.getBaseUrlPathCurrent() + "/edit/study/" + persistentId);
}

static Response publishDatasetViaNativeApi(String persistentId, String majorOrMinor, String apiToken) {
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.urlEncodingEnabled(false)
.post("/api/datasets/:persistentId/actions/:publish?type=" + majorOrMinor + "&persistentId=" + persistentId);
}

static Response publishDatasetViaNativeApiDeprecated(String persistentId, String majorOrMinor, String apiToken) {
/**
* @todo This should be a POST rather than a GET:
* https://github.com/IQSS/dataverse/issues/2431
*/
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.urlEncodingEnabled(false)
.get("/api/datasets/:persistentId/actions/:publish?type=" + majorOrMinor + "&persistentId=" + persistentId);
}

static Response publishDatasetViaNativeApi(Integer datasetId, String majorOrMinor, String apiToken) {
/**
* @todo This should be a POST rather than a GET:
* https://github.com/IQSS/dataverse/issues/2431
*
* @todo Prevent version less than v1.0 to be published (i.e. v0.1):
* https://github.com/IQSS/dataverse/issues/2461
*/
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
Expand Down

0 comments on commit 4f1a073

Please sign in to comment.