1212import java .io .IOException ;
1313import java .util .*;
1414import java .util .function .Consumer ;
15+ import java .util .function .Function ;
1516
1617import edu .kit .datamanager .ro_crate .special .IdentifierUtils ;
1718import org .apache .http .client .methods .CloseableHttpResponse ;
@@ -38,14 +39,16 @@ public class RoCrateMetadataContext implements CrateMetadataContext {
3839 protected final HashMap <String , String > other = new HashMap <>();
3940
4041 /**
41- * Default constructor for the creation of the default context.
42+ * Default constructor for the creation of the v1.1 default context.
4243 */
4344 public RoCrateMetadataContext () {
4445 this .addToContextFromUrl (DEFAULT_CONTEXT );
4546 }
4647
4748 /**
4849 * Constructor for creating the context from a list of url.
50+ * <p>
51+ * Note: Does NOT contain the default context if not explicitly given!
4952 *
5053 * @param urls the url list with different context.
5154 */
@@ -55,6 +58,8 @@ public RoCrateMetadataContext(Collection<String> urls) {
5558
5659 /**
5760 * Constructor for creating the context from a json object.
61+ * <p>
62+ * Note: Does NOT contain the default context if not explicitly given!
5863 *
5964 * @param context the Json object of the context.
6065 */
@@ -83,6 +88,28 @@ public RoCrateMetadataContext(JsonNode context) {
8388 }
8489 }
8590
91+ /**
92+ * Converts the context into a JSON-LD representation.
93+ * <p>
94+ * The resulting JSON structure depends on the content:
95+ * - If there's only one URL and no key-value pairs: {"@context": "url"}
96+ * - If there are multiple URLs and/or key-value pairs: {"@context": ["url1", "url2", {"key1": "value1", "key2": "value2"}]}
97+ * <p>
98+ * Example output:
99+ * <pre>
100+ * {
101+ * "@context": [
102+ * "https://w3id.org/ro/crate/1.1/context",
103+ * {
104+ * "schema": "http://schema.org/",
105+ * "rdfs": "http://www.w3.org/2000/01/rdf-schema#"
106+ * }
107+ * ]
108+ * }
109+ * </pre>
110+ *
111+ * @return an ObjectNode containing the JSON-LD context representation
112+ */
86113 @ Override
87114 public ObjectNode getContextJsonEntity () {
88115 ObjectMapper objectMapper = MyObjectMapper .getMapper ();
@@ -106,6 +133,21 @@ public ObjectNode getContextJsonEntity() {
106133 return finalNode ;
107134 }
108135
136+ /**
137+ * Checks if the given entity is valid according to the context.
138+ * <p>
139+ * - full URLs in the @type and field names are considered valid without further checks.
140+ * - The "@id" value is treated as a special case, where it refers to the entity's ID.
141+ * - The "@json" type is a linked data built-in type and is always considered valid.
142+ * - If a type or field name is not found in the context, it will print an error message and return false.
143+ * - This method checks both the types in the @type array and the field names in the entity's properties.
144+ * - Prefixes in the context are considered valid if they match the context keys.
145+ * - Suffixes after a valid prefix are considered valid in any case. This is not perfect,
146+ * but it would be hard to handle correctly.
147+ *
148+ * @param entity the entity to check
149+ * @return true if the entity is valid, false otherwise
150+ */
109151 @ Override
110152 public boolean checkEntity (AbstractEntity entity ) {
111153 ObjectMapper objectMapper = MyObjectMapper .getMapper ();
@@ -117,6 +159,11 @@ public boolean checkEntity(AbstractEntity entity) {
117159 entity .getProperties ().path ("@type" ),
118160 new TypeReference <>() {}
119161 );
162+
163+ final Function <String , Boolean > isFail = checkMeStr -> this .contextMap .get (checkMeStr ) == null
164+ && this .contextMap .keySet ().stream ()
165+ .noneMatch (key -> checkMeStr .startsWith (key + ":" ));
166+
120167 // check if the items in the array of types are present in the context
121168 for (String s : types ) {
122169 // special cases:
@@ -134,7 +181,7 @@ public boolean checkEntity(AbstractEntity entity) {
134181 continue ;
135182 }
136183
137- if (this . contextMap . get (s ) == null ) {
184+ if (isFail . apply (s )) {
138185 System .err .println ("type " + s + " is missing from the context!" );
139186 return false ;
140187 }
@@ -147,14 +194,21 @@ public boolean checkEntity(AbstractEntity entity) {
147194 // full URLs are considered fine
148195 continue ;
149196 }
150- if (this . contextMap . get (s ) == null ) {
197+ if (isFail . apply (s )) {
151198 System .err .println ("attribute name " + s + " is missing from context;" );
152199 return false ;
153200 }
154201 }
155202 return true ;
156203 }
157204
205+ /**
206+ * Adds a URL to the context.
207+ * <p>
208+ * It will try to fetch the context from the URL.
209+ *
210+ * @param url the URL to add
211+ */
158212 @ Override
159213 public void addToContextFromUrl (String url ) {
160214 this .urls .add (url );
@@ -194,18 +248,31 @@ public void addToContextFromUrl(String url) {
194248 }));
195249 }
196250
251+ /**
252+ * Adds a key-value pair to the context.
253+ *
254+ * @param key the key to add. It may be a prefix or a term.
255+ * @param value the value to add
256+ */
197257 @ Override
198258 public void addToContext (String key , String value ) {
199259 this .contextMap .put (key , value );
200260 this .other .put (key , value );
201261 }
202262
263+ /**
264+ * @param key the key for the value to retrieve.
265+ * @return the value of the key if it exists in the context, null otherwise.
266+ */
203267 @ Override
204268 public String getValueOf (String key ) {
205269 return Optional .ofNullable (this .contextMap .get (key ))
206270 .orElseGet (() -> this .other .get (key ));
207271 }
208272
273+ /**
274+ * @return the set of all keys in the context.
275+ */
209276 @ Override
210277 public Set <String > getKeys () {
211278 List <String > merged = new ArrayList <>();
@@ -214,6 +281,11 @@ public Set<String> getKeys() {
214281 return Set .copyOf (merged );
215282 }
216283
284+ /**
285+ * @return a map of all key-value pairs in the context. Note that some pairs may come
286+ * from URLs or a pair may not be available as a context was not successfully resolved
287+ * from a URL.
288+ */
217289 @ Override
218290 public Map <String , String > getPairs () {
219291 Map <String , String > merged = new HashMap <>();
@@ -222,13 +294,18 @@ public Map<String, String> getPairs() {
222294 return Map .copyOf (merged );
223295 }
224296
225-
297+ /**
298+ * @param key the key to delete from the context.
299+ */
226300 @ Override
227301 public void deleteValuePairFromContext (String key ) {
228302 this .contextMap .remove (key );
229303 this .other .remove (key );
230304 }
231305
306+ /**
307+ * @param url the URL to delete from the context.
308+ */
232309 @ Override
233310 public void deleteUrlFromContext (String url ) {
234311 this .urls .remove (url );
0 commit comments