12
12
import java .io .IOException ;
13
13
import java .util .*;
14
14
import java .util .function .Consumer ;
15
+ import java .util .function .Function ;
15
16
16
17
import edu .kit .datamanager .ro_crate .special .IdentifierUtils ;
17
18
import org .apache .http .client .methods .CloseableHttpResponse ;
@@ -38,14 +39,16 @@ public class RoCrateMetadataContext implements CrateMetadataContext {
38
39
protected final HashMap <String , String > other = new HashMap <>();
39
40
40
41
/**
41
- * Default constructor for the creation of the default context.
42
+ * Default constructor for the creation of the v1.1 default context.
42
43
*/
43
44
public RoCrateMetadataContext () {
44
45
this .addToContextFromUrl (DEFAULT_CONTEXT );
45
46
}
46
47
47
48
/**
48
49
* Constructor for creating the context from a list of url.
50
+ * <p>
51
+ * Note: Does NOT contain the default context if not explicitly given!
49
52
*
50
53
* @param urls the url list with different context.
51
54
*/
@@ -55,6 +58,8 @@ public RoCrateMetadataContext(Collection<String> urls) {
55
58
56
59
/**
57
60
* Constructor for creating the context from a json object.
61
+ * <p>
62
+ * Note: Does NOT contain the default context if not explicitly given!
58
63
*
59
64
* @param context the Json object of the context.
60
65
*/
@@ -83,6 +88,28 @@ public RoCrateMetadataContext(JsonNode context) {
83
88
}
84
89
}
85
90
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
+ */
86
113
@ Override
87
114
public ObjectNode getContextJsonEntity () {
88
115
ObjectMapper objectMapper = MyObjectMapper .getMapper ();
@@ -106,6 +133,21 @@ public ObjectNode getContextJsonEntity() {
106
133
return finalNode ;
107
134
}
108
135
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
+ */
109
151
@ Override
110
152
public boolean checkEntity (AbstractEntity entity ) {
111
153
ObjectMapper objectMapper = MyObjectMapper .getMapper ();
@@ -117,6 +159,11 @@ public boolean checkEntity(AbstractEntity entity) {
117
159
entity .getProperties ().path ("@type" ),
118
160
new TypeReference <>() {}
119
161
);
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
+
120
167
// check if the items in the array of types are present in the context
121
168
for (String s : types ) {
122
169
// special cases:
@@ -134,7 +181,7 @@ public boolean checkEntity(AbstractEntity entity) {
134
181
continue ;
135
182
}
136
183
137
- if (this . contextMap . get (s ) == null ) {
184
+ if (isFail . apply (s )) {
138
185
System .err .println ("type " + s + " is missing from the context!" );
139
186
return false ;
140
187
}
@@ -147,14 +194,21 @@ public boolean checkEntity(AbstractEntity entity) {
147
194
// full URLs are considered fine
148
195
continue ;
149
196
}
150
- if (this . contextMap . get (s ) == null ) {
197
+ if (isFail . apply (s )) {
151
198
System .err .println ("attribute name " + s + " is missing from context;" );
152
199
return false ;
153
200
}
154
201
}
155
202
return true ;
156
203
}
157
204
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
+ */
158
212
@ Override
159
213
public void addToContextFromUrl (String url ) {
160
214
this .urls .add (url );
@@ -194,18 +248,31 @@ public void addToContextFromUrl(String url) {
194
248
}));
195
249
}
196
250
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
+ */
197
257
@ Override
198
258
public void addToContext (String key , String value ) {
199
259
this .contextMap .put (key , value );
200
260
this .other .put (key , value );
201
261
}
202
262
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
+ */
203
267
@ Override
204
268
public String getValueOf (String key ) {
205
269
return Optional .ofNullable (this .contextMap .get (key ))
206
270
.orElseGet (() -> this .other .get (key ));
207
271
}
208
272
273
+ /**
274
+ * @return the set of all keys in the context.
275
+ */
209
276
@ Override
210
277
public Set <String > getKeys () {
211
278
List <String > merged = new ArrayList <>();
@@ -214,6 +281,11 @@ public Set<String> getKeys() {
214
281
return Set .copyOf (merged );
215
282
}
216
283
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
+ */
217
289
@ Override
218
290
public Map <String , String > getPairs () {
219
291
Map <String , String > merged = new HashMap <>();
@@ -222,13 +294,18 @@ public Map<String, String> getPairs() {
222
294
return Map .copyOf (merged );
223
295
}
224
296
225
-
297
+ /**
298
+ * @param key the key to delete from the context.
299
+ */
226
300
@ Override
227
301
public void deleteValuePairFromContext (String key ) {
228
302
this .contextMap .remove (key );
229
303
this .other .remove (key );
230
304
}
231
305
306
+ /**
307
+ * @param url the URL to delete from the context.
308
+ */
232
309
@ Override
233
310
public void deleteUrlFromContext (String url ) {
234
311
this .urls .remove (url );
0 commit comments