Skip to content

Commit 7aa6235

Browse files
authored
Merge pull request #11403 from IQSS/11401-update-categories-with-replace
add replace to update category api
2 parents e3bc7cf + 29190cd commit 7aa6235

File tree

5 files changed

+60
-6
lines changed

5 files changed

+60
-6
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### Categories can now be replaced
2+
3+
Previously the API POST /files/{id}/metadata/categories could only add new categories to the categories list. Now with the query parameter ?replace=true the list of categories will be replaced.
4+
5+
See also [the guides](https://dataverse-guide--11359.org.readthedocs.build/en/11359/api/native-api.html#updating-file-metadata-categories), #11401, and #11359.

doc/sphinx-guides/source/api/native-api.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4609,6 +4609,8 @@ Updating File Metadata Categories
46094609
46104610
Updates the categories for an existing 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 category names.
46114611
4612+
The list of "categories" 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 categories to be deleted and the new "categories" to be added. Sending an empty list will remove all of the pre-existing categories.
4613+
46124614
Although updating categories can also be done with the previous endpoint, this has been created to be more practical when it is only necessary to update categories and not other metadata fields.
46134615
46144616
The JSON representation of file categories (``categories.json``) looks like this::
@@ -4640,6 +4642,9 @@ The fully expanded example above (without environment variables) looks like this
46404642
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
46414643
"http://demo.dataverse.org/api/files/24/metadata/categories" \
46424644
-H "Content-type:application/json" --upload-file categories.json
4645+
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
4646+
"http://demo.dataverse.org/api/files/24/metadata/categories?replace=true" \
4647+
-H "Content-type:application/json" --upload-file categories.json
46434648
46444649
A curl example using a ``PERSISTENT_ID``
46454650
@@ -4653,6 +4658,9 @@ A curl example using a ``PERSISTENT_ID``
46534658
curl -H "X-Dataverse-key:$API_TOKEN" -X POST \
46544659
"$SERVER_URL/api/files/:persistentId/metadata/categories?persistentId=$PERSISTENT_ID" \
46554660
-H "Content-type:application/json" --upload-file $FILE_PATH
4661+
curl -H "X-Dataverse-key:$API_TOKEN" -X POST \
4662+
"$SERVER_URL/api/files/:persistentId/metadata/categories?persistentId=$PERSISTENT_ID&replace=true" \
4663+
-H "Content-type:application/json" --upload-file $FILE_PATH
46564664
46574665
The fully expanded example above (without environment variables) looks like this:
46584666
@@ -4661,6 +4669,9 @@ The fully expanded example above (without environment variables) looks like this
46614669
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
46624670
"https://demo.dataverse.org/api/files/:persistentId/metadata/categories?persistentId=doi:10.5072/FK2/AAA000" \
46634671
-H "Content-type:application/json" --upload-file categories.json
4672+
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X POST \
4673+
"https://demo.dataverse.org/api/files/:persistentId/metadata/categories?persistentId=doi:10.5072/FK2/AAA000&replace=true" \
4674+
-H "Content-type:application/json" --upload-file tags.json
46644675
46654676
Note that if the specified categories do not exist, they will be created.
46664677

src/main/java/edu/harvard/iq/dataverse/api/Files.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -924,14 +924,17 @@ public Response getFileDataTables(@Context ContainerRequestContext crc, @PathPar
924924
@AuthRequired
925925
@Path("{id}/metadata/categories")
926926
@Produces(MediaType.APPLICATION_JSON)
927-
public Response setFileCategories(@Context ContainerRequestContext crc, @PathParam("id") String dataFileId, String jsonBody) {
927+
public Response setFileCategories(@Context ContainerRequestContext crc, @PathParam("id") String dataFileId, String jsonBody, @QueryParam("replace") boolean replaceData) {
928928
return response(req -> {
929929
DataFile dataFile = execCommand(new GetDataFileCommand(req, findDataFileOrDie(dataFileId)));
930930
jakarta.json.JsonObject jsonObject;
931931
try (StringReader stringReader = new StringReader(jsonBody)) {
932932
jsonObject = Json.createReader(stringReader).readObject();
933933
JsonArray requestedCategoriesJson = jsonObject.getJsonArray("categories");
934934
FileMetadata fileMetadata = dataFile.getFileMetadata();
935+
if (replaceData) {
936+
fileMetadata.setCategories(Lists.newArrayList());
937+
}
935938
for (JsonValue jsonValue : requestedCategoriesJson) {
936939
JsonString jsonString = (JsonString) jsonValue;
937940
fileMetadata.addCategoryByName(jsonString.getString());

src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2659,19 +2659,50 @@ public void testSetFileCategories() {
26592659
String dataFileId = uploadResponse.getBody().jsonPath().getString("data.files[0].dataFile.id");
26602660

26612661
// Set categories
2662-
String testCategory1 = "testCategory1";
2663-
String testCategory2 = "testCategory2";
2664-
List<String> testCategories = List.of(testCategory1, testCategory2);
2662+
String testCategory0 = "testCategory0";
2663+
List<String> testCategories = List.of(testCategory0);
26652664
Response setFileCategoriesResponse = UtilIT.setFileCategories(dataFileId, apiToken, testCategories);
26662665
setFileCategoriesResponse.then().assertThat().statusCode(OK.getStatusCode());
2667-
26682666
// Get file data and check for new categories
26692667
Response getFileDataResponse = UtilIT.getFileData(dataFileId, apiToken);
26702668
getFileDataResponse.prettyPrint();
26712669
getFileDataResponse.then().assertThat()
2670+
.body("data.categories", hasItem(testCategory0))
2671+
.statusCode(OK.getStatusCode());
2672+
// Set categories
2673+
String testCategory1 = "testCategory1";
2674+
String testCategory2 = "testCategory2";
2675+
testCategories = List.of(testCategory1, testCategory2);
2676+
setFileCategoriesResponse = UtilIT.setFileCategories(dataFileId, apiToken, testCategories);
2677+
setFileCategoriesResponse.then().assertThat().statusCode(OK.getStatusCode());
2678+
// Get file data and check for new categories + original category
2679+
getFileDataResponse = UtilIT.getFileData(dataFileId, apiToken);
2680+
getFileDataResponse.prettyPrint();
2681+
getFileDataResponse.then().assertThat()
2682+
.body("data.categories", hasItem(testCategory0))
26722683
.body("data.categories", hasItem(testCategory1))
26732684
.body("data.categories", hasItem(testCategory2))
26742685
.statusCode(OK.getStatusCode());
2686+
// test replace categories
2687+
testCategories = List.of(testCategory1, testCategory2);
2688+
setFileCategoriesResponse = UtilIT.setFileCategories(dataFileId, apiToken, testCategories, true);
2689+
setFileCategoriesResponse.then().assertThat().statusCode(OK.getStatusCode());
2690+
// Get file data and check for new categories only
2691+
getFileDataResponse = UtilIT.getFileData(dataFileId, apiToken);
2692+
getFileDataResponse.prettyPrint();
2693+
getFileDataResponse.then().assertThat()
2694+
.body("data.categories", not(hasItem(testCategory0)))
2695+
.body("data.categories", hasItem(testCategory1))
2696+
.body("data.categories", hasItem(testCategory2))
2697+
.statusCode(OK.getStatusCode());
2698+
// Test clear all categories by passing empty list
2699+
setFileCategoriesResponse = UtilIT.setFileCategories(dataFileId, apiToken, Lists.emptyList(), true);
2700+
setFileCategoriesResponse.then().assertThat().statusCode(OK.getStatusCode());
2701+
getFileDataResponse = UtilIT.getFileData(dataFileId, apiToken);
2702+
getFileDataResponse.prettyPrint();
2703+
getFileDataResponse.then().assertThat()
2704+
.body("data.dataFile", not(hasItem("categories")))
2705+
.statusCode(OK.getStatusCode());
26752706
}
26762707

26772708
@Test

src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4220,17 +4220,21 @@ static Response getVersionFileCounts(Integer datasetId,
42204220
}
42214221

42224222
static Response setFileCategories(String dataFileId, String apiToken, List<String> categories) {
4223+
return setFileCategories(dataFileId, apiToken, categories, null);
4224+
}
4225+
static Response setFileCategories(String dataFileId, String apiToken, List<String> categories, Boolean replaceData) {
42234226
JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
42244227
for (String category : categories) {
42254228
jsonArrayBuilder.add(category);
42264229
}
4230+
String replace = replaceData != null ? "?replace=" + replaceData : "";
42274231
JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
42284232
jsonObjectBuilder.add("categories", jsonArrayBuilder);
42294233
String jsonString = jsonObjectBuilder.build().toString();
42304234
return given()
42314235
.header(API_TOKEN_HTTP_HEADER, apiToken)
42324236
.body(jsonString)
4233-
.post("/api/files/" + dataFileId + "/metadata/categories");
4237+
.post("/api/files/" + dataFileId + "/metadata/categories" + replace);
42344238
}
42354239

42364240
static Response setFileTabularTags(String dataFileId, String apiToken, List<String> tabularTags) {

0 commit comments

Comments
 (0)