ontoripple 0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
ontoripple/evol_kg.py ADDED
@@ -0,0 +1,1956 @@
1
+ from rdflib import URIRef, Variable
2
+ from .constants import *
3
+ import os
4
+
5
+
6
+ # ---------------------------------------------------------------------------------------------------------------------------
7
+
8
+ def add_class_rml(change, change_data, output_mappings):
9
+ """
10
+ Adds a class defined in the change KG into the output_mappings.
11
+ If there is a TriplesMap that creates instances of that class, the TriplesMap is not created
12
+ Args:
13
+ change: the URI of the change which needs to be of the type AddClass
14
+ Returns:
15
+ the output_mappings updated with a new class
16
+ """
17
+ select_change = f' SELECT DISTINCT ?class WHERE {{' \
18
+ f' <{change}> {OCH_ADDED_CLASS} ?class .}} '
19
+
20
+ results = change_data.query(select_change)
21
+ added_class = results.bindings[0][Variable('class')]
22
+ check_query = f'ASK {{ ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP} .' \
23
+ f' ?triples_map {R2RML_SUBJECT} ?subject . ' \
24
+ f' ?subject {R2RML_CLASS} {added_class} }}'
25
+ #print(check_query)
26
+ check_res = output_mappings.query(check_query)
27
+ if not check_res.askAnswer:
28
+ if added_class.startswith('http://') or added_class.startswith('https://'):
29
+ triples_map_id = f'{added_class.split("#")[1]}_TM'
30
+ else:
31
+ triples_map_id = added_class+"_TM"
32
+ insert_class_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
33
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
34
+ f' INSERT DATA {{' \
35
+ f' <{EXAMPLE_URI}{triples_map_id}> {RDF_TYPE} {R2RML_TRIPLES_MAP}; ' \
36
+ f' {RML_LOGICAL_SOURCE} [ ' \
37
+ f' {RML_SOURCE} "XXX"; ' \
38
+ f' {RML_REFERENCE_FORMULATION} "XXX" ' \
39
+ f' ]; ' \
40
+ f' {R2RML_SUBJECT} [ ' \
41
+ f' {R2RML_TEMPLATE} "XXX"; ' \
42
+ f' {R2RML_CLASS} <{added_class}> ' \
43
+ f' ]. }} '
44
+ output_mappings.update(insert_class_query)
45
+ else:
46
+ print(f'The input mappings already has rules to create instances of {added_class}.')
47
+
48
+
49
+ # ---------------------------------------------------------------------------------------------------------------------------
50
+ def remove_class_rml(change,change_data, output_mappings, review_mappings, ontology):
51
+ """
52
+ Remove a class defined in the change KG into the output_mappings.
53
+ If there is a TriplesMap that creates instances of that class, the TriplesMap and associated POM are removed.
54
+ Referenced TriplesMaps POMs are also removed.
55
+ When the removed class is the sbclass of another class then the deleted PredicateObjectMaps are inserted into a different
56
+ document so that the KGE can review it, and move those to the parent class.
57
+ Args:
58
+ change: the URI of the change which needs to be of the type AddClass
59
+ Returns:
60
+ the output_mappings updated with the data
61
+ """
62
+ query = f' SELECT DISTINCT ?class_name WHERE {{ ' \
63
+ f' <{change}> {OCH_DELETED_CLASS} ?class_name . }}'
64
+
65
+ for result in change_data.query(query):
66
+ class_name = result["class_name"]
67
+ query = f' ASK {{<{class_name}> {RDFS_SUBCLASS} ?parent}} '
68
+ for result in ontology.query(query):
69
+ if result is True:
70
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
71
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
72
+ f' CONSTRUCT {{' \
73
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
74
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
75
+ f' ?subject ?subject_term ?subject_value .' \
76
+ f' ?subject {R2RML_CLASS} <{class_name}> .' \
77
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
78
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
79
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
80
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . ' \
81
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
82
+ f' ?predicate_bn ?predicate_term ?predicate_value . ' \
83
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object. ' \
84
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
85
+ f' ?object_bn ?object_term ?object_value.' \
86
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
87
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
88
+ f' ?join_condition ?condition_term ?condition_value . ' \
89
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom . ' \
90
+ f' ?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .' \
91
+ f' ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn .' \
92
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value .' \
93
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object . ' \
94
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map . ' \
95
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
96
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .}} ' \
97
+ f' WHERE {{ ' \
98
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
99
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
100
+ f' ?subject ?subject_term ?subject_value .' \
101
+ f' ?subject {R2RML_CLASS} <{class_name}> .' \
102
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
103
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
104
+ f' OPTIONAL {{ ' \
105
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
106
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . }}' \
107
+ f' OPTIONAL {{ ?pom {R2RML_PREDICATE} ?predicate_bn.'\
108
+ f' ?predicate_bn ?predicate_term ?predicate_value . }}' \
109
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
110
+ f' OPTIONAL {{?pom {R2RML_OBJECT} ?object_bn .' \
111
+ f' ?object_bn ?object_term ?object_value. }}' \
112
+ f' OPTIONAL {{' \
113
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
114
+ f' OPTIONAL {{ ' \
115
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
116
+ f' ?join_condition ?condition_term ?condition_value .' \
117
+ f' }}' \
118
+ f' }}' \
119
+ f' }}' \
120
+ f' OPTIONAL {{ ' \
121
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
122
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .}}' \
123
+ f' OPTIONAL {{ ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn.'\
124
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
125
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object .' \
126
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map .' \
127
+ f' OPTIONAL {{ ' \
128
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
129
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .' \
130
+ f' }}' \
131
+ f' }} ' \
132
+ f' }}'
133
+ hola=output_mappings.query(query)
134
+ for row in hola:
135
+ review_mappings.add(row)
136
+
137
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
138
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
139
+ f' DELETE {{' \
140
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
141
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
142
+ f' ?subject ?subject_term ?subject_value .' \
143
+ f' ?subject {R2RML_CLASS} <{class_name}> .' \
144
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
145
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
146
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
147
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . ' \
148
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
149
+ f' ?predicate_bn ?predicate_term ?predicate_value . ' \
150
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object. ' \
151
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
152
+ f' ?object_bn ?object_term ?object_value.' \
153
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
154
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
155
+ f' ?join_condition ?condition_term ?condition_value . ' \
156
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom . ' \
157
+ f' ?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .' \
158
+ f' ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn .' \
159
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value .' \
160
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object . ' \
161
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map . ' \
162
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
163
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .}} ' \
164
+ f' WHERE {{ ' \
165
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
166
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
167
+ f' ?subject ?subject_term ?subject_value .' \
168
+ f' ?subject {R2RML_CLASS} <{class_name}> .' \
169
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
170
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
171
+ f' OPTIONAL {{ ' \
172
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
173
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . }}' \
174
+ f' OPTIONAL {{ ?pom {R2RML_PREDICATE} ?predicate_bn.'\
175
+ f' ?predicate_bn ?predicate_term ?predicate_value . }}' \
176
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
177
+ f' OPTIONAL {{?pom {R2RML_OBJECT} ?object_bn .' \
178
+ f' ?object_bn ?object_term ?object_value. }}' \
179
+ f' OPTIONAL {{' \
180
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
181
+ f' OPTIONAL {{ ' \
182
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
183
+ f' ?join_condition ?condition_term ?condition_value .' \
184
+ f' }}' \
185
+ f' }}' \
186
+ f' }}' \
187
+ f' OPTIONAL {{ ' \
188
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
189
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .}}' \
190
+ f' OPTIONAL {{ ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn.'\
191
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
192
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object .' \
193
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map .' \
194
+ f' OPTIONAL {{ ' \
195
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
196
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .' \
197
+ f' }}' \
198
+ f' }} ' \
199
+ f' }}'
200
+ output_mappings.update(query)
201
+
202
+ # ---------------------------------------------------------------------------------------------------------------------------------
203
+
204
+ def add_super_class_rml(change,change_data, output_mappings):
205
+ """
206
+ Adds a superclass and its properties into the TriplesMap that instantiate the subclass .
207
+ Args:
208
+ change: the URI of the change which needs to be of the type add_sub_class
209
+ Returns:
210
+ the output_mappings updated with the TriplesMap of child adding the parent class and its properties
211
+ """
212
+ super_class = None
213
+ sub_class = None
214
+ query = f' SELECT DISTINCT ?super_class ?sub_class WHERE {{ ' \
215
+ f' <{change}> {OCH_ADD_SUBCLASS_SOURCE} ?sub_class. ' \
216
+ f' <{change}> {OCH_ADD_SUBCLASS_TARGET} ?super_class. }}'
217
+
218
+ for result in change_data.query(query):
219
+ sub_class = result["sub_class"]
220
+ super_class = result["super_class"]
221
+ insert_super_class_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
222
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
223
+ f' INSERT {{ ?subjectMap {R2RML_CLASS} <{super_class}>. }}' \
224
+ f' WHERE {{' \
225
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap. ' \
226
+ f' ?subjectMap {R2RML_CLASS} <{sub_class}>. }}'
227
+ #print(insert_super_class_query)
228
+ output_mappings.update(insert_super_class_query)
229
+
230
+ # Query that takes the Predicate Object Maps from the parent class triples map and inserts them into the child triples map.
231
+ """"
232
+ insert_super_class_pom_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
233
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
234
+ f' INSERT {{' \
235
+ f' ?subclass_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
236
+ f' ?pom ?predicate_property ?predicate . ' \
237
+ f' ?predicate ?predicate_term ?predicate_value . ' \
238
+ f' ?pom ?object_property ?object. ' \
239
+ f' ?object ?object_term ?object_value.' \
240
+ f' ?object {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
241
+ f' ?object {R2RML_JOIN_CONDITION} ?join_condition . ' \
242
+ f' ?join_condition ?condition_term ?condition_value . ' \
243
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom . ' \
244
+ f' ?parent_pom ?parent_predicate_property ?parent_predicate .' \
245
+ f' ?parent_predicate ?parent_predicate_term ?parent_predicate_value .' \
246
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object . ' \
247
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map . ' \
248
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions.'\
249
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .}} '\
250
+ f' WHERE {{ ' \
251
+ f' ?subclass_triples_map {R2RML_SUBJECT} ?subclass_subject.' \
252
+ f' ?subclass_subject {R2RML_CLASS} <{sub_class}>.' \
253
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
254
+ f' ?subject {R2RML_CLASS} <{super_class}> .' \
255
+ f' OPTIONAL {{ ' \
256
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
257
+ f' ?pom {R2RML_SHORTCUT_PREDICATE}|{R2RML_PREDICATE} ?predicate .' \
258
+ f' OPTIONAL {{ ?predicate ?predicate_term ?predicate_value . }}' \
259
+ f' ?pom {R2RML_SHORTCUT_OBJECT}|{R2RML_OBJECT} ?object .' \
260
+ f' OPTIONAL {{ ?object ?object_term ?object_value. }}' \
261
+ f' OPTIONAL {{' \
262
+ f' ?object {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
263
+ f' OPTIONAL {{ ' \
264
+ f' ?object {R2RML_JOIN_CONDITION} ?join_condition . ' \
265
+ f' ?join_condition ?condition_term ?condition_value .' \
266
+ f' }}' \
267
+ f' }}' \
268
+ f' }} ' \
269
+ f' OPTIONAL {{ ' \
270
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
271
+ f' ?parent_pom {R2RML_SHORTCUT_PREDICATE}|{R2RML_PREDICATE} ?parent_predicate .' \
272
+ f' OPTIONAL {{ ?parent_predicate ?parent_predicate_term ?parent_predicate_value . }}' \
273
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object .' \
274
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map .' \
275
+ f' OPTIONAL {{ ' \
276
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
277
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .' \
278
+ f' }}' \
279
+ f' }} ' \
280
+ f' }}'
281
+ print(insert_super_class_pom_query)
282
+ output_mappings.update(insert_super_class_pom_query)
283
+ """
284
+
285
+ # --------------------------------------------------------------------------------------------------------------
286
+ def remove_super_class_rml(change,change_data, output_mappings):
287
+ """
288
+ Removes superclass and its properties from the TriplesMap that instantiate the subclass .
289
+ Args:
290
+ change: the URI of the change which needs to be of the type remove_sub_class
291
+ Returns:
292
+ the output_mappings updated with the TriplesMap of child removing the parent class and its properties
293
+ """
294
+ # When removing the subclass relationship between two classes the child one loses the parent in the rr:class part.
295
+ query = f'SELECT DISTINCT ?super_class ?sub_class WHERE {{ ' \
296
+ f' <{change}> {OCH_REMOVE_SUBCLASS_SOURCE} ?sub_class.' \
297
+ f' <{change}> {OCH_REMOVE_SUBCLASS_TARGET} ?super_class. }}'
298
+
299
+ for result in change_data.query(query):
300
+ super_class = result["super_class"]
301
+ sub_class = result["sub_class"]
302
+ delete_super_class_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
303
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
304
+ f' DELETE {{ ?subjectMap {R2RML_CLASS} <{super_class}> }}' \
305
+ f' WHERE {{' \
306
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap . ' \
307
+ f' ?subjectMap {R2RML_CLASS} <{super_class}>, <{sub_class}> .}}'
308
+ #print(delete_super_class_query)
309
+ output_mappings.update(delete_super_class_query)
310
+
311
+ #Query that takes the Predicate Object Maps from the parent class triples map and inserts them into the child triples map.
312
+ """
313
+ remove_super_class_pom_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
314
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
315
+ f' DELETE {{' \
316
+ f' ?subclass_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
317
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate . ' \
318
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
319
+ f' ?predicate_bn ?parent_predicate_term ?parent_predicate_value . ' \
320
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?parent_object. ' \
321
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
322
+ f' ?object_bn ?parent_object_term ?parent_object_value.' \
323
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
324
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
325
+ f' ?join_condition ?parent_condition_term ?parent_condition_value . }} ' \
326
+ f' WHERE {{ ' \
327
+ f' ?subclass_triples_map {R2RML_SUBJECT} ?subclass_subject.' \
328
+ f' ?subclass_subject {R2RML_CLASS} <{sub_class}>.' \
329
+ f' ?parent_triples_map {R2RML_SUBJECT} ?parent_subject.' \
330
+ f' ?parent_subject {R2RML_CLASS} <{super_class}> .' \
331
+ f' OPTIONAL {{ ' \
332
+ f' ?subclass_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
333
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate }}' \
334
+ f' OPTIONAL {{ '\
335
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
336
+ f' ?predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
337
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?parent_object }}' \
338
+ f' OPTIONAL {{ '\
339
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
340
+ f' ?object_bn ?parent_object_term ?parent_object_value. ' \
341
+ f' OPTIONAL {{' \
342
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
343
+ f' OPTIONAL {{ ' \
344
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
345
+ f' ?join_condition ?parent_condition_term ?parent_condition_value .' \
346
+ f' }}' \
347
+ f' }}' \
348
+ f' }} ' \
349
+ f' }} ' \
350
+ f' OPTIONAL {{ ' \
351
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
352
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate }}' \
353
+ f' OPTIONAL {{ '\
354
+ f' ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn . ' \
355
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
356
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_OBJECT} ?parent_object }}' \
357
+ f' OPTIONAL {{ '\
358
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object_bn . ' \
359
+ f' ?parent_object_bn ?parent_object_term ?parent_object_value. ' \
360
+ f' OPTIONAL {{' \
361
+ f' ?parent_object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
362
+ f' OPTIONAL {{ ' \
363
+ f' ?object_bn_bn {R2RML_JOIN_CONDITION} ?parent_join_condition . ' \
364
+ f' ?parent_join_condition ?parent_condition_term ?parent_condition_value .' \
365
+ f' }}' \
366
+ f' }}' \
367
+ f' }} ' \
368
+ f' }} ' \
369
+ f' }}'
370
+ print(remove_super_class_pom_query)
371
+ output_mappings.update(remove_super_class_pom_query)
372
+ """
373
+
374
+ def add_object_property_rml(change, change_data, output_mappings):
375
+ """
376
+ Adds an object property to the TriplesMap indicated in the domain. For a change in the predicate object map the domain, property and range additions are needed.
377
+ Args:
378
+ change: the URI of the change which needs to be of the type addObjectProperty
379
+ Returns:
380
+ the output_mappings updated with the added predicate object maps.
381
+ """
382
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
383
+ f' <{change}> {OCH_ADDED_OBJECT_PROPERTY} ?property .' \
384
+ f' ?domainchange {OCH_ADDED_DOMAIN_TO_PROPERTY} ?property.' \
385
+ f' ?domainchange {OCH_ADDED_DOMAIN} ?domain.' \
386
+ f' ?rangechange {OCH_ADDED_RANGE_TO_PROPERTY} ?property.' \
387
+ f' ?rangechange {OCH_ADDED_OBJECT_RANGE} ?range. }}'
388
+
389
+ for result in change_data.query(query):
390
+ property_domain = result["domain"]
391
+ property_predicate = result["property"]
392
+ property_range = result["range"]
393
+
394
+ insert_object_property_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
395
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
396
+ f' INSERT {{ ' \
397
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} [ ' \
398
+ f' {R2RML_SHORTCUT_PREDICATE} <{property_predicate}> ; ' \
399
+ f' {R2RML_OBJECT} [ ' \
400
+ f' {R2RML_PARENT_TRIPLESMAP} ?parent_triplesMap;' \
401
+ f' {R2RML_JOIN_CONDITION} [ ' \
402
+ f' {R2RML_CHILD} "XXX"; {R2RML_PARENT} "XXX" ' \
403
+ f' ] ] ]. }}' \
404
+ f' WHERE {{' \
405
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap . ' \
406
+ f' ?subjectMap {R2RML_CLASS} <{property_domain}> .' \
407
+ f' ?parent_triplesMap {R2RML_SUBJECT} ?parent_subjectMap . ' \
408
+ f' ?parent_subjectMap {R2RML_CLASS} <{property_range}> }}'
409
+ output_mappings.update(insert_object_property_query)
410
+
411
+
412
+ # --------------------------------------------------------------------------------------------------------------------------------------------------
413
+ def remove_object_property_rml(change, change_data, output_mappings):
414
+ """
415
+ Removes the object property indicated in the change as property from its domain. For a change in the predicate object map the domain, property and range additions are needed.
416
+ Args:
417
+ change: the URI of the change which needs to be of the type addObjectProperty
418
+ Returns:
419
+ the output_mappings updated with the reference predicate object mapping removed
420
+ """
421
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
422
+ f' <{change}> {OCH_REMOVED_OBJECT_PROPERTY} ?property .' \
423
+ f' ?domainchange {OCH_REMOVED_DOMAIN_TO_PROPERTY} ?property.' \
424
+ f' ?domainchange {OCH_REMOVED_DOMAIN} ?domain.' \
425
+ f' ?rangechange {OCH_REMOVED_RANGE_TO_PROPERTY} ?property.' \
426
+ f' ?rangechange {OCH_REMOVED_OBJECT_RANGE} ?range. }}'
427
+
428
+ #print(query)
429
+ for result in change_data.query(query):
430
+ property_domain = result["domain"]
431
+ property_predicate = result["property"]
432
+ property_range = result["range"]
433
+ remove_object_property_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
434
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
435
+ f' DELETE {{' \
436
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
437
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{property_predicate}> .' \
438
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
439
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap . ' \
440
+ f' ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions . ' \
441
+ f' ?joinConditions ?conditions ?condition_values }} ' \
442
+ f' WHERE {{' \
443
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap.' \
444
+ f' ?subjectMap {R2RML_CLASS} <{property_domain}> . ' \
445
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
446
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{property_predicate}> .' \
447
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
448
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap .' \
449
+ f' ?parent_triplesMap {R2RML_SUBJECT} ?parent_subjectMap . ' \
450
+ f' ?parent_subjectMap {R2RML_CLASS} <{property_range}> ' \
451
+ f' OPTIONAL {{ ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions .' \
452
+ f' ?joinConditions ?conditions ?condition_values }} . }}'
453
+ #print(remove_object_property_query)
454
+ output_mappings.update(remove_object_property_query)
455
+
456
+
457
+ # -------------------------------------------------------------------------------------------------------------------------
458
+ def add_data_property_rml(change,change_data, output_mappings):
459
+ """
460
+ Adds a data property to the TriplesMap indicated in the domain. For a change in the predicate object map the domain, property and range additions are needed.
461
+ Args:
462
+ change: the URI of the change which needs to be of the type addObjectProperty
463
+ Returns:
464
+ the output_mappings updated with the new predicate object map with empty reference
465
+ """
466
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
467
+ f' <{change}> {OCH_ADDED_DATA_PROPERTY} ?property .' \
468
+ f' ?domainchange {OCH_ADDED_DOMAIN_TO_PROPERTY} ?property.' \
469
+ f' ?domainchange {OCH_ADDED_DOMAIN} ?domain.' \
470
+ f' ?rangechange {OCH_ADDED_RANGE_TO_PROPERTY} ?property.' \
471
+ f' ?rangechange {OCH_ADDED_DATA_RANGE} ?range. }}'
472
+ #print(query)
473
+ for result in change_data.query(query):
474
+ property_domain = result["domain"]
475
+ property_predicate = result["property"]
476
+ property_range = result["range"]
477
+ insert_data_property_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
478
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
479
+ f' INSERT {{ ' \
480
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} [ ' \
481
+ f' {R2RML_SHORTCUT_PREDICATE} <{property_predicate}> ; ' \
482
+ f' {R2RML_OBJECT} [ ' \
483
+ f' {RML_REFERENCE} "XXX";' \
484
+ f' {R2RML_DATATYPE} <{property_range}>' \
485
+ f' ] ]. }}' \
486
+ f' WHERE {{' \
487
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap . ' \
488
+ f' ?subjectMap {R2RML_CLASS} <{property_domain}> . }} '
489
+ #print(insert_data_property_query)
490
+ output_mappings.update(insert_data_property_query)
491
+
492
+
493
+ # -----------------------------------------------------------------------------------------------------------------------------------
494
+ def remove_data_property_rml(change,change_data, output_mappings):
495
+ """
496
+ Removes the data property indicated in the change as property from its domain. For a change in the predicate object map the domain, property and range additions are needed.
497
+ Args:
498
+ change: the URI of the change which needs to be of the type addObjectProperty
499
+ Returns:
500
+ the output_mappings updated with the predicate object mapping removed
501
+ """
502
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
503
+ f' <{change}> {OCH_REMOVED_DATA_PROPERTY} ?property .' \
504
+ f' ?domainchange {OCH_REMOVED_DOMAIN_TO_PROPERTY} ?property.' \
505
+ f' ?domainchange {OCH_REMOVED_DOMAIN} ?domain.' \
506
+ f' ?rangechange {OCH_REMOVED_RANGE_TO_PROPERTY} ?property.' \
507
+ f' ?rangechange {OCH_REMOVED_DATA_RANGE} ?range. }}'
508
+ #print(query)
509
+ for result in change_data.query(query):
510
+ property_domain = result["domain"]
511
+ property_predicate = result["property"]
512
+ property_range = result["range"]
513
+
514
+ remove_data_property_query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
515
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
516
+ f' DELETE {{' \
517
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
518
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{property_predicate}> .' \
519
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object.' \
520
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
521
+ f' ?objectMap ?object_term ?objectValue .}}' \
522
+ f' WHERE {{' \
523
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap.' \
524
+ f' ?subjectMap {R2RML_CLASS} <{property_domain}> . ' \
525
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
526
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{property_predicate}> .' \
527
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
528
+ f' OPTIONAL {{ '\
529
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
530
+ f' ?objectMap ?object_term ?objectValue.' \
531
+ f' OPTIONAL {{ ?objectMap {R2RML_DATATYPE} <{property_range}>}} }} . }}'
532
+ #print(remove_data_property_query)
533
+ output_mappings.update(remove_data_property_query)
534
+
535
+
536
+
537
+ # -------------------------------------------------------------------------------------------------------------
538
+
539
+ def deprecate_entity_rml(change,change_data, output_mappings, deprecated_mappings,ontology):
540
+ """
541
+ Deprecates an entity in the knowledge graph by removing its triples map and its subject.
542
+ Args:
543
+ change: the URI of the change which needs to be of the type deprecate_entity
544
+ """
545
+ query = f' SELECT DISTINCT ?entity WHERE {{ ' \
546
+ f' <{change}> {OCH_DEPRECATED_ENTITY} ?entity. }}'
547
+ #print(query)
548
+ for result in change_data.query(query):
549
+ entity = result["entity"]
550
+ query = f' SELECT DISTINCT ?type WHERE {{ ' \
551
+ f' <{entity}> {RDF_TYPE} ?type. }}'
552
+ #print(query)
553
+ for result in ontology.query(query):
554
+ entity_type = result["type"]
555
+ #print(f'Entity type: {entity_type}')
556
+ if entity_type == URIRef(OWL_CLASS_URI):
557
+ # Remove the triples map for the class entity
558
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
559
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
560
+ f' CONSTRUCT {{' \
561
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
562
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
563
+ f' ?subject ?subject_term ?subject_value .' \
564
+ f' ?subject {R2RML_CLASS} <{entity}> .' \
565
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
566
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
567
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
568
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . ' \
569
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
570
+ f' ?predicate_bn ?predicate_term ?predicate_value . ' \
571
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object. ' \
572
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
573
+ f' ?object_bn ?object_term ?object_value.' \
574
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
575
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
576
+ f' ?join_condition ?condition_term ?condition_value . ' \
577
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom . ' \
578
+ f' ?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .' \
579
+ f' ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn .' \
580
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value .' \
581
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object . ' \
582
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?parent_triples_map . ' \
583
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
584
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .}} ' \
585
+ f' WHERE {{ ' \
586
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
587
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
588
+ f' ?subject ?subject_term ?subject_value .' \
589
+ f' ?subject {R2RML_CLASS} <{entity}> .' \
590
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
591
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
592
+ f' OPTIONAL {{ ' \
593
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
594
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . }}' \
595
+ f' OPTIONAL {{ ?pom {R2RML_PREDICATE} ?predicate_bn.'\
596
+ f' ?predicate_bn ?predicate_term ?predicate_value . }}' \
597
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
598
+ f' OPTIONAL {{?pom {R2RML_OBJECT} ?object_bn .' \
599
+ f' ?object_bn ?object_term ?object_value. }}' \
600
+ f' OPTIONAL {{' \
601
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
602
+ f' OPTIONAL {{ ' \
603
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
604
+ f' ?join_condition ?condition_term ?condition_value .' \
605
+ f' }}' \
606
+ f' }}' \
607
+ f' }}' \
608
+ f' OPTIONAL {{ ' \
609
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
610
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .}}' \
611
+ f' OPTIONAL {{ ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn.'\
612
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
613
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object .' \
614
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?parent_triples_map .' \
615
+ f' OPTIONAL {{ ' \
616
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
617
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .' \
618
+ f' }}' \
619
+ f' }} ' \
620
+ f' }}'
621
+ #print(query)
622
+ deprecated_triples=output_mappings.query(query)
623
+ for row in deprecated_triples:
624
+ deprecated_mappings.add(row)
625
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
626
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
627
+ f' DELETE {{' \
628
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
629
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
630
+ f' ?subject ?subject_term ?subject_value .' \
631
+ f' ?subject {R2RML_CLASS} <{entity}> .' \
632
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
633
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
634
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
635
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . ' \
636
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
637
+ f' ?predicate_bn ?predicate_term ?predicate_value . ' \
638
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object. ' \
639
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
640
+ f' ?object_bn ?object_term ?object_value.' \
641
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
642
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
643
+ f' ?join_condition ?condition_term ?condition_value . ' \
644
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom . ' \
645
+ f' ?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .' \
646
+ f' ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn .' \
647
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value .' \
648
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object . ' \
649
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map . ' \
650
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
651
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .}} ' \
652
+ f' WHERE {{ ' \
653
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
654
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
655
+ f' ?subject ?subject_term ?subject_value .' \
656
+ f' ?subject {R2RML_CLASS} <{entity}> .' \
657
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
658
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
659
+ f' OPTIONAL {{ ' \
660
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
661
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . }}' \
662
+ f' OPTIONAL {{ ?pom {R2RML_PREDICATE} ?predicate_bn.'\
663
+ f' ?predicate_bn ?predicate_term ?predicate_value . }}' \
664
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
665
+ f' OPTIONAL {{?pom {R2RML_OBJECT} ?object_bn .' \
666
+ f' ?object_bn ?object_term ?object_value. }}' \
667
+ f' OPTIONAL {{' \
668
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
669
+ f' OPTIONAL {{ ' \
670
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
671
+ f' ?join_condition ?condition_term ?condition_value .' \
672
+ f' }}' \
673
+ f' }}' \
674
+ f' }}' \
675
+ f' OPTIONAL {{ ' \
676
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
677
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .}}' \
678
+ f' OPTIONAL {{ ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn.'\
679
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
680
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object .' \
681
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map .' \
682
+ f' OPTIONAL {{ ' \
683
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
684
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .' \
685
+ f' }}' \
686
+ f' }} ' \
687
+ f' }}'
688
+ #print(query)
689
+ output_mappings.update(query)
690
+
691
+ elif entity_type == URIRef(OWL_OBJECT_PROPERTY_URI):
692
+ # Remove all predicate-object maps using this object property
693
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
694
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
695
+ f' CONSTRUCT {{' \
696
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
697
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
698
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
699
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap . ' \
700
+ f' ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions . ' \
701
+ f' ?joinConditions ?conditions ?condition_values }} ' \
702
+ f' WHERE {{' \
703
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap.' \
704
+ f' ?subjectMap {R2RML_CLASS} ?domain . ' \
705
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
706
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
707
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
708
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap .' \
709
+ f' ?parent_triplesMap {R2RML_SUBJECT} ?parent_subjectMap . ' \
710
+ f' ?parent_subjectMap {R2RML_CLASS} ?range. ' \
711
+ f' OPTIONAL {{ ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions .' \
712
+ f' ?joinConditions ?conditions ?condition_values }} . }}'
713
+ #print(query)
714
+ deprecated_triples=output_mappings.query(query)
715
+ for row in deprecated_triples:
716
+ deprecated_mappings.add(row)
717
+ query= f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
718
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
719
+ f' DELETE {{' \
720
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
721
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
722
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
723
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap . ' \
724
+ f' ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions . ' \
725
+ f' ?joinConditions ?conditions ?condition_values }} ' \
726
+ f' WHERE {{' \
727
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap.' \
728
+ f' ?subjectMap {R2RML_CLASS} ?domain . ' \
729
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
730
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
731
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
732
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap .' \
733
+ f' ?parent_triplesMap {R2RML_SUBJECT} ?parent_subjectMap . ' \
734
+ f' ?parent_subjectMap {R2RML_CLASS} ?range. ' \
735
+ f' OPTIONAL {{ ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions .' \
736
+ f' ?joinConditions ?conditions ?condition_values }} . }}'
737
+ #print(query)
738
+ output_mappings.update(query)
739
+
740
+ elif entity_type == URIRef(OWL_DATA_PROPERTY_URI):
741
+ # Remove all predicate-object maps using this data property
742
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
743
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
744
+ f' CONSTRUCT {{' \
745
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
746
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
747
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object.' \
748
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
749
+ f' ?objectMap ?object_term ?objectValue .}}' \
750
+ f' WHERE {{' \
751
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap.' \
752
+ f' ?subjectMap {R2RML_CLASS} ?domain . ' \
753
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
754
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
755
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
756
+ f' OPTIONAL {{ '\
757
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
758
+ f' ?objectMap ?object_term ?objectValue.' \
759
+ f' OPTIONAL {{ ?objectMap {R2RML_DATATYPE} ?range}} }} . }}'
760
+ deprecated_triples=output_mappings.query(query)
761
+ for row in deprecated_triples:
762
+ deprecated_mappings.add(row)
763
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
764
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
765
+ f' DELETE {{' \
766
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
767
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
768
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object.' \
769
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
770
+ f' ?objectMap ?object_term ?objectValue .}}' \
771
+ f' WHERE {{' \
772
+ f' ?triplesMap {R2RML_SUBJECT} ?subjectMap.' \
773
+ f' ?subjectMap {R2RML_CLASS} ?domain . ' \
774
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
775
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
776
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
777
+ f' OPTIONAL {{ '\
778
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
779
+ f' ?objectMap ?object_term ?objectValue.' \
780
+ f' OPTIONAL {{ ?objectMap {R2RML_DATATYPE} ?range}} }} . }}'
781
+ output_mappings.update(query)
782
+
783
+ def revoke_deprecate_entity_rml(change, change_data, output_mappings, deprecated_mappings, ontology):
784
+ """
785
+ Reverts the deprecation of an entity in the knowledge graph by restoring its triples map and its subject from deprecated_mappings.
786
+ Args:
787
+ change: the URI of the change which needs to be of the type revoke_deprecate_entity
788
+ """
789
+ query = f' SELECT DISTINCT ?entity WHERE {{ ' \
790
+ f' <{change}> {OCH_UNDEPRECATED_ELEMENT} ?entity. }}'
791
+ #print(query)
792
+ for result in change_data.query(query):
793
+ entity = result["entity"]
794
+ query = f' SELECT DISTINCT ?type WHERE {{ ' \
795
+ f' <{entity}> {RDF_TYPE} ?type. }}'
796
+ #print(query)
797
+ for result in ontology.query(query):
798
+ entity_type = result["type"]
799
+ #print(f'Entity type: {entity_type}')
800
+ if entity_type == URIRef(OWL_CLASS_URI):
801
+ # Restore the triples map for the class entity from deprecated_mappings to output_mappings
802
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
803
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
804
+ f' CONSTRUCT {{' \
805
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
806
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
807
+ f' ?subject ?subject_term ?subject_value .' \
808
+ f' ?subject {R2RML_CLASS} <{entity}> .' \
809
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
810
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
811
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom. ' \
812
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . ' \
813
+ f' ?pom {R2RML_PREDICATE} ?predicate_bn . ' \
814
+ f' ?predicate_bn ?predicate_term ?predicate_value . ' \
815
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object. ' \
816
+ f' ?pom {R2RML_OBJECT} ?object_bn . ' \
817
+ f' ?object_bn ?object_term ?object_value.' \
818
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm . ' \
819
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
820
+ f' ?join_condition ?condition_term ?condition_value . ' \
821
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom . ' \
822
+ f' ?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .' \
823
+ f' ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn .' \
824
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value .' \
825
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object . ' \
826
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map . ' \
827
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
828
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .}} ' \
829
+ f' WHERE {{ ' \
830
+ f' ?triples_map {RDF_TYPE} {R2RML_TRIPLES_MAP}.' \
831
+ f' ?triples_map {R2RML_SUBJECT} ?subject.' \
832
+ f' ?subject ?subject_term ?subject_value .' \
833
+ f' ?subject {R2RML_CLASS} <{entity}> .' \
834
+ f' ?triples_map {RML_LOGICAL_SOURCE} ?logical_source .' \
835
+ f' ?logical_source ?logical_source_term ?logical_source_value .' \
836
+ f' OPTIONAL {{ ' \
837
+ f' ?triples_map {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
838
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_PREDICATE} ?predicate . }}' \
839
+ f' OPTIONAL {{ ?pom {R2RML_PREDICATE} ?predicate_bn.'\
840
+ f' ?predicate_bn ?predicate_term ?predicate_value . }}' \
841
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
842
+ f' OPTIONAL {{?pom {R2RML_OBJECT} ?object_bn .' \
843
+ f' ?object_bn ?object_term ?object_value. }}' \
844
+ f' OPTIONAL {{' \
845
+ f' ?object_bn {R2RML_PARENT_TRIPLESMAP} ?parent_tm .' \
846
+ f' OPTIONAL {{ ' \
847
+ f' ?object_bn {R2RML_JOIN_CONDITION} ?join_condition . ' \
848
+ f' ?join_condition ?condition_term ?condition_value .' \
849
+ f' }}' \
850
+ f' }}' \
851
+ f' }}' \
852
+ f' OPTIONAL {{ ' \
853
+ f' ?parent_triples_map {R2RML_PREDICATE_OBJECT_MAP} ?parent_pom.' \
854
+ f' OPTIONAL {{?parent_pom {R2RML_SHORTCUT_PREDICATE} ?parent_predicate .}}' \
855
+ f' OPTIONAL {{ ?parent_pom {R2RML_PREDICATE} ?parent_predicate_bn.'\
856
+ f' ?parent_predicate_bn ?parent_predicate_term ?parent_predicate_value . }}' \
857
+ f' ?parent_pom {R2RML_OBJECT} ?parent_object .' \
858
+ f' ?parent_object {R2RML_PARENT_TRIPLESMAP} ?triples_map .' \
859
+ f' OPTIONAL {{ ' \
860
+ f' ?parent_object {R2RML_JOIN_CONDITION} ?parent_join_conditions . ' \
861
+ f' ?parent_join_conditions ?parent_condition_term ?parent_conditions_value .' \
862
+ f' }}' \
863
+ f' }} ' \
864
+ f' }}'
865
+ #print(query)
866
+ restored_triples = deprecated_mappings.query(query)
867
+ for row in restored_triples:
868
+ output_mappings.add(row)
869
+ # Remove from deprecated_mappings
870
+ deprecated_mappings.update(query.replace("CONSTRUCT", "DELETE", 1))
871
+ elif entity_type == URIRef(OWL_OBJECT_PROPERTY_URI):
872
+ # Restore all predicate-object maps using this object property
873
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
874
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
875
+ f' CONSTRUCT {{' \
876
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
877
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
878
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
879
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap . ' \
880
+ f' ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions . ' \
881
+ f' ?joinConditions ?conditions ?condition_values }} ' \
882
+ f' WHERE {{' \
883
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
884
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
885
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
886
+ f' ?objectMap {R2RML_PARENT_TRIPLESMAP} ?parentTriplesMap .' \
887
+ f' OPTIONAL {{ ?objectMap {R2RML_JOIN_CONDITION} ?joinConditions .' \
888
+ f' ?joinConditions ?conditions ?condition_values }} . }}'
889
+ #print(query)
890
+ restored_triples = deprecated_mappings.query(query)
891
+ for row in restored_triples:
892
+ output_mappings.add(row)
893
+ deprecated_mappings.update(query.replace("CONSTRUCT", "DELETE", 1))
894
+ elif entity_type == URIRef(OWL_DATA_PROPERTY_URI):
895
+ # Restore all predicate-object maps using this data property
896
+ query = f' PREFIX {R2RML_PREFIX}: <{R2RML_URI}>' \
897
+ f' PREFIX {RML_PREFIX}: <{RML_URI}>' \
898
+ f' CONSTRUCT {{' \
899
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom.' \
900
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
901
+ f' ?pom {R2RML_SHORTCUT_OBJECT} ?object.' \
902
+ f' ?pom {R2RML_OBJECT} ?objectMap.' \
903
+ f' ?objectMap ?object_term ?objectValue .}}' \
904
+ f' WHERE {{' \
905
+ f' ?triplesMap {R2RML_PREDICATE_OBJECT_MAP} ?pom .' \
906
+ f' ?pom {R2RML_SHORTCUT_PREDICATE} <{entity}> .' \
907
+ f' OPTIONAL {{?pom {R2RML_SHORTCUT_OBJECT} ?object .}}' \
908
+ f' OPTIONAL {{ '\
909
+ f' ?pom {R2RML_OBJECT} ?objectMap .' \
910
+ f' ?objectMap ?object_term ?objectValue.' \
911
+ f' OPTIONAL {{ ?objectMap {R2RML_DATATYPE} ?range}} }} . }}'
912
+ #print(query)
913
+ restored_triples = deprecated_mappings.query(query)
914
+ for row in restored_triples:
915
+ output_mappings.add(row)
916
+ deprecated_mappings.update(query.replace("CONSTRUCT", "DELETE", 1))
917
+
918
+ def rename_entity(change, change_data, output_mappings):
919
+ """
920
+ Renames a term (class, property, etc.) in the output_mappings.
921
+ Args:
922
+ change: the URI of the change which needs to be of the type RenameEntity
923
+ """
924
+ query = f'SELECT DISTINCT ?old_entity ?new_entity WHERE {{ ' \
925
+ f'<{change}> {OCH_OLD_NAME} ?old_entity. ' \
926
+ f'<{change}> {OCH_NEW_NAME} ?new_entity. }}'
927
+ for result in change_data.query(query):
928
+ old_entity = result["old_entity"]
929
+ new_entity = result["new_entity"]
930
+ # Update all triples where old_entity appears as subject, predicate, or object
931
+ update_query = f' DELETE {{ ?s ?p ?o. }} ' \
932
+ f' INSERT {{ ?s_new ?p_new ?o_new. }} ' \
933
+ f' WHERE {{ ' \
934
+ f' ?s ?p ?o. ' \
935
+ f' BIND(IF(?s = <{old_entity}>, <{new_entity}>, ?s) AS ?s_new) ' \
936
+ f' BIND(IF(?p = <{old_entity}>, <{new_entity}>, ?p) AS ?p_new) ' \
937
+ f' BIND(IF(?o = <{old_entity}>, <{new_entity}>, ?o) AS ?o_new) ' \
938
+ f' FILTER(?s != ?s_new || ?p != ?p_new || ?o != ?o_new) ' \
939
+ f' }}'
940
+ output_mappings.update(update_query)
941
+
942
+ #---------------------------------------SHACL CHANGES-------------------------------------------------------------
943
+
944
+
945
+ def deprecate_entity_shacl(change,change_data,output_shacl):
946
+ """
947
+ Deprecates an entity in the SHACL shape by adding the "sh:deactivated true" to the corresponding shape.
948
+ Args:
949
+ change: the URI of the change which needs to be of the type deprecate_entity
950
+ """
951
+ query = f' SELECT DISTINCT ?entity WHERE {{ ' \
952
+ f' <{change}> {OCH_DEPRECATED_ENTITY} ?entity. }}'
953
+ #print(query)
954
+ for result in change_data.query(query):
955
+ entity = result["entity"]
956
+ query = (
957
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}> '
958
+ f' INSERT {{ '
959
+ f' ?shape {SHACL_DEACTIVATED} true . '
960
+ f' }} '
961
+ f' WHERE {{ '
962
+ f' {{ '
963
+ f' ?shape a {SHACL_NODE_SHAPE} ; '
964
+ f' {SHACL_TARGET_CLASS} <{entity}> . '
965
+ f' }} '
966
+ f' UNION '
967
+ f' {{ '
968
+ f' ?shape {SHACL_PATH} <{entity}> . '
969
+ f' }} '
970
+ f' FILTER NOT EXISTS {{ ?shape {SHACL_DEACTIVATED} true }} '
971
+ f' }}'
972
+ )
973
+ #print(query)
974
+ output_shacl.update(query)
975
+
976
+ #-----------------------------------------------------------------------------------------------------------------
977
+
978
+ def revoke_deprecate_entity_shacl(change,change_data,output_shacl):
979
+ """
980
+ Revokes the deprecation of an entity in the SHACL shape by removing the "sh:deactivated true" from the corresponding shape.
981
+ Args:
982
+ change: the URI of the change which needs to be of the type revoke_deprecate_entity
983
+ """
984
+ query = f' SELECT DISTINCT ?entity WHERE {{ ' \
985
+ f' <{change}> {OCH_UNDEPRECATED_ELEMENT} ?entity. }}'
986
+ #print(query)
987
+ for result in change_data.query(query):
988
+ entity = result["entity"]
989
+ query = (
990
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}> '
991
+ f' DELETE {{ '
992
+ f' ?shape {SHACL_DEACTIVATED} true . '
993
+ f' }} '
994
+ f' WHERE {{ '
995
+ f' {{ '
996
+ f' ?shape a {SHACL_NODE_SHAPE} ; '
997
+ f' {SHACL_TARGET_CLASS} <{entity}> . '
998
+ f' }} '
999
+ f' UNION '
1000
+ f' {{ '
1001
+ f' ?shape {SHACL_PATH} <{entity}> . '
1002
+ f' }} '
1003
+ f' }}'
1004
+ )
1005
+ #print(query)
1006
+ output_shacl.update(query)
1007
+
1008
+ #-----------------------------------------------------------------------------------------------------------------
1009
+
1010
+ def add_class_shacl(change, change_data, output_shapes):
1011
+ """
1012
+ Adds a class defined in the change KG into the shacl shape. This takes the form of adding NodeShape with the class as targetClass.
1013
+ Args:
1014
+ change: the URI of the change which needs to be of the type AddClass
1015
+ Returns:
1016
+ the output_shapes updated with a new class
1017
+ """
1018
+ select_change = f' SELECT DISTINCT ?class WHERE {{' \
1019
+ f' <{change}> {OCH_ADDED_CLASS} ?class .}} '
1020
+
1021
+ for result in change_data.query(select_change):
1022
+ added_class = result["class"]
1023
+ if "#" in added_class:
1024
+ class_local = added_class.split("#")[-1]
1025
+ elif "/" in added_class:
1026
+ class_local = added_class.split("/")[-1]
1027
+ else:
1028
+ class_local = added_class
1029
+ insert_class_query = (
1030
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1031
+ f' INSERT DATA {{ '
1032
+ f' <{EXAMPLE_URI}{class_local}Shape> '
1033
+ f' a {SHACL_NODE_SHAPE} ; '
1034
+ f' {SHACL_TARGET_CLASS} <{added_class}> ; '
1035
+ f' }}'
1036
+ )
1037
+ #print(insert_class_query)
1038
+ output_shapes.update(insert_class_query)
1039
+
1040
+ def remove_class_shacl(change, change_data, output_mappings):
1041
+ """
1042
+ Removes a class defined in the change KG from the SHACL shape. This deletes the NodeShape with the class as targetClass and all related property shapes and nested shapes.
1043
+ Args:
1044
+ change: the URI of the change which needs to be of the type RemoveClass
1045
+ Returns:
1046
+ the output_shapes updated with the class and its related shapes removed
1047
+ """
1048
+ select_change = f' SELECT DISTINCT ?class WHERE {{' \
1049
+ f' <{change}> {OCH_DELETED_CLASS} ?class .}} '
1050
+
1051
+ for result in change_data.query(select_change):
1052
+ removed_class = result["class"]
1053
+ delete_class_query = (
1054
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>\n'
1055
+ f' PREFIX {RDF_PREFIX}: <{RDF_URI}>\n'
1056
+ f' DELETE {{\n'
1057
+ f' ?shape ?p ?o .\n'
1058
+ f' ?propShape ?pp ?po .\n'
1059
+ f' ?list ?lp ?lo .\n'
1060
+ f' ?listItem ?listItemP ?listItemO .\n'
1061
+ f' ?restNode ?restP ?restO .\n'
1062
+ f' }}\n'
1063
+ f' WHERE {{\n'
1064
+ f' ?shape a {SHACL_NODE_SHAPE} ;\n'
1065
+ f' {SHACL_TARGET_CLASS} <{removed_class}> ;\n'
1066
+ f' ?p ?o .\n'
1067
+ f' OPTIONAL {{\n'
1068
+ f' ?shape {SHACL_PROPERTY_SHAPE} ?propShape .\n'
1069
+ f' FILTER (isBlank(?propShape))\n'
1070
+ f' ?propShape ?pp ?po .\n'
1071
+ f' OPTIONAL {{\n'
1072
+ f' ?propShape ?listPred ?list .\n'
1073
+ f' FILTER(?listPred IN ({SHACL_IN}, {SHACL_OR}, {SHACL_AND}, {SHACL_XONE}))\n'
1074
+ f' ?list {RDF_REST}*/{RDF_FIRST} ?listItem .\n'
1075
+ f' ?list ?lp ?lo .\n'
1076
+ f' OPTIONAL {{ ?listItem ?listItemP ?listItemO . }}\n'
1077
+ f' ?list {RDF_REST}* ?restNode .\n'
1078
+ f' ?restNode ?restP ?restO .\n'
1079
+ f' }}\n'
1080
+ f' }}\n'
1081
+ f' }}'
1082
+ )
1083
+ #print(delete_class_query)
1084
+ output_mappings.update(delete_class_query)
1085
+
1086
+
1087
+ def add_super_class_shacl(change, change_data, output_shapes):
1088
+ """
1089
+ Adds a subclass to the SHACL NodeShape of the superclass by inserting the subclas as an additional sh:targetClass.
1090
+ Args:
1091
+ change: the URI of the change which needs to be of the type add_sub_class
1092
+ Returns:
1093
+ The output_shapes updated with the NodeShape of the superclass including the subclass as targetClass.
1094
+ """
1095
+ query = (
1096
+ f' SELECT DISTINCT ?super_class ?sub_class WHERE {{ '
1097
+ f' <{change}> {OCH_ADD_SUBCLASS_SOURCE} ?sub_class. '
1098
+ f' <{change}> {OCH_ADD_SUBCLASS_TARGET} ?super_class. }}'
1099
+ )
1100
+ for result in change_data.query(query):
1101
+ sub_class = result["sub_class"]
1102
+ super_class = result["super_class"]
1103
+ insert_super_class_query = (
1104
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1105
+ f' INSERT {{ '
1106
+ f' ?shape {SHACL_TARGET_CLASS} <{sub_class}> . '
1107
+ f' }} '
1108
+ f' WHERE {{ '
1109
+ f' ?shape a {SHACL_NODE_SHAPE} ; '
1110
+ f' {SHACL_TARGET_CLASS} <{super_class}> . '
1111
+ f' FILTER NOT EXISTS {{ ?shape {SHACL_TARGET_CLASS} <{sub_class}> }} '
1112
+ f' }}'
1113
+ )
1114
+ output_shapes.update(insert_super_class_query)
1115
+
1116
+ def remove_super_class_shacl(change, change_data, output_shapes):
1117
+ """
1118
+ Removes a subclass from the SHACL NodeShape of the superclass by deleting the subclass from sh:targetClass.
1119
+ Args:
1120
+ change: the URI of the change which needs to be of the type add_sub_class
1121
+ Returns:
1122
+ The output_shapes updated with the NodeShape of the superclass not including the subclass as targetClass.
1123
+ """
1124
+ query = (
1125
+ f' SELECT DISTINCT ?super_class ?sub_class WHERE {{ '
1126
+ f' <{change}> {OCH_REMOVE_SUBCLASS_SOURCE} ?sub_class. '
1127
+ f' <{change}> {OCH_REMOVE_SUBCLASS_TARGET} ?super_class. }}'
1128
+ )
1129
+ for result in change_data.query(query):
1130
+ sub_class = result["sub_class"]
1131
+ super_class = result["super_class"]
1132
+ remove_super_class_query = (
1133
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1134
+ f' DELETE {{ '
1135
+ f' ?shape {SHACL_TARGET_CLASS} <{sub_class}> . '
1136
+ f' }} '
1137
+ f' WHERE {{ '
1138
+ f' ?shape a {SHACL_NODE_SHAPE} ; '
1139
+ f' {SHACL_TARGET_CLASS} <{super_class}>, <{sub_class}> . '
1140
+ f' }}'
1141
+ )
1142
+ output_shapes.update(remove_super_class_query)
1143
+
1144
+ def add_equivalent_class_shacl(change, change_data, output_shapes):
1145
+ """
1146
+ Adds an equivalent class to the SHACL NodeShape of the class by inserting the equivalent class as an additional sh:targetClass.
1147
+ Args:
1148
+ change: the URI of the change which needs to be of the type add_equivalent_class
1149
+ Returns:
1150
+ The output_shapes updated with the NodeShape of the class including the equivalent class as targetClass.
1151
+ """
1152
+ query = (
1153
+ f' SELECT DISTINCT ?source_class ?target_class WHERE {{ '
1154
+ f' <{change}> {OCH_ADD_EQUIVALENT_CLASS_SOURCE} ?source_class. '
1155
+ f' <{change}> {OCH_ADD_EQUIVALENT_CLASS_TARGET} ?target_class. }}'
1156
+ )
1157
+ for result in change_data.query(query):
1158
+ source_class = result["source_class"]
1159
+ target_class = result["target_class"]
1160
+ insert_equivalent_class_query = (
1161
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1162
+ f' PREFIX {PROV_PREFIX}: <{PROV_URI}>'
1163
+ f' INSERT {{ '
1164
+ f' ?shape {SHACL_TARGET_CLASS} ?otherClass . '
1165
+ f' ?shape {PROV_WAS_DERIVED_FROM} ?originalClass . '
1166
+ f' }} '
1167
+ f' WHERE {{ '
1168
+ f' ?shape a {SHACL_NODE_SHAPE} ; '
1169
+ f' {SHACL_TARGET_CLASS} ?originalClass . '
1170
+ f' VALUES (?originalClass ?otherClass) {{ '
1171
+ f' (<{source_class}> <{target_class}>) '
1172
+ f' (<{target_class}> <{source_class}>) '
1173
+ f' }} '
1174
+ f' FILTER NOT EXISTS {{ ?shape {SHACL_TARGET_CLASS} ?otherClass }} '
1175
+ f' }}'
1176
+ )
1177
+ #print(insert_equivalent_class_query)
1178
+ output_shapes.update(insert_equivalent_class_query)
1179
+
1180
+ def remove_equivalent_class_shacl(change, change_data, output_shapes):
1181
+ """
1182
+ Removes an equivalent class from the SHACL NodeShape of the class by deleting the equivalent class from the sh:targetClass.
1183
+ Args:
1184
+ change: the URI of the change which needs to be of the type remove_equivalent_class
1185
+ Returns:
1186
+ The output_shapes updated with the NodeShape of the class excluding the equivalent class as targetClass.
1187
+ """
1188
+ query = (
1189
+ f' SELECT DISTINCT ?source_class ?target_class WHERE {{ '
1190
+ f' <{change}> {OCH_REMOVE_EQUIVALENT_CLASS_SOURCE} ?source_class. '
1191
+ f' <{change}> {OCH_REMOVE_EQUIVALENT_CLASS_TARGET} ?target_class. }}'
1192
+ )
1193
+ for result in change_data.query(query):
1194
+ source_class = result["source_class"]
1195
+ target_class = result["target_class"]
1196
+ delete_equivalent_class_query = (
1197
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>\n'
1198
+ f' PREFIX {PROV_PREFIX}: <{PROV_URI}>\n'
1199
+ f' DELETE {{\n'
1200
+ f' ?shape {SHACL_TARGET_CLASS} ?otherClass .\n'
1201
+ f' ?shape {PROV_WAS_DERIVED_FROM} ?originalClass .\n'
1202
+ f' }}\n'
1203
+ f' WHERE {{\n'
1204
+ f' ?shape a {SHACL_NODE_SHAPE} ;\n'
1205
+ f' {SHACL_TARGET_CLASS} ?originalClass, ?otherClass ;\n'
1206
+ f' {PROV_WAS_DERIVED_FROM} ?originalClass .\n'
1207
+ f' VALUES (?originalClass ?otherClass) {{\n'
1208
+ f' (<{source_class}> <{target_class}>)\n'
1209
+ f' (<{target_class}> <{source_class}>)\n'
1210
+ f' }}\n'
1211
+ f' }}'
1212
+ )
1213
+ #print(delete_equivalent_class_query)
1214
+ output_shapes.update(delete_equivalent_class_query)
1215
+
1216
+
1217
+ def add_disjoint_class_shacl(change, change_data, output_shapes):
1218
+ """
1219
+ Adds a disjoint class restriction to the SHACL NodeShape via SHACL-SPARQL query.
1220
+ Args:
1221
+ change: the URI of the change which needs to be of the type add_disjoint_class
1222
+ Returns:
1223
+ The output_shapes updated with the constraints that enforce the disjointness of the classes.
1224
+ """
1225
+ query = (
1226
+ f' SELECT DISTINCT ?source_class ?target_class WHERE {{ '
1227
+ f' <{change}> {OCH_ADD_DISJOINT_CLASS_SOURCE} ?source_class. '
1228
+ f' <{change}> {OCH_ADD_DISJOINT_CLASS_TARGET} ?target_class. }}'
1229
+ )
1230
+ for result in change_data.query(query):
1231
+ source_class = result["source_class"]
1232
+ target_class = result["target_class"]
1233
+ add_disjoint_class_query = (
1234
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>\n'
1235
+ f' INSERT {{\n'
1236
+ f' ?sourceShape {SHACL_NOT} [ {SHACL_CLASS} <{target_class}> ] .\n'
1237
+ f' ?targetShape {SHACL_NOT} [ {SHACL_CLASS} <{source_class}> ] .\n'
1238
+ f' }}\n'
1239
+ f' WHERE {{\n'
1240
+ f' ?sourceShape a {SHACL_NODE_SHAPE} ;\n'
1241
+ f' {SHACL_TARGET_CLASS} <{source_class}> .\n'
1242
+ f' ?targetShape a {SHACL_NODE_SHAPE} ;\n'
1243
+ f' {SHACL_TARGET_CLASS} <{target_class}> .\n'
1244
+ f'}}'
1245
+ )
1246
+ print(add_disjoint_class_query)
1247
+ output_shapes.update(add_disjoint_class_query)
1248
+
1249
+ def remove_disjoint_class_shacl(change, change_data, output_shapes):
1250
+ """
1251
+ Removes a disjoint class restriction from the SHACL NodeShape via SHACL-SPARQL query.
1252
+ Args:
1253
+ change: the URI of the change which needs to be of the type remove_disjoint_class
1254
+ Returns:
1255
+ The output_shapes updated without the constraints that enforce the disjointness of the classes.
1256
+ """
1257
+ query = (
1258
+ f' SELECT DISTINCT ?source_class ?target_class WHERE {{ '
1259
+ f' <{change}> {OCH_REMOVE_DISJOINT_CLASS_SOURCE} ?source_class. '
1260
+ f' <{change}> {OCH_REMOVE_DISJOINT_CLASS_TARGET} ?target_class. }}'
1261
+ )
1262
+ for result in change_data.query(query):
1263
+ source_class = result["source_class"]
1264
+ target_class = result["target_class"]
1265
+ remove_disjoint_class_query = (
1266
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>\n'
1267
+ f' DELETE {{\n'
1268
+ f' ?sourceShape {SHACL_NOT} ?propertyShapeSource.\n'
1269
+ f' ?propertyShapeSource {SHACL_CLASS} <{target_class}>.\n'
1270
+ f' ?targetShape {SHACL_NOT} ?propertyShapeTarget. \n'
1271
+ f' ?propertyShapeTarget {SHACL_CLASS} <{source_class}>.\n'
1272
+ f' }}\n'
1273
+ f' WHERE {{\n'
1274
+ f' ?sourceShape a {SHACL_NODE_SHAPE} ;\n'
1275
+ f' {SHACL_TARGET_CLASS} <{source_class}> .\n'
1276
+ f' ?targetShape a {SHACL_NODE_SHAPE} ;\n'
1277
+ f' {SHACL_TARGET_CLASS} <{target_class}> .\n'
1278
+ f' ?sourceShape {SHACL_NOT} ?propertyShapeSource.\n'
1279
+ f' ?propertyShapeSource {SHACL_CLASS} <{target_class}>.\n'
1280
+ f' ?targetShape {SHACL_NOT} ?propertyShapeTarget. \n'
1281
+ f' ?propertyShapeTarget {SHACL_CLASS} <{source_class}>.\n'
1282
+ f'}}'
1283
+ )
1284
+ #print(remove_disjoint_class_query)
1285
+ output_shapes.update(remove_disjoint_class_query)
1286
+
1287
+ def add_object_property_shacl(change,change_data, output_shapes):
1288
+ """
1289
+ Adds an object property to the NodeShape indicated in the domain. For a full change in the Property Shape the domain, property and range additions are needed.
1290
+ Args:
1291
+ change: the URI of the change which needs to be of the type addObjectProperty
1292
+ Returns:
1293
+ the output_shapes updated with the added predicate object maps.
1294
+ """
1295
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
1296
+ f' <{change}> {OCH_ADDED_OBJECT_PROPERTY} ?property .' \
1297
+ f' ?domainchange {OCH_ADDED_DOMAIN_TO_PROPERTY} ?property.' \
1298
+ f' ?domainchange {OCH_ADDED_DOMAIN} ?domain.' \
1299
+ f' ?rangechange {OCH_ADDED_RANGE_TO_PROPERTY} ?property.' \
1300
+ f' ?rangechange {OCH_ADDED_OBJECT_RANGE} ?range. }}'
1301
+
1302
+ for result in change_data.query(query):
1303
+ property_domain = result["domain"]
1304
+ property_predicate = result["property"]
1305
+ property_range = result["range"]
1306
+ if "#" in property_predicate:
1307
+ property_local = property_predicate.split("#")[-1]
1308
+ elif "/" in property_predicate:
1309
+ property_local = property_predicate.split("/")[-1]
1310
+ else:
1311
+ property_local = property_predicate
1312
+ insert_object_property_query = (
1313
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1314
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1315
+ f' INSERT {{ '
1316
+ f' ?nodeShape {SHACL_PROPERTY} {EXAMPLE_PREFIX}:{property_local}Shape . '
1317
+ f' {EXAMPLE_PREFIX}:{property_local}Shape {SHACL_PATH} <{property_predicate}> ; '
1318
+ f' {SHACL_CLASS} <{property_range}> . '
1319
+ f' }} '
1320
+ f' WHERE {{ '
1321
+ f' ?nodeShape a {SHACL_NODE_SHAPE} ; '
1322
+ f' {SHACL_TARGET_CLASS} <{property_domain}> . '
1323
+ f' }}'
1324
+ )
1325
+ #print(insert_object_property_query)
1326
+ output_shapes.update(insert_object_property_query)
1327
+
1328
+ def remove_object_property_shacl(change, change_data, output_shapes):
1329
+ """
1330
+ Removes an object property from the NodeShape indicated in the domain. For a full change in the Property Shape the domain, property and range removals are needed.
1331
+ Args:
1332
+ change: the URI of the change which needs to be of the type removeObjectProperty
1333
+ Returns:
1334
+ the output_shapes updated with the property shape removed.
1335
+ """
1336
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
1337
+ f' <{change}> {OCH_REMOVED_OBJECT_PROPERTY} ?property .' \
1338
+ f' ?domainchange {OCH_REMOVED_DOMAIN_TO_PROPERTY} ?property.' \
1339
+ f' ?domainchange {OCH_REMOVED_DOMAIN} ?domain.' \
1340
+ f' ?rangechange {OCH_REMOVED_RANGE_TO_PROPERTY} ?property.' \
1341
+ f' ?rangechange {OCH_REMOVED_OBJECT_RANGE} ?range. }}'
1342
+
1343
+ for result in change_data.query(query):
1344
+ property_domain = result["domain"]
1345
+ property_predicate = result["property"]
1346
+ property_range = result["range"]
1347
+
1348
+ # Remove property shape whether it is a blank node (sh:property) or a full PropertyShape (URI)
1349
+ delete_object_property_query = (
1350
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>\n'
1351
+ f' DELETE {{\n'
1352
+ f' ?nodeShape {SHACL_PROPERTY} ?propertyShape .\n'
1353
+ f' ?propertyShape {SHACL_PATH} <{property_predicate}> ;\n'
1354
+ f' {SHACL_CLASS} <{property_range}> .\n'
1355
+ f' ?propertyShape ?pp ?po .\n'
1356
+ f' ?list ?lp ?lo .\n'
1357
+ f' ?listItem ?listItemP ?listItemO .\n'
1358
+ f' ?restNode ?restP ?restO .\n'
1359
+ f' }}\n'
1360
+ f' WHERE {{\n'
1361
+ f' ?nodeShape a {SHACL_NODE_SHAPE} ;\n'
1362
+ f' {SHACL_TARGET_CLASS} <{property_domain}> ;\n'
1363
+ f' {SHACL_PROPERTY} ?propertyShape .\n'
1364
+ f' ?propertyShape {SHACL_PATH} <{property_predicate}> ;\n'
1365
+ f' {SHACL_CLASS} <{property_range}> .\n'
1366
+ f' OPTIONAL {{ ?propertyShape ?pp ?po .\n'
1367
+ f' OPTIONAL {{\n'
1368
+ f' ?propertyShape ?listPred ?list .\n'
1369
+ f' FILTER(?listPred IN ({SHACL_IN}, {SHACL_OR}, {SHACL_AND}, {SHACL_XONE}))\n'
1370
+ f' ?list {RDF_REST}*/{RDF_FIRST} ?listItem .\n'
1371
+ f' ?list ?lp ?lo .\n'
1372
+ f' OPTIONAL {{ ?listItem ?listItemP ?listItemO . }}\n'
1373
+ f' ?list {RDF_REST}* ?restNode .\n'
1374
+ f' ?restNode ?restP ?restO .\n'
1375
+ f' }}\n'
1376
+ f' }}\n'
1377
+ f'}}'
1378
+ )
1379
+ #print(delete_object_property_query)
1380
+ output_shapes.update(delete_object_property_query)
1381
+
1382
+ def add_data_property_shacl(change, change_data, output_shapes):
1383
+ """
1384
+ Adds a data property to the NodeShape indicated in the domain. For a full change in the Property Shape the domain, property and range additions are needed.
1385
+ Args:
1386
+ change: the URI of the change which needs to be of the type addDataProperty
1387
+ Returns:
1388
+ the output_shapes updated with the added data property shape.
1389
+ """
1390
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
1391
+ f' <{change}> {OCH_ADDED_DATA_PROPERTY} ?property .' \
1392
+ f' ?domainchange {OCH_ADDED_DOMAIN_TO_PROPERTY} ?property.' \
1393
+ f' ?domainchange {OCH_ADDED_DOMAIN} ?domain.' \
1394
+ f' ?rangechange {OCH_ADDED_RANGE_TO_PROPERTY} ?property.' \
1395
+ f' ?rangechange {OCH_ADDED_DATA_RANGE} ?range. }}'
1396
+
1397
+ for result in change_data.query(query):
1398
+ property_domain = result["domain"]
1399
+ property_predicate = result["property"]
1400
+ property_range = result["range"]
1401
+ if "#" in property_predicate:
1402
+ property_local = property_predicate.split("#")[-1]
1403
+ elif "/" in property_predicate:
1404
+ property_local = property_predicate.split("/")[-1]
1405
+ else:
1406
+ property_local = property_predicate
1407
+ insert_data_property_query = (
1408
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1409
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1410
+ f' INSERT {{ '
1411
+ f' ?nodeShape {SHACL_PROPERTY} {EXAMPLE_PREFIX}:{property_local}Shape . '
1412
+ f' {EXAMPLE_PREFIX}:{property_local}Shape {SHACL_PATH} <{property_predicate}> ; '
1413
+ f' {SHACL_DATATYPE} <{property_range}> . '
1414
+ f' }} '
1415
+ f' WHERE {{ '
1416
+ f' ?nodeShape a {SHACL_NODE_SHAPE} ; '
1417
+ f' {SHACL_TARGET_CLASS} <{property_domain}> . '
1418
+ f' }}'
1419
+ )
1420
+ print(insert_data_property_query)
1421
+ output_shapes.update(insert_data_property_query)
1422
+
1423
+ def remove_data_property_shacl(change, change_data, output_shapes):
1424
+ """
1425
+ Removes a data property from the NodeShape indicated in the domain. For a full change in the Property Shape the domain, property and range removals are needed.
1426
+ Args:
1427
+ change: the URI of the change which needs to be of the type removeDataProperty
1428
+ Returns:
1429
+ the output_shapes updated with the data property shape removed.
1430
+ """
1431
+ query = f' SELECT DISTINCT ?domain ?property ?range WHERE {{ ' \
1432
+ f' <{change}> {OCH_REMOVED_DATA_PROPERTY} ?property .' \
1433
+ f' ?domainchange {OCH_REMOVED_DOMAIN_TO_PROPERTY} ?property.' \
1434
+ f' ?domainchange {OCH_REMOVED_DOMAIN} ?domain.' \
1435
+ f' ?rangechange {OCH_REMOVED_RANGE_TO_PROPERTY} ?property.' \
1436
+ f' ?rangechange {OCH_REMOVED_DATA_RANGE} ?range. }}'
1437
+
1438
+ for result in change_data.query(query):
1439
+ property_domain = result["domain"]
1440
+ property_predicate = result["property"]
1441
+ property_range = result["range"]
1442
+
1443
+ delete_data_property_query = (
1444
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>\n'
1445
+ f' DELETE {{\n'
1446
+ f' ?nodeShape {SHACL_PROPERTY} ?propertyShape .\n'
1447
+ f' ?propertyShape {SHACL_PATH} <{property_predicate}> ;\n'
1448
+ f' {SHACL_DATATYPE} <{property_range}> .\n'
1449
+ f' ?propertyShape ?pp ?po .\n'
1450
+ f' ?list ?lp ?lo .\n'
1451
+ f' ?listItem ?listItemP ?listItemO .\n'
1452
+ f' ?restNode ?restP ?restO .\n'
1453
+ f' }}\n'
1454
+ f' WHERE {{\n'
1455
+ f' ?nodeShape a {SHACL_NODE_SHAPE} ;\n'
1456
+ f' {SHACL_TARGET_CLASS} <{property_domain}> ;\n'
1457
+ f' {SHACL_PROPERTY} ?propertyShape .\n'
1458
+ f' ?propertyShape {SHACL_PATH} <{property_predicate}> ;\n'
1459
+ f' {SHACL_DATATYPE} <{property_range}> .\n'
1460
+ f' OPTIONAL {{ ?propertyShape ?pp ?po .\n'
1461
+ f' OPTIONAL {{\n'
1462
+ f' ?propertyShape ?listPred ?list .\n'
1463
+ f' FILTER(?listPred IN ({SHACL_IN}, {SHACL_OR}, {SHACL_AND}, {SHACL_XONE}))\n'
1464
+ f' ?list {RDF_REST}*/{RDF_FIRST} ?listItem .\n'
1465
+ f' ?list ?lp ?lo .\n'
1466
+ f' OPTIONAL {{ ?listItem ?listItemP ?listItemO . }}\n'
1467
+ f' ?list {RDF_REST}* ?restNode .\n'
1468
+ f' ?restNode ?restP ?restO .\n'
1469
+ f' }}\n'
1470
+ f' }}\n'
1471
+ f'}}'
1472
+ )
1473
+ print(delete_data_property_query)
1474
+ output_shapes.update(delete_data_property_query)
1475
+
1476
+ def add_characteristic_shacl(change, change_data, output_shapes):
1477
+ """
1478
+ Modifies the property shape corresponding to a given property to add restrictions based on the added characteristic.
1479
+ Args:
1480
+ change: the URI of the change which needs to be of the type addCharacteristic
1481
+ Returns:
1482
+ the output_shapes updated with the data property shape modified.
1483
+ """
1484
+ print("Entra en la función add_characteristic_shacl")
1485
+ query = f' SELECT DISTINCT ?property ?characteristic WHERE {{ ' \
1486
+ f' <{change}> {OCH_ADDED_CHARACTERISTIC_TO_PROPERTY} ?property ;' \
1487
+ f' {OCH_ADDED_CHARACTERISTIC} ?characteristic }}'
1488
+ print(query)
1489
+ for result in change_data.query(query):
1490
+ property = result["property"]
1491
+ characteristic = result["characteristic"]
1492
+ print(f"Property: {property}, Characteristic: {characteristic}")
1493
+ # Add SHACL restrictions for property characteristics
1494
+ if characteristic == URIRef(OWL_FUNCTIONAL_PROPERTY_URI):
1495
+ #print("Entra en la condición de OWL_FUNCTIONAL_PROPERTY")
1496
+ # Functional property: sh:maxCount 1
1497
+ insert_characteristic_query = (
1498
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1499
+ f' INSERT {{ ?propertyShape {SHACL_MAX_COUNT} 1 }}'
1500
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1501
+ )
1502
+ print(insert_characteristic_query)
1503
+ output_shapes.update(insert_characteristic_query)
1504
+ elif characteristic == URIRef(OWL_SYMMETRIC_PROPERTY_URI):
1505
+ # Symmetric property: custom SHACL-SPARQL constraint
1506
+ insert_characteristic_query = (
1507
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1508
+ f' INSERT {{ ?propertyShape {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v . FILTER NOT EXISTS {{ ?v <{property}> $this }} }}" ] }}'
1509
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1510
+ )
1511
+ print(insert_characteristic_query)
1512
+ output_shapes.update(insert_characteristic_query)
1513
+ elif characteristic == URIRef(OWL_ASYMMETRIC_PROPERTY_URI):
1514
+ # Asymmetric property: custom SHACL-SPARQL constraint
1515
+ insert_characteristic_query = (
1516
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1517
+ f' INSERT {{ ?propertyShape {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v . FILTER EXISTS {{ ?v <{property}> $this }} }}" ] }}'
1518
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1519
+ )
1520
+ print(insert_characteristic_query)
1521
+ output_shapes.update(insert_characteristic_query)
1522
+ elif characteristic == URIRef(OWL_REFLEXIVE_PROPERTY_URI):
1523
+ # Reflexive property: custom SHACL-SPARQL constraint
1524
+ insert_characteristic_query = (
1525
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1526
+ f' INSERT {{ ?propertyShape {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ FILTER NOT EXISTS {{ $this <{property}> $this }} }}" ] }}'
1527
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1528
+ )
1529
+ print(insert_characteristic_query)
1530
+ output_shapes.update(insert_characteristic_query)
1531
+ elif characteristic == URIRef(OWL_IRREFLEXIVE_PROPERTY_URI):
1532
+ # Irreflexive property: custom SHACL-SPARQL constraint
1533
+ insert_characteristic_query = (
1534
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1535
+ f' INSERT {{ ?propertyShape {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> $this }}" ] }}'
1536
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1537
+ )
1538
+ print(insert_characteristic_query)
1539
+ output_shapes.update(insert_characteristic_query)
1540
+ elif characteristic == URIRef(OWL_INVERSE_FUNCTIONAL_PROPERTY_URI):
1541
+ # Inverse functional property: sh:maxCount 1 on inverse path
1542
+ # Use a blank node for the property shape and avoid using a URI for the shape
1543
+ if "#" in property:
1544
+ property_local = property.split("#")[-1]
1545
+ elif "/" in property:
1546
+ property_local = property.split("/")[-1]
1547
+ else:
1548
+ property_local = property
1549
+ insert_characteristic_query = (
1550
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1551
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1552
+ f' INSERT DATA {{ '
1553
+ f' {EXAMPLE_PREFIX}:{property_local}InvFunctShape a {SHACL_PROPERTY_SHAPE} ; '
1554
+ f' {SHACL_PATH} [ {SHACL_INVERSE_PATH} <{property}> ] ; '
1555
+ f' {SHACL_MAX_COUNT} 1 . '
1556
+ f' }} '
1557
+ )
1558
+ print(insert_characteristic_query)
1559
+ output_shapes.update(insert_characteristic_query)
1560
+ elif characteristic == URIRef(OWL_TRANSITIVE_PROPERTY_URI):
1561
+ # Transitive property: custom SHACL-SPARQL constraint
1562
+ insert_characteristic_query = (
1563
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1564
+ f' INSERT {{ ?propertyShape {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v1 . ?v1 <{property}> ?v2 . FILTER NOT EXISTS {{ $this <{property}> ?v2 }} }}" ] }}'
1565
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1566
+ )
1567
+ print(insert_characteristic_query)
1568
+ output_shapes.update(insert_characteristic_query)
1569
+
1570
+ def remove_characteristic_shacl(change, change_data, output_shapes):
1571
+ #print("Entra en la función remove_characteristic_shacl")
1572
+ """
1573
+ Modifies the property shape corresponding to a given property to remove restrictions based on the removed characteristic.
1574
+ Args:
1575
+ change: the URI of the change which needs to be of the type removeCharacteristic
1576
+ Returns:
1577
+ the output_shapes updated with the data property shape modified.
1578
+ """
1579
+ query = f' SELECT DISTINCT ?property ?characteristic WHERE {{ ' \
1580
+ f' <{change}> {OCH_REMOVED_CHARACTERISTIC_FROM_PROPERTY} ?property ;' \
1581
+ f' {OCH_REMOVED_CHARACTERISTIC} ?characteristic }}'
1582
+ print(query)
1583
+ for result in change_data.query(query):
1584
+ property = result["property"]
1585
+ characteristic = result["characteristic"]
1586
+ print(f"Property: {property}, Characteristic: {characteristic}")
1587
+ # Remove SHACL restrictions for property characteristics
1588
+ if characteristic == URIRef(OWL_FUNCTIONAL_PROPERTY_URI):
1589
+ #print("Entra en la condición de OWL_FUNCTIONAL_PROPERTY")
1590
+ # Functional property: sh:maxCount 1
1591
+ delete_characteristic_query = (
1592
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1593
+ f' DELETE {{ ?propertyShape {SHACL_MAX_COUNT} 1 }}'
1594
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> }}'
1595
+ )
1596
+ print(delete_characteristic_query)
1597
+ output_shapes.update(delete_characteristic_query)
1598
+ elif characteristic == URIRef(OWL_SYMMETRIC_PROPERTY_URI):
1599
+ print(f"Entra en la condición de remove OWL_SYMMETRIC_PROPERTY: {property}")
1600
+ # Symmetric property: custom SHACL-SPARQL constraint
1601
+ delete_characteristic_query = (
1602
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1603
+ f' DELETE {{ ?propertyShape {SHACL_SPARQL} ?constraintNode .'
1604
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1605
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v . FILTER NOT EXISTS {{ ?v <{property}> $this }} }}" }}'
1606
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> . '
1607
+ f' ?propertyShape {SHACL_SPARQL} ?constraintNode . '
1608
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1609
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v . FILTER NOT EXISTS {{ ?v <{property}> $this }} }}" }}'
1610
+ )
1611
+ print(delete_characteristic_query)
1612
+ output_shapes.update(delete_characteristic_query)
1613
+ elif characteristic == URIRef(OWL_ASYMMETRIC_PROPERTY_URI):
1614
+ # Asymmetric property: custom SHACL-SPARQL constraint
1615
+ #print(f"Entra en la condición de remove OWL_ASYMMETRIC_PROPERTY: {property}")
1616
+ delete_characteristic_query = (
1617
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1618
+ f' DELETE {{ ?propertyShape {SHACL_SPARQL} ?constraintNode .'
1619
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1620
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v . FILTER EXISTS {{ ?v <{property}> $this }} }}" }}'
1621
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> . '
1622
+ f' ?propertyShape {SHACL_SPARQL} ?constraintNode . '
1623
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1624
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v . FILTER EXISTS {{ ?v <{property}> $this }} }}" }}'
1625
+ )
1626
+ print(delete_characteristic_query)
1627
+ output_shapes.update(delete_characteristic_query)
1628
+ elif characteristic == URIRef(OWL_REFLEXIVE_PROPERTY_URI):
1629
+ # Reflexive property: custom SHACL-SPARQL constraint
1630
+ delete_characteristic_query = (
1631
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1632
+ f' DELETE {{ ?propertyShape {SHACL_SPARQL} ?constraintNode .'
1633
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1634
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ FILTER NOT EXISTS {{ $this <{property}> $this }} }}" }}'
1635
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> . '
1636
+ f' ?propertyShape {SHACL_SPARQL} ?constraintNode . '
1637
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1638
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ FILTER NOT EXISTS {{ $this <{property}> $this }} }}" }}'
1639
+ )
1640
+ print(delete_characteristic_query)
1641
+ output_shapes.update(delete_characteristic_query)
1642
+ elif characteristic == URIRef(OWL_IRREFLEXIVE_PROPERTY_URI):
1643
+ # Irreflexive property: custom SHACL-SPARQL constraint
1644
+ delete_characteristic_query = (
1645
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1646
+ f' DELETE {{ ?propertyShape {SHACL_SPARQL} ?constraintNode .'
1647
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1648
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> $this }}" }}'
1649
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> . '
1650
+ f' ?propertyShape {SHACL_SPARQL} ?constraintNode . '
1651
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1652
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> $this }}" }}'
1653
+ )
1654
+ print(delete_characteristic_query)
1655
+ output_shapes.update(delete_characteristic_query)
1656
+ elif characteristic == URIRef(OWL_INVERSE_FUNCTIONAL_PROPERTY_URI):
1657
+ # Inverse functional property: sh:uniqueLang or custom constraint
1658
+ delete_characteristic_query = (
1659
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1660
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1661
+ f' DELETE {{ '
1662
+ f' ?shape a {SHACL_PROPERTY_SHAPE} ; '
1663
+ f' {SHACL_PATH} ?pathbnode . '
1664
+ f' ?pathbnode {SHACL_INVERSE_PATH} <{property}> . '
1665
+ f' ?shape {SHACL_MAX_COUNT} 1 . '
1666
+ f' }} '
1667
+ f' WHERE {{ ?shape a {SHACL_PROPERTY_SHAPE} ; '
1668
+ f' {SHACL_PATH} ?pathbnode . '
1669
+ f' ?pathbnode {SHACL_INVERSE_PATH} <{property}> . '
1670
+ f' ?shape {SHACL_MAX_COUNT} 1 . '
1671
+ f' }}'
1672
+ )
1673
+ print(delete_characteristic_query)
1674
+ output_shapes.update(delete_characteristic_query)
1675
+ elif characteristic == URIRef(OWL_TRANSITIVE_PROPERTY_URI):
1676
+ # Transitive property: custom SHACL-SPARQL constraint
1677
+ delete_characteristic_query = (
1678
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1679
+ f' DELETE {{ ?propertyShape {SHACL_SPARQL} ?constraintNode .'
1680
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1681
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v1 . ?v1 <{property}> ?v2 . FILTER NOT EXISTS {{ $this <{property}> ?v2 }} }}" }}'
1682
+ f' WHERE {{ ?propertyShape {SHACL_PATH} <{property}> . '
1683
+ f' ?propertyShape {SHACL_SPARQL} ?constraintNode . '
1684
+ f' ?constraintNode a {SHACL_SPARQL_CONSTRAINT} ; '
1685
+ f' {SHACL_SPARQL_SELECT} "SELECT $this WHERE {{ $this <{property}> ?v1 . ?v1 <{property}> ?v2 . FILTER NOT EXISTS {{ $this <{property}> ?v2 }} }}" }}'
1686
+ )
1687
+ print(delete_characteristic_query)
1688
+ output_shapes.update(delete_characteristic_query)
1689
+
1690
+ def add_inverse_property_shacl(change, change_data, output_shapes):
1691
+ """
1692
+ Adds an inverse property relationship to SHACL NodeShapes by inserting a SPARQL constraint that checks for the inverse property.
1693
+ Args:
1694
+ change: The URI of the change, which must be of the type add_inverse_property.
1695
+ change_data: The RDF graph or data source containing information about the change.
1696
+ output_shapes: The collection or graph to be updated with the new SHACL NodeShape including the inverse property restriction.
1697
+ Returns:
1698
+ The output_shapes updated with the data property shape modified.
1699
+ """
1700
+ query = (
1701
+ f' SELECT DISTINCT ?source_prop ?target_prop WHERE {{ '
1702
+ f' <{change}> {OCH_ADD_INVERSE_PROPERTY_SOURCE} ?source_prop . '
1703
+ f' <{change}> {OCH_ADD_INVERSE_PROPERTY_TARGET} ?target_prop . }}'
1704
+ )
1705
+ for result in change_data.query(query):
1706
+ source_prop = result["source_prop"]
1707
+ target_prop = result["target_prop"]
1708
+ insert_inverse_property_query = (
1709
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1710
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1711
+ f' INSERT {{ '
1712
+ f' ?shapesource {SHACL_PATH} <{source_prop}> ; '
1713
+ f' {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} """ SELECT ?this WHERE {{ ?sub <{source_prop}> ?obj . FILTER NOT EXISTS {{ ?obj <{target_prop}> ?sub . }} }} """ ; ] . '
1714
+ f' ?shapetarget {SHACL_PATH} <{target_prop}> ; '
1715
+ f' {SHACL_SPARQL} [ a {SHACL_SPARQL_CONSTRAINT} ; {SHACL_SPARQL_SELECT} """ SELECT ?this WHERE {{ ?sub <{target_prop}> ?obj . FILTER NOT EXISTS {{ ?obj <{source_prop}> ?sub . }} }} """ ; ] . '
1716
+ f' }} WHERE {{ '
1717
+ f' ?shapesource {SHACL_PATH} <{source_prop}> . '
1718
+ f' ?shapetarget {SHACL_PATH} <{target_prop}> . '
1719
+ f' }}'
1720
+ )
1721
+ print(insert_inverse_property_query)
1722
+ output_shapes.update(insert_inverse_property_query)
1723
+
1724
+ def remove_inverse_property_shacl(change, change_data, output_shapes):
1725
+ """
1726
+ Removes an inverse property relationship from SHACL NodeShapes by deleting the SPARQL constraint that checks for the inverse property.
1727
+ Args:
1728
+ change: The URI of the change, which must be of the type add_inverse_property.
1729
+ change_data: The RDF graph or data source containing information about the change.
1730
+ output_shapes: The collection or graph to be updated without the new SHACL NodeShape including the inverse property restriction.
1731
+ Returns:
1732
+ The output_shapes updated with the data property shape modified.
1733
+ """
1734
+ query = (
1735
+ f' SELECT DISTINCT ?source_prop ?target_prop WHERE {{ '
1736
+ f' <{change}> {OCH_REMOVE_INVERSE_PROPERTY_SOURCE} ?source_prop . '
1737
+ f' <{change}> {OCH_REMOVE_INVERSE_PROPERTY_TARGET} ?target_prop . }}'
1738
+ )
1739
+ for result in change_data.query(query):
1740
+ source_prop = result["source_prop"]
1741
+ target_prop = result["target_prop"]
1742
+ remove_inverse_property_query = (
1743
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1744
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1745
+ f' DELETE {{ '
1746
+ f' ?shapesource {SHACL_SPARQL} ?constraintSource . '
1747
+ f' ?constraintSource a {SHACL_SPARQL_CONSTRAINT} ; '
1748
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?sub <{source_prop}> ?obj . FILTER NOT EXISTS {{ ?obj <{target_prop}> ?sub . }} }} " . '
1749
+ f' ?shapetarget {SHACL_SPARQL} ?constraintTarget . '
1750
+ f' ?constraintTarget a {SHACL_SPARQL_CONSTRAINT} ; '
1751
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?sub <{target_prop}> ?obj . FILTER NOT EXISTS {{ ?obj <{source_prop}> ?sub . }} }} " . '
1752
+ f' }} WHERE {{ '
1753
+ f' ?shapesource {SHACL_PATH} <{source_prop}> ; '
1754
+ f' {SHACL_SPARQL} ?constraintSource . '
1755
+ f' ?constraintSource a {SHACL_SPARQL_CONSTRAINT} ; '
1756
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?sub <{source_prop}> ?obj . FILTER NOT EXISTS {{ ?obj <{target_prop}> ?sub . }} }} " . '
1757
+ f' ?shapetarget {SHACL_PATH} <{target_prop}> ; '
1758
+ f' {SHACL_SPARQL} ?constraintTarget . '
1759
+ f' ?constraintTarget a {SHACL_SPARQL_CONSTRAINT} ; '
1760
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?sub <{target_prop}> ?obj . FILTER NOT EXISTS {{ ?obj <{source_prop}> ?sub . }} }} " . '
1761
+ f' }}'
1762
+ )
1763
+ print(remove_inverse_property_query)
1764
+ output_shapes.update(remove_inverse_property_query)
1765
+
1766
+ def add_disjoint_property_shacl(change, change_data, output_shapes):
1767
+ """
1768
+ Adds a disjoint property restriction to the SHACL NodeShape via SHACL-SPARQL query.
1769
+ Args:
1770
+ change: the URI of the change which needs to be of the type add_disjoint_property
1771
+ Returns:
1772
+ The output_shapes updated with the constraints that enforce the disjointness of the properties.
1773
+ """
1774
+ query = (
1775
+ f' SELECT DISTINCT ?source_property ?target_property WHERE {{ '
1776
+ f' <{change}> {OCH_ADD_DISJOINT_PROPERTY_SOURCE} ?source_property. '
1777
+ f' <{change}> {OCH_ADD_DISJOINT_PROPERTY_TARGET} ?target_property. }}'
1778
+ )
1779
+ for result in change_data.query(query):
1780
+ source_prop = result["source_property"]
1781
+ target_prop = result["target_property"]
1782
+ add_disjoint_property_query = (
1783
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1784
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1785
+ f' INSERT {{ '
1786
+ f' ?shapesource {SHACL_DISJOINT} <{target_prop}> . '
1787
+ f' ?shapetarget {SHACL_DISJOINT} <{source_prop}> . '
1788
+ f' }} WHERE {{ '
1789
+ f' ?shapesource {SHACL_PATH} <{source_prop}> . '
1790
+ f' ?shapetarget {SHACL_PATH} <{target_prop}> . '
1791
+ f' }}'
1792
+ )
1793
+ print(add_disjoint_property_query)
1794
+ output_shapes.update(add_disjoint_property_query)
1795
+
1796
+ def remove_disjoint_property_shacl(change, change_data, output_shapes):
1797
+ """
1798
+ Removes a disjoint property restriction from the SHACL NodeShape via SHACL-SPARQL query.
1799
+ Args:
1800
+ change: the URI of the change which needs to be of the type remove_disjoint_property
1801
+ Returns:
1802
+ The output_shapes updated without the constraints that enforce the disjointness of the properties.
1803
+ """
1804
+ query = (
1805
+ f' SELECT DISTINCT ?source_property ?target_property WHERE {{ '
1806
+ f' <{change}> {OCH_REMOVE_DISJOINT_PROPERTY_SOURCE} ?source_property. '
1807
+ f' <{change}> {OCH_REMOVE_DISJOINT_PROPERTY_TARGET} ?target_property. }}'
1808
+ )
1809
+ for result in change_data.query(query):
1810
+ source_prop = result["source_property"]
1811
+ target_prop = result["target_property"]
1812
+ remove_disjoint_property_query = (
1813
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1814
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1815
+ f' DELETE {{ '
1816
+ f' ?shapesource {SHACL_DISJOINT} <{target_prop}> . '
1817
+ f' ?shapetarget {SHACL_DISJOINT} <{source_prop}> . '
1818
+ f' }} WHERE {{ '
1819
+ f' ?shapesource {SHACL_PATH} <{source_prop}> . '
1820
+ f' ?shapetarget {SHACL_PATH} <{target_prop}> . '
1821
+ f' ?shapesource {SHACL_DISJOINT} <{target_prop}> . '
1822
+ f' ?shapetarget {SHACL_DISJOINT} <{source_prop}> . '
1823
+ f' }}'
1824
+ )
1825
+ print(remove_disjoint_property_query)
1826
+ output_shapes.update(remove_disjoint_property_query)
1827
+
1828
+ def add_superproperty_shacl(change, change_data, output_shapes):
1829
+ """
1830
+ Adds a subproperty relationship to SHACL NodeShapes by inserting a SPARQL constraint that checks for the subproperty.
1831
+ Args:
1832
+ change: The URI of the change, which must be of the type add_subproperty.
1833
+ change_data: The RDF graph or data source containing information about the change.
1834
+ output_shapes: The collection or graph to be updated with the new SHACL NodeShape including the subproperty restriction.
1835
+ Returns:
1836
+ The output_shapes updated with the data property shape modified.
1837
+ """
1838
+ query = (
1839
+ f' SELECT DISTINCT ?sub_property ?super_property WHERE {{ '
1840
+ f' <{change}> {OCH_ADD_SUBPROPERTY_SOURCE} ?sub_property . '
1841
+ f' <{change}> {OCH_ADD_SUBPROPERTY_TARGET} ?super_property . }}'
1842
+ )
1843
+ for result in change_data.query(query):
1844
+ sub_property = result["sub_property"]
1845
+ super_property = result["super_property"]
1846
+ insert_subproperty_query = (
1847
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1848
+ f' PREFIX {EXAMPLE_PREFIX}: <{EXAMPLE_URI}>'
1849
+ f' INSERT {{ '
1850
+ f' ?shapesub {SHACL_SPARQL} [ '
1851
+ f' a {SHACL_SPARQL_CONSTRAINT} ; '
1852
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?this <{sub_property}> ?v . FILTER NOT EXISTS {{ ?this <{super_property}> ?v }} }} " ; ] . '
1853
+ f' }} WHERE {{ '
1854
+ f' ?shapesub {SHACL_PATH} <{sub_property}> . '
1855
+ f' }}'
1856
+ )
1857
+ print(insert_subproperty_query)
1858
+ output_shapes.update(insert_subproperty_query)
1859
+
1860
+ def remove_superproperty_shacl(change, change_data, output_shapes):
1861
+ """
1862
+ Removes a subproperty relationship to SHACL NodeShapes by inserting a SPARQL constraint that checks for the subproperty.
1863
+ Args:
1864
+ change: The URI of the change, which must be of the type add_subproperty.
1865
+ change_data: The RDF graph or data source containing information about the change.
1866
+ output_shapes: The collection or graph to be updated with the new SHACL NodeShape including the subproperty restriction.
1867
+ Returns:
1868
+ The output_shapes updated with the data property shape modified.
1869
+ """
1870
+ query = (
1871
+ f' SELECT DISTINCT ?sub_property ?super_property WHERE {{ '
1872
+ f' <{change}> {OCH_REMOVE_SUBPROPERTY_SOURCE} ?sub_property . '
1873
+ f' <{change}> {OCH_REMOVE_SUBPROPERTY_TARGET} ?super_property . }}'
1874
+ )
1875
+ for result in change_data.query(query):
1876
+ sub_property = result["sub_property"]
1877
+ super_property = result["super_property"]
1878
+ remove_subproperty_query = (
1879
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1880
+ f' DELETE {{ '
1881
+ f' ?shapesub {SHACL_SPARQL} ?sparqlrestriction . '
1882
+ f' ?sparqlrestriction a {SHACL_SPARQL_CONSTRAINT} ; '
1883
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?this <{sub_property}> ?v . FILTER NOT EXISTS {{ ?this <{super_property}> ?v }} }} " ; '
1884
+ f' }} WHERE {{ '
1885
+ f' ?shapesub {SHACL_PATH} <{sub_property}> . '
1886
+ f' ?shapesub {SHACL_SPARQL} ?sparqlrestriction . '
1887
+ f' ?sparqlrestriction a {SHACL_SPARQL_CONSTRAINT} ; '
1888
+ f' {SHACL_SPARQL_SELECT} "SELECT ?this WHERE {{ ?this <{sub_property}> ?v . FILTER NOT EXISTS {{ ?this <{super_property}> ?v }} }} " ; '
1889
+ f' }}'
1890
+ )
1891
+ print(remove_subproperty_query)
1892
+ output_shapes.update(remove_subproperty_query)
1893
+
1894
+ def add_equivalent_property_shacl(change, change_data, output_shapes):
1895
+ """
1896
+ Adds a sh:equals constraint to the property shapes involved in the relationship .
1897
+ Args:
1898
+ change: The URI of the change, which must be of the type add_subproperty.
1899
+ change_data: The RDF graph or data source containing information about the change.
1900
+ output_shapes: The collection or graph to be updated with the new SHACL NodeShape including the subproperty restriction.
1901
+ Returns:
1902
+ The output_shapes updated with the data property shape modified.
1903
+ """
1904
+ query = (
1905
+ f' SELECT DISTINCT ?source_property ?target_property WHERE {{ '
1906
+ f' <{change}> {OCH_ADD_EQUIVALENT_PROPERTY_SOURCE} ?source_property . '
1907
+ f' <{change}> {OCH_ADD_EQUIVALENT_PROPERTY_TARGET} ?target_property . }}'
1908
+ )
1909
+ for result in change_data.query(query):
1910
+ source_property = result["source_property"]
1911
+ target_property = result["target_property"]
1912
+ insert_subproperty_query = (
1913
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1914
+ f' INSERT {{ '
1915
+ f' ?shape_source {SHACL_EQUALS} <{target_property}> . '
1916
+ f' ?shape_target {SHACL_EQUALS} <{source_property}> . '
1917
+ f' }} WHERE {{ '
1918
+ f' ?shape_source {SHACL_PATH} <{source_property}> . '
1919
+ f' ?shape_target {SHACL_PATH} <{target_property}> . '
1920
+ f' }}'
1921
+ )
1922
+ print(insert_subproperty_query)
1923
+ output_shapes.update(insert_subproperty_query)
1924
+
1925
+ def remove_equivalent_property_shacl(change, change_data, output_shapes):
1926
+ """
1927
+ Removes a sh:equals constraint from the property shapes involved in the relationship.
1928
+ Args:
1929
+ change: The URI of the change, which must be of the type add_subproperty.
1930
+ change_data: The RDF graph or data source containing information about the change.
1931
+ output_shapes: The collection or graph to be updated with the new SHACL NodeShape including the subproperty restriction.
1932
+ Returns:
1933
+ The output_shapes updated with the data property shape modified.
1934
+ """
1935
+ query = (
1936
+ f' SELECT DISTINCT ?source_property ?target_property WHERE {{ '
1937
+ f' <{change}> {OCH_REMOVE_EQUIVALENT_PROPERTY_SOURCE} ?source_property . '
1938
+ f' <{change}> {OCH_REMOVE_EQUIVALENT_PROPERTY_TARGET} ?target_property . }}'
1939
+ )
1940
+ for result in change_data.query(query):
1941
+ source_property = result["source_property"]
1942
+ target_property = result["target_property"]
1943
+ remove_subproperty_query = (
1944
+ f' PREFIX {SHACL_PREFIX}: <{SHACL_URI}>'
1945
+ f' DELETE {{ '
1946
+ f' ?shape_source {SHACL_EQUALS} <{target_property}> . '
1947
+ f' ?shape_target {SHACL_EQUALS} <{source_property}> . '
1948
+ f' }} WHERE {{ '
1949
+ f' ?shape_source {SHACL_PATH} <{source_property}> ; '
1950
+ f' {SHACL_EQUALS} <{target_property}> . '
1951
+ f' ?shape_target {SHACL_PATH} <{target_property}> ; '
1952
+ f' {SHACL_EQUALS} <{source_property}> . '
1953
+ f' }}'
1954
+ )
1955
+ print(remove_subproperty_query)
1956
+ output_shapes.update(remove_subproperty_query)