Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions doc/release-notes/11292-update-tabular-tags-with-replace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### Tabular Tags can now be replaced

Previously the API POST /files/{id}/metadata/tabularTags could only add new tags to the tabular tags list. Now with the query parameter ?replace=true the list of tags will be replaced.

See also [the guides](https://dataverse-guide--11359.org.readthedocs.build/en/11359/api/native-api.html#updating-file-tabular-tags), #11292, and #11359.
11 changes: 11 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4605,6 +4605,8 @@ Updating File Tabular Tags

Updates the tabular tags for an existing tabular file where ``ID`` is the database id of the file to update or ``PERSISTENT_ID`` is the persistent id (DOI or Handle) of the file. Requires a ``jsonString`` expressing the tabular tag names.

The list of "tabularTags" will be added to the existing list unless the optional ``replace=true`` query parameter is included. The inclusion of this parameter will cause the pre-existing tags to be deleted and the "tabularTags" to be added. Sending an empty list will remove all of the pre-existing tags.

The JSON representation of tabular tags (``tags.json``) looks like this::

{
Expand Down Expand Up @@ -4634,6 +4636,9 @@ The fully expanded example above (without environment variables) looks like this
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
"http://demo.dataverse.org/api/files/24/metadata/tabularTags" \
-H "Content-type:application/json" --upload-file tags.json
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
"http://demo.dataverse.org/api/files/24/metadata/tabularTags?replace=true" \
-H "Content-type:application/json" --upload-file tags.json

A curl example using a ``PERSISTENT_ID``

Expand All @@ -4647,6 +4652,9 @@ A curl example using a ``PERSISTENT_ID``
curl -H "X-Dataverse-key:$API_TOKEN" -X POST \
"$SERVER_URL/api/files/:persistentId/metadata/tabularTags?persistentId=$PERSISTENT_ID" \
-H "Content-type:application/json" --upload-file $FILE_PATH
curl -H "X-Dataverse-key:$API_TOKEN" -X POST \
"$SERVER_URL/api/files/:persistentId/metadata/tabularTags?persistentId=$PERSISTENT_ID&replace=true" \
-H "Content-type:application/json" --upload-file $FILE_PATH

The fully expanded example above (without environment variables) looks like this:

Expand All @@ -4655,6 +4663,9 @@ The fully expanded example above (without environment variables) looks like this
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
"https://demo.dataverse.org/api/files/:persistentId/metadata/tabularTags?persistentId=doi:10.5072/FK2/AAA000" \
-H "Content-type:application/json" --upload-file tags.json
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
"https://demo.dataverse.org/api/files/:persistentId/metadata/tabularTags?persistentId=doi:10.5072/FK2/AAA000&replace=true" \
-H "Content-type:application/json" --upload-file tags.json

Note that the specified tabular tags must be valid. The supported tags are:

Expand Down
6 changes: 5 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/api/Files.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.harvard.iq.dataverse.api;

import com.google.api.client.util.Lists;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import edu.harvard.iq.dataverse.*;
Expand Down Expand Up @@ -918,7 +919,7 @@ public Response setFileCategories(@Context ContainerRequestContext crc, @PathPar
@AuthRequired
@Path("{id}/metadata/tabularTags")
@Produces(MediaType.APPLICATION_JSON)
public Response setFileTabularTags(@Context ContainerRequestContext crc, @PathParam("id") String dataFileId, String jsonBody) {
public Response setFileTabularTags(@Context ContainerRequestContext crc, @PathParam("id") String dataFileId, String jsonBody, @QueryParam("replace") boolean replaceData) {
return response(req -> {
DataFile dataFile = execCommand(new GetDataFileCommand(req, findDataFileOrDie(dataFileId)));
if (!dataFile.isTabularData()) {
Expand All @@ -928,6 +929,9 @@ public Response setFileTabularTags(@Context ContainerRequestContext crc, @PathPa
try (StringReader stringReader = new StringReader(jsonBody)) {
jsonObject = Json.createReader(stringReader).readObject();
JsonArray requestedTabularTagsJson = jsonObject.getJsonArray("tabularTags");
if (replaceData) {
dataFile.setTags(Lists.newArrayList());
}
for (JsonValue jsonValue : requestedTabularTagsJson) {
JsonString jsonString = (JsonString) jsonValue;
try {
Expand Down
16 changes: 16 additions & 0 deletions src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.logging.Logger;

import edu.harvard.iq.dataverse.api.auth.ApiKeyAuthMechanism;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeAll;
import io.restassured.path.json.JsonPath;
Expand Down Expand Up @@ -2717,6 +2718,21 @@ public void testSetFileTabularTags() throws InterruptedException {

setFileTabularTagsResponse = UtilIT.setFileTabularTags(nonTabularFileId, apiToken, List.of(testInvalidTabularTag));
setFileTabularTagsResponse.then().assertThat().statusCode(BAD_REQUEST.getStatusCode());

// Test set with replaceData = true to show that the list is replaced and not added to
setFileTabularTagsResponse = UtilIT.setFileTabularTags(tabularFileId, apiToken, List.of("Geospatial"), true);
setFileTabularTagsResponse.then().assertThat().statusCode(OK.getStatusCode());
getFileDataResponse = UtilIT.getFileData(tabularFileId, apiToken);
actualTabularTagsCount = getFileDataResponse.jsonPath().getList("data.dataFile.tabularTags").size();
assertEquals(1, actualTabularTagsCount);
// Test clear all tags by passing empty list
setFileTabularTagsResponse = UtilIT.setFileTabularTags(tabularFileId, apiToken, Lists.emptyList(), true);
setFileTabularTagsResponse.then().assertThat().statusCode(OK.getStatusCode());
getFileDataResponse = UtilIT.getFileData(tabularFileId, apiToken);
getFileDataResponse.prettyPrint();
getFileDataResponse.then().assertThat()
.body("data.dataFile", not(hasItem("tabularTags")))
.statusCode(OK.getStatusCode());
}

@Test
Expand Down
6 changes: 5 additions & 1 deletion src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -4191,17 +4191,21 @@ static Response setFileCategories(String dataFileId, String apiToken, List<Strin
}

static Response setFileTabularTags(String dataFileId, String apiToken, List<String> tabularTags) {
return setFileTabularTags(dataFileId, apiToken, tabularTags, null);
}
static Response setFileTabularTags(String dataFileId, String apiToken, List<String> tabularTags, Boolean replaceData) {
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
for (String tabularTag : tabularTags) {
jsonArrayBuilder.add(tabularTag);
}
String replace = replaceData != null ? "?replace=" + replaceData : "";
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
jsonObjectBuilder.add("tabularTags", jsonArrayBuilder);
String jsonString = jsonObjectBuilder.build().toString();
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.body(jsonString)
.post("/api/files/" + dataFileId + "/metadata/tabularTags");
.post("/api/files/" + dataFileId + "/metadata/tabularTags" + replace);
}

static Response deleteFileInDataset(Integer fileId, String apiToken) {
Expand Down