diff --git a/src/main/java/edu/kit/datamanager/ro_crate/Crate.java b/src/main/java/edu/kit/datamanager/ro_crate/Crate.java index d7fd8bd9..aff1b6fe 100644 --- a/src/main/java/edu/kit/datamanager/ro_crate/Crate.java +++ b/src/main/java/edu/kit/datamanager/ro_crate/Crate.java @@ -2,6 +2,7 @@ import java.io.File; import java.util.Collection; +import java.util.Map; import java.util.Optional; import java.util.Set; @@ -51,6 +52,25 @@ public interface Crate { void setMetadataContext(CrateMetadataContext metadataContext); + /** + * Get the value of a key from the metadata context. + * @param key the key to be searched + * @return the value of the key, null if not found + */ + String getMetadataContextValueOf(String key); + + /** + * Get an immutable collection of the keys in the metadata context. + * @return the keys in the metadata context + */ + Set getMetadataContextKeys(); + + /** + * Get an immutable map of the context. + * @return an immutable map containing the context key-value pairs + */ + Map getMetadataContextPairs(); + RootDataEntity getRootDataEntity(); void setRootDataEntity(RootDataEntity rootDataEntity); diff --git a/src/main/java/edu/kit/datamanager/ro_crate/RoCrate.java b/src/main/java/edu/kit/datamanager/ro_crate/RoCrate.java index 2e6db32b..c3f68a0f 100644 --- a/src/main/java/edu/kit/datamanager/ro_crate/RoCrate.java +++ b/src/main/java/edu/kit/datamanager/ro_crate/RoCrate.java @@ -62,6 +62,20 @@ public void setMetadataContext(CrateMetadataContext metadataContext) { this.metadataContext = metadataContext; } + public String getMetadataContextValueOf(String key) { + return this.metadataContext.getValueOf(key); + } + + @Override + public Set getMetadataContextKeys() { + return this.metadataContext.getKeys(); + } + + @Override + public Map getMetadataContextPairs() { + return this.metadataContext.getPairs(); + } + public ContextualEntity getJsonDescriptor() { return jsonDescriptor; } diff --git a/src/main/java/edu/kit/datamanager/ro_crate/context/CrateMetadataContext.java b/src/main/java/edu/kit/datamanager/ro_crate/context/CrateMetadataContext.java index ba203338..dfe6548e 100644 --- a/src/main/java/edu/kit/datamanager/ro_crate/context/CrateMetadataContext.java +++ b/src/main/java/edu/kit/datamanager/ro_crate/context/CrateMetadataContext.java @@ -4,6 +4,9 @@ import edu.kit.datamanager.ro_crate.entities.AbstractEntity; +import java.util.Map; +import java.util.Set; + /** * Interface for the metadata context. * Most often in an ROCrate this is the default context, @@ -22,6 +25,25 @@ public interface CrateMetadataContext { void addToContext(String key, String value); + /** + * Get the value of a key from the context. + * @param key the key to be searched + * @return the value of the key, null if not found + */ + String getValueOf(String key); + + /** + * Get an immutable collection of the keys in the metadata context. + * @return the keys in the metadata context + */ + Set getKeys(); + + /** + * Get an immutable map of the context. + * @return an immutable map containing the context key-value pairs + */ + Map getPairs(); + void deleteValuePairFromContext(String key); void deleteUrlFromContext(String url); diff --git a/src/main/java/edu/kit/datamanager/ro_crate/context/RoCrateMetadataContext.java b/src/main/java/edu/kit/datamanager/ro_crate/context/RoCrateMetadataContext.java index f4c2dfc4..731a4c1a 100644 --- a/src/main/java/edu/kit/datamanager/ro_crate/context/RoCrateMetadataContext.java +++ b/src/main/java/edu/kit/datamanager/ro_crate/context/RoCrateMetadataContext.java @@ -31,7 +31,7 @@ public class RoCrateMetadataContext implements CrateMetadataContext { protected static final String DEFAULT_CONTEXT_LOCATION = "default_context/version1.1.json"; protected static JsonNode defaultContext = null; - protected final Set url = new HashSet<>(); + protected final Set urls = new HashSet<>(); protected final HashMap contextMap = new HashMap<>(); // we need to keep the ones that are no coming from url // for the final representation @@ -89,7 +89,7 @@ public ObjectNode getContextJsonEntity() { ArrayNode array = objectMapper.createArrayNode(); ObjectNode jsonNode = objectMapper.createObjectNode(); ObjectNode finalNode = objectMapper.createObjectNode(); - for (String e : url) { + for (String e : urls) { array.add(e); } for (Map.Entry s : other.entrySet()) { @@ -156,7 +156,7 @@ public boolean checkEntity(AbstractEntity entity) { @Override public void addToContextFromUrl(String url) { - this.url.add(url); + this.urls.add(url); ObjectMapper objectMapper = MyObjectMapper.getMapper(); @@ -200,6 +200,29 @@ public void addToContext(String key, String value) { this.other.put(key, value); } + @Override + public String getValueOf(String key) { + return Optional.ofNullable(this.contextMap.get(key)) + .orElseGet(() -> this.other.get(key)); + } + + @Override + public Set getKeys() { + List merged = new ArrayList<>(); + merged.addAll(this.contextMap.keySet()); + merged.addAll(this.other.keySet()); + return Set.copyOf(merged); + } + + @Override + public Map getPairs() { + Map merged = new HashMap<>(); + merged.putAll(this.contextMap); + merged.putAll(this.other); + return Map.copyOf(merged); + } + + @Override public void deleteValuePairFromContext(String key) { this.contextMap.remove(key); @@ -208,7 +231,7 @@ public void deleteValuePairFromContext(String key) { @Override public void deleteUrlFromContext(String url) { - this.url.remove(url); + this.urls.remove(url); } } diff --git a/src/test/java/edu/kit/datamanager/ro_crate/context/ContextTest.java b/src/test/java/edu/kit/datamanager/ro_crate/context/ContextTest.java index f00e9d33..4995f272 100644 --- a/src/test/java/edu/kit/datamanager/ro_crate/context/ContextTest.java +++ b/src/test/java/edu/kit/datamanager/ro_crate/context/ContextTest.java @@ -1,6 +1,6 @@ package edu.kit.datamanager.ro_crate.context; -import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -14,18 +14,26 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.io.IOException; import java.util.List; +import java.util.Set; import static org.junit.jupiter.api.Assertions.*; public class ContextTest { RoCrateMetadataContext context; + RoCrateMetadataContext complexContext; @BeforeEach - void initContext() { + void initContext() throws IOException { // this will load the default context this.context = new RoCrateMetadataContext(); + + final String crateManifestPath = "/crates/extendedContextExample/ro-crate-metadata.json"; + ObjectMapper objectMapper = MyObjectMapper.getMapper(); + JsonNode jsonNode = objectMapper.readTree(ContextTest.class.getResourceAsStream(crateManifestPath)); + this.complexContext = new RoCrateMetadataContext(jsonNode.get("@context")); } @Test @@ -137,12 +145,12 @@ void deleteUrlTest() { } @Test - void doubledContextUrlsTest() throws JsonProcessingException { + void doubledContextUrlsTest() { String url = "www.example.com"; RoCrateMetadataContext context = new RoCrateMetadataContext(); - assertFalse(context.url.contains(url)); + assertFalse(context.urls.contains(url)); context.addToContextFromUrl(url); - assertTrue(context.url.contains(url)); + assertTrue(context.urls.contains(url)); RoCrateMetadataContext contextDoubled = new RoCrateMetadataContext(); contextDoubled.addToContextFromUrl(url); @@ -224,4 +232,50 @@ void testAbsoluteUrlType() { .build(); assertTrue(this.context.checkEntity(validEntity)); } + + @Test + void testSetDeleteGetPair() { + String key = "key"; + String value = "value"; + context.addToContext(key, value); + assertEquals(value, context.getValueOf(key)); + context.deleteValuePairFromContext(key); + assertNull(context.getValueOf(key)); + } + + @Test + void testReadDeleteGetPair() { + String key = "custom"; + String value = "_:"; + assertEquals(value, this.complexContext.getValueOf(key)); + this.complexContext.deleteValuePairFromContext(key); + assertNull(this.complexContext.getValueOf(key)); + this.complexContext.addToContext(key, value); + assertEquals(value, this.complexContext.getValueOf(key)); + } + + @Test + void testReadKeys() { + var expected = Set.of("custom", "owl", "datacite", "xsd", "rdfs"); + var given = this.complexContext.getKeys(); + for (String key : expected) { + assertTrue(given.contains(key), "Key " + key + " not found in the context"); + } + // prove immutability + assertThrows(UnsupportedOperationException.class, () -> given.add("newKey")); + } + + @Test + void testReadPairs() { + var expected = Set.of("custom", "owl", "datacite", "xsd", "rdfs"); + var given = this.complexContext.getPairs(); + var keys = given.keySet(); + var values = given.values(); + for (String key : expected) { + assertTrue(keys.contains(key), "Key " + key + " not found in the context"); + values.forEach(s -> assertFalse(s.isEmpty(), "Value for key " + key + " is empty")); + } + // prove immutability + assertThrows(UnsupportedOperationException.class, () -> given.put("newKey", "newValue")); + } } diff --git a/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java b/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java index f51d0351..8f008510 100644 --- a/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java +++ b/src/test/java/edu/kit/datamanager/ro_crate/crate/TestRemoveAddContext.java @@ -1,13 +1,29 @@ package edu.kit.datamanager.ro_crate.crate; -import org.junit.jupiter.api.Test; +import edu.kit.datamanager.ro_crate.reader.FolderReader; +import edu.kit.datamanager.ro_crate.reader.RoCrateReader; +import edu.kit.datamanager.ro_crate.HelpFunctions; +import edu.kit.datamanager.ro_crate.RoCrate; import com.fasterxml.jackson.core.JsonProcessingException; -import edu.kit.datamanager.ro_crate.HelpFunctions; -import edu.kit.datamanager.ro_crate.RoCrate; +import java.util.Objects; +import java.util.Set; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; public class TestRemoveAddContext { + private RoCrate crateWithComplexContext; + + @BeforeEach + void setup() { + String crateManifestPath = "/crates/extendedContextExample/"; + crateManifestPath = Objects.requireNonNull(TestRemoveAddContext.class.getResource(crateManifestPath)).getPath(); + this.crateWithComplexContext = new RoCrateReader(new FolderReader()).readCrate(crateManifestPath); + } + @Test void testAddRemoveValuePair() throws JsonProcessingException { RoCrate crate = new RoCrate.RoCrateBuilder().addValuePairToContext("key", "value").build(); @@ -30,4 +46,37 @@ void testAddRemoveUrl() throws JsonProcessingException { } + @Test + void testReadDeleteGetContextPair() { + String key = "custom"; + String value = "_:"; + assertEquals(value, this.crateWithComplexContext.getMetadataContextValueOf(key)); + this.crateWithComplexContext.deleteValuePairFromContext(key); + assertNull(this.crateWithComplexContext.getMetadataContextValueOf(key)); + } + + @Test + void testReadContextKeys() { + var expected = Set.of("custom", "owl", "datacite", "xsd", "rdfs"); + var given = this.crateWithComplexContext.getMetadataContextKeys(); + for (String key : expected) { + assertTrue(given.contains(key), "Key " + key + " not found in the context"); + } + // prove immutability + assertThrows(UnsupportedOperationException.class, () -> given.add("newKey")); + } + + @Test + void testReadContextPairs() { + var expected = Set.of("custom", "owl", "datacite", "xsd", "rdfs"); + var given = this.crateWithComplexContext.getMetadataContextPairs(); + var keys = given.keySet(); + var values = given.values(); + for (String key : expected) { + assertTrue(keys.contains(key), "Key " + key + " not found in the context"); + values.forEach(s -> assertFalse(s.isEmpty(), "Value for key " + key + " is empty")); + } + // prove immutability + assertThrows(UnsupportedOperationException.class, () -> given.put("newKey", "newValue")); + } } diff --git a/src/test/resources/crates/extendedContextExample/ro-crate-metadata.json b/src/test/resources/crates/extendedContextExample/ro-crate-metadata.json new file mode 100644 index 00000000..c9648594 --- /dev/null +++ b/src/test/resources/crates/extendedContextExample/ro-crate-metadata.json @@ -0,0 +1,28 @@ +{ + "@context": [ + "https://w3id.org/ro/crate/1.1/context", + { + "owl": "https://www.w3.org/TR/owl-ref/#", + "datacite": "http://datacite.org/schema/kernel-4#", + "xsd": "http://www.w3.org/2001/XMLSchema#", + "rdfs": "https://www.w3.org/2000/01/rdf-schema#", + "custom": "_:" + } + ], + "@graph": [ + { + "@id": "./", + "@type": "Dataset", + "name" : "minimal", + "description" : "minimal RO_crate", + "datePublished": "2024", + "license": {"@id": "https://creativecommons.org/licenses/by-nc-sa/3.0/au/"} + }, + { + "@type": "CreativeWork", + "@id": "ro-crate-metadata.json", + "conformsTo": {"@id": "https://w3id.org/ro/crate/1.1"}, + "about": {"@id": "./"} + } + ] +} \ No newline at end of file