Skip to content
11 changes: 11 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
Original file line number Diff line number Diff line change
Expand Up @@ -1969,4 +1969,15 @@ public Response createTemplate(@Context ContainerRequestContext crc, String body
return e.getResponse();
}
}

@GET
@AuthRequired
@Path("{identifier}/metadataLanguage")
public Response getMetadataLanguage(@Context ContainerRequestContext crc, @PathParam("identifier") String dvIdtf) {
return response(req -> {
Dataverse dataverse = findDataverseOrDie(dvIdtf);
return ok(jsonLanguage(execCommand(
new GetDataverseMetadataLanguageCommand(req, dataverse))));
}, getRequestUser(crc));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package edu.harvard.iq.dataverse.engine.command.impl;

import java.util.Collections;
import java.util.Map;
import java.util.Set;

import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.DvObjectContainer;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.engine.command.AbstractCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;

public class GetDataverseMetadataLanguageCommand extends AbstractCommand<Map<String, String>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm refreshing myself on how this feature even works by reading https://guides.dataverse.org/en/6.8/installation/config.html#allowing-the-language-used-for-dataset-metadata-to-be-specified

In this command we're doing a get. Is there a command or at least an API endpoint for doing a set? As of #7958 the docs above say that the metadata language can be configured per collection but is only possible via the UI? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, there's no API endpoint currently to set a metadata language in a collection. It's possible via the UI and Dataverse has a setter method

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks for confirming. Are you interested in expanding the scope of this pull request to include the setter method?

Also, it could be expanded, if you want, to include a getter for the :MetadataLanguages setting. Please see https://guides.dataverse.org/en/6.8/developers/api-design.html#exposing-settings

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the GET method is sufficient for my purposes, but adding a POST doesn't seem to be much work. I'll do it tomorrow.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, we have a PUT method now!


private final Dataverse dv;

public GetDataverseMetadataLanguageCommand(DataverseRequest aRequest, Dataverse dv) {
super(aRequest, dv);
this.dv = dv;
}

@Override
public Map<String, String> execute(CommandContext ctxt) throws CommandException {
Map<String, String> langMap = ctxt.settings().getBaseMetadataLanguageMap(null, true);
String dvMetadataLanguage = dv.getMetadataLanguage();
if (!dvMetadataLanguage.equals(DvObjectContainer.UNDEFINED_CODE)) {
return Collections.singletonMap(dvMetadataLanguage, langMap.get(dvMetadataLanguage));
}
return langMap;

}

@Override
public Map<String, Set<Permission>> getRequiredPermissions() {
return Collections.singletonMap("",
dv.isReleased() ? Collections.<Permission>emptySet()
: Collections.singleton(Permission.ViewUnpublishedDataverse));
}
}
10 changes: 10 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1685,4 +1685,14 @@ public static JsonArrayBuilder json(List<UserNotification> notifications, Authen

return notificationsArray;
}

public static JsonObjectBuilder jsonLanguage(String locale, String title) {
// returns a single metadata language entry
return jsonObjectBuilder().add("locale", locale).add("title", title);
}

public static JsonArrayBuilder jsonLanguage(Map<String, String> langMap) {
// returns an array of metadatalanguages
return Json.createArrayBuilder(langMap.entrySet().stream().map(entry -> jsonLanguage(entry.getKey(), entry.getValue())).toList());
}
}
31 changes: 31 additions & 0 deletions src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -2457,4 +2457,35 @@ private String getSuperuserToken() {
UtilIT.makeSuperUser(username);
return adminApiToken;
}

@Test
public void testGetDataverseMetadataLanguage() {
Response createUser = UtilIT.createRandomUser();
createUser.prettyPrint();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest checking for OK or CREATED (I forget which) here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is pretty common in other test cases too. It would make sense to check for CREATED in all of them, but that's beyond the scope of this pull request, I think.

String username = UtilIT.getUsernameFromResponse(createUser);
String apiToken = UtilIT.getApiTokenFromResponse(createUser);
UtilIT.deleteSetting(":MetadataLanguages");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also go in the @BeforeAll setupClass and the @AfterAll afterClass.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why isn't it enough to delete it in the beggining and end of the test case?

Response createDataverse1Response = UtilIT.createRandomDataverse(apiToken);

createDataverse1Response.prettyPrint();
createDataverse1Response.then().assertThat().statusCode(CREATED.getStatusCode());

String alias = UtilIT.getAliasFromResponse(createDataverse1Response);

Response noLang = UtilIT.getDataverseMetadataLanguage(alias, apiToken);
noLang.prettyPrint();

noLang.then().assertThat().body("data", equalTo(List.of()));

UtilIT.setSetting(":MetadataLanguages",
"[{\"locale\":\"en\",\"title\":\"English\"},{\"locale\":\"hu\",\"title\":\"magyar\"}]");
Response allLangs = UtilIT.getDataverseMetadataLanguage(alias, apiToken);
allLangs.prettyPrint();
allLangs.then().assertThat()
.body("data.size()", equalTo(2))
.and().body("data[0].locale", equalTo("en"))
.and().body("data[1].locale", equalTo("hu"));

}

}
8 changes: 8 additions & 0 deletions src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -5001,4 +5001,12 @@ public static Response callCallbackUrl(String callbackUrl) {
.when()
.get(callbackUrl);
}

public static Response getDataverseMetadataLanguage(String alias, String apiToken) {
return given()
.header(API_TOKEN_HTTP_HEADER, apiToken)
.get("/api/dataverses/"
+ alias
+ "/metadataLanguage");
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strange. A number of tests are failing.

Screenshot 2025-10-01 at 09-27-58 IQSS-Dataverse-Develop-PR_PR-11857 #1 edu harvard iq dataverse api Jenkins Screenshot 2025-10-01 at 09-28-07 IQSS-Dataverse-Develop-PR_PR-11857 #1 test - testBagItExport Jenkins

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't investigated, but when :MetadataLanguages is set, I think datasets created via the API need to specify the metadataLanguage they use. So perhaps every test run after it's set is failing? If that's true, in addition to deleting the setting at the end of the test, the test may need to be annotated to not run in parallel with anything else (@ResourceLock(GLOBAL_TEST_LOCK) ?).