From c3a13c893284b4376ee8db5c39364da4492068bb Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Thu, 4 Sep 2025 14:14:26 -0400 Subject: [PATCH 1/3] add support for matching object with a key in an array of strings --- .../iq/dataverse/DatasetFieldServiceBean.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldServiceBean.java index 0b6b74e6a73..811c67c52d6 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DatasetFieldServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/DatasetFieldServiceBean.java @@ -764,13 +764,24 @@ Object processPathSegment(int index, String[] pathParts, JsonValue curPath, Stri JsonValue val = jo.get(keyVal[0]); if (val != null) { if (val.getValueType().equals(ValueType.STRING)) { + //Match a string value if (((JsonString) val).getString().equals(expected)) { logger.fine("Found: " + jo); curPath = jo; return processPathSegment(index + 1, pathParts, curPath, termUri); } - } else { - logger.warning("Expected a string value for " + keyVal[0] + " but found: " + val.getValueType()); + } else if (val.getValueType() == JsonValue.ValueType.ARRAY) { + // Match one string in an array + JsonArray jsonArray = (JsonArray) val; + for (JsonValue arrayVal : jsonArray) { + if (arrayVal.getValueType() == JsonValue.ValueType.STRING) { + if (((JsonString) arrayVal).getString().equals(expected)) { + logger.fine("Found match in array: " + jo.toString()); + curPath = jo; + return processPathSegment(index + 1, pathParts, curPath, termUri); + } + } + } } } } From fc68f5677646c0f6384595bea14e51ebc44680de Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Fri, 5 Sep 2025 13:55:24 -0400 Subject: [PATCH 2/3] release note --- doc/release-notes/11793 - ext. vocab. improvements.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/release-notes/11793 - ext. vocab. improvements.md diff --git a/doc/release-notes/11793 - ext. vocab. improvements.md b/doc/release-notes/11793 - ext. vocab. improvements.md new file mode 100644 index 00000000000..46998e56b60 --- /dev/null +++ b/doc/release-notes/11793 - ext. vocab. improvements.md @@ -0,0 +1 @@ +This version of Dataverse includes extensions of the Dataverse External Vocabulary mechanism (https://guides.dataverse.org/en/latest/admin/metadatacustomization.html#using-external-vocabulary-services) that improve Dataverse's ability to include metadata about vocabulary terms and external identifiers such as ORCID and ROR in it's metadata exports. More information on how to configure external vocabulary scripts to use this functionality can be found at https://github.com/gdcc/dataverse-external-vocab-support/blob/main/docs/readme.md and in the examples in the https://github.com/gdcc/dataverse-external-vocab-support repository. \ No newline at end of file From 81aa56b30a059a1302f5d814f3757c9d5f03742b Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Thu, 16 Oct 2025 18:42:27 -0400 Subject: [PATCH 3/3] test per review --- .../DatasetFieldServiceBeanTest.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/test/java/edu/harvard/iq/dataverse/DatasetFieldServiceBeanTest.java b/src/test/java/edu/harvard/iq/dataverse/DatasetFieldServiceBeanTest.java index 873d417131d..8e6fc76c134 100644 --- a/src/test/java/edu/harvard/iq/dataverse/DatasetFieldServiceBeanTest.java +++ b/src/test/java/edu/harvard/iq/dataverse/DatasetFieldServiceBeanTest.java @@ -1,6 +1,9 @@ package edu.harvard.iq.dataverse; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; @@ -17,7 +20,10 @@ import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import jakarta.json.Json; +import jakarta.json.JsonArray; +import jakarta.json.JsonArrayBuilder; import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; public class DatasetFieldServiceBeanTest { @@ -152,6 +158,57 @@ void getIndexableStringsByTermUriOrcid() throws IOException { assertEquals(Collections.emptySet(), result); } + @Test + public void testProcessPathSegmentWithArrayStringMatching() { + // Create a DatasetFieldServiceBean instance + DatasetFieldServiceBean bean = new DatasetFieldServiceBean(); + + String termUri = "http://example.org/term/123"; + + // Create a JSON structure with an array containing string values + JsonArrayBuilder tagsArrayBuilder = Json.createArrayBuilder(); + JsonObject testObject = Json.createObjectBuilder().add("tag", Json.createArrayBuilder().add("research").add("science")).add("name", "one").build(); + tagsArrayBuilder.add(testObject); + JsonObject testObject2 = Json.createObjectBuilder().add("tag", "art").add("name", "two").build(); + tagsArrayBuilder.add(testObject2); + JsonObject testObject3 = Json.createObjectBuilder().add("tag", termUri).add("name", "three").build(); + tagsArrayBuilder.add(testObject3); + JsonArray tags = tagsArrayBuilder.build(); + + // Test case 1: Match a string in an array of strings + String[] pathParts = { "tag=research", "name" }; + Object result = bean.processPathSegment(0, pathParts, tags, termUri); + + // The method should return the test object when a match is found + // Result should not be null when a match is found + assertNotNull(result); + assertEquals("one", result, "Result should be the original test object"); + + // Test case 2: Match a string + pathParts[0] = "tag=art"; + result = bean.processPathSegment(0, pathParts, tags, termUri); + + // The method should return the test object when a match is found + // Result should not be null when a match is found + assertNotNull(result); + assertEquals("two", result, "Result should be the original test object"); + + // Test case 3: No match in the array + String[] noMatchPathParts = { "tags=nonexistent" }; + Object noMatchResult = bean.processPathSegment(0, noMatchPathParts, testObject, termUri); + + // The method should return null when no match is found + assertNull(noMatchResult, "Result should be null when no match is found"); + + // Test case 4: Match with @id substitution + + String[] idPathParts = { "tag=@id", "name" }; + Object idResult = bean.processPathSegment(0, idPathParts, tags, termUri); + + assertNotNull(idResult, "Result should not be null when matching with @id"); + assertEquals("three", idResult, "Result should be the original test object"); + } + /** * Prepare unit tests with mock methods. *