@skaterqiang/protege-js 0.1.0

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.
Files changed (92) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +48 -0
  3. package/README.md +287 -0
  4. package/docs/API.md +654 -0
  5. package/docs/design/OWL2-/347/274/272/345/217/243/345/210/206/346/236/220.md +140 -0
  6. package/docs/owl2-rl/OWL2-RL-/350/247/204/345/210/231/347/273/206/345/210/231.md +168 -0
  7. package/docs/owl2-rl/owl2-profiles-spec-zh.html +1914 -0
  8. package/docs/owl2-rl/owl2-profiles-spec.html +1916 -0
  9. package/docs/owl2-rl/rl_rules.json +392 -0
  10. package/main.js +46 -0
  11. package/package.json +76 -0
  12. package/sample/README.md +74 -0
  13. package/sample/case1-ecommerce-risk.js +170 -0
  14. package/sample/case10-ecommerce-customer-service.js +454 -0
  15. package/sample/case2-family-swrl.js +147 -0
  16. package/sample/case3-pharma-safety.js +132 -0
  17. package/sample/case4-knowledge-publishing.js +111 -0
  18. package/sample/case5-obda-profiles.js +153 -0
  19. package/sample/case6-medical-ontology.js +152 -0
  20. package/sample/case7-manufacturing-ppr.js +155 -0
  21. package/sample/case8-real-medical-bfo-ogms.js +353 -0
  22. package/sample/case9-real-manufacturing-iao.js +360 -0
  23. package/sample/ontologies/bfo.owl +1715 -0
  24. package/sample/ontologies/iao.owl +8532 -0
  25. package/sample/ontologies/ogms.owl +4320 -0
  26. package/sample/ontologies/ro-core.owl +1010 -0
  27. package/scripts/verify-api.js +53 -0
  28. package/src/index.js +176 -0
  29. package/src/inference/OWL2ProfileReasoners.js +67 -0
  30. package/src/inference/OWL2RLReasoner.js +65 -0
  31. package/src/inference/ReasonerQueries.js +111 -0
  32. package/src/inference/SWRLReasoner.js +409 -0
  33. package/src/inference/TripleStore.js +82 -0
  34. package/src/inference/rdf.js +83 -0
  35. package/src/inference/rules/owl2el.js +33 -0
  36. package/src/inference/rules/owl2ql.js +29 -0
  37. package/src/inference/rules/owl2rl.js +823 -0
  38. package/src/io/FunctionalSyntaxParser.js +399 -0
  39. package/src/io/FunctionalSyntaxWriter.js +180 -0
  40. package/src/io/ManchesterSyntaxParser.js +398 -0
  41. package/src/io/OWLXMLParser.js +356 -0
  42. package/src/io/OntologyLoader.js +125 -0
  43. package/src/io/RDFGraphToOntology.js +702 -0
  44. package/src/io/RDFXMLParser.js +319 -0
  45. package/src/io/RDFXMLWriter.js +196 -0
  46. package/src/io/SWRLParser.js +150 -0
  47. package/src/io/TurtleParser.js +363 -0
  48. package/src/io/TurtleWriter.js +393 -0
  49. package/src/model/IRI.js +62 -0
  50. package/src/model/OWLAxiom.js +507 -0
  51. package/src/model/OWLClassExpression.js +242 -0
  52. package/src/model/OWLEntity.js +142 -0
  53. package/src/model/OWLLiteral.js +30 -0
  54. package/src/model/OWLModelManager.js +106 -0
  55. package/src/model/OWLOntology.js +119 -0
  56. package/src/model/SWRL.js +152 -0
  57. package/src/model/event/OWLModelManagerEvent.js +33 -0
  58. package/src/model/hierarchy/HierarchyProvider.js +214 -0
  59. package/src/profiles/OWL2Profiles.js +185 -0
  60. package/src/server/public/app.js +97 -0
  61. package/src/server/public/index.html +49 -0
  62. package/src/server/webServer.js +138 -0
  63. package/src/validation/GlobalRestrictionsValidator.js +172 -0
  64. package/test/core.test.js +111 -0
  65. package/test/exports-map.test.js +165 -0
  66. package/test/owl2/axioms.test.js +160 -0
  67. package/test/owl2/classExpressions.test.js +99 -0
  68. package/test/owl2/functional-syntax-writer.test.js +65 -0
  69. package/test/owl2/functional.test.js +113 -0
  70. package/test/owl2/global-restrictions.test.js +76 -0
  71. package/test/owl2/longtail.test.js +74 -0
  72. package/test/owl2/manchester-syntax.test.js +100 -0
  73. package/test/owl2/ontology-loader-imports.test.js +62 -0
  74. package/test/owl2/owlxml-parser.test.js +112 -0
  75. package/test/owl2/profile-reasoners.test.js +108 -0
  76. package/test/owl2/profiles.test.js +66 -0
  77. package/test/owl2/rdf-graph-to-ontology.test.js +177 -0
  78. package/test/owl2/rdfxml-punning.test.js +25 -0
  79. package/test/owl2/rdfxml-writer.test.js +55 -0
  80. package/test/owl2/rdfxml.test.js +91 -0
  81. package/test/owl2/reasoner-queries.test.js +58 -0
  82. package/test/owl2/sample-e2e.test.js +195 -0
  83. package/test/owl2/swrl-parser.test.js +60 -0
  84. package/test/owl2/swrl.test.js +131 -0
  85. package/test/owl2/turtle-writer.test.js +84 -0
  86. package/test/owl2/turtle.test.js +124 -0
  87. package/test/owl2rl/cax.test.js +57 -0
  88. package/test/owl2rl/cls.test.js +210 -0
  89. package/test/owl2rl/dt.test.js +72 -0
  90. package/test/owl2rl/eq.test.js +95 -0
  91. package/test/owl2rl/prp.test.js +198 -0
  92. package/test/owl2rl/scm.test.js +203 -0
@@ -0,0 +1,823 @@
1
+ 'use strict';
2
+
3
+ const { NS, P, C, literal } = require('../rdf');
4
+
5
+ // ---------------------------------------------------------------------------
6
+ // Equality rules (eq-*) — 9 rules.
7
+ // Each rule: (store, add, conflict) => void
8
+ // store TripleStore
9
+ // add(s,p,o) derive a new triple (returns true if new)
10
+ // conflict(ruleId, desc) record an inconsistency (consequent false)
11
+ // ---------------------------------------------------------------------------
12
+
13
+ const BUILTIN_ANNOTATION_PROPERTIES = [
14
+ NS.RDFS + 'label', NS.RDFS + 'comment', NS.RDFS + 'seeAlso', NS.RDFS + 'isDefinedBy',
15
+ NS.OWL + 'versionInfo', NS.OWL + 'priorVersion', NS.OWL + 'backwardCompatibleWith',
16
+ NS.OWL + 'incompatibleWith', NS.OWL + 'deprecated'
17
+ ];
18
+
19
+ const BUILTIN_DATATYPES = [
20
+ // Core scalar types
21
+ NS.XSD + 'string', NS.XSD + 'boolean', NS.XSD + 'decimal', NS.XSD + 'integer',
22
+ NS.XSD + 'int', NS.XSD + 'long', NS.XSD + 'short', NS.XSD + 'byte',
23
+ NS.XSD + 'nonNegativeInteger', NS.XSD + 'nonPositiveInteger',
24
+ NS.XSD + 'positiveInteger', NS.XSD + 'negativeInteger',
25
+ NS.XSD + 'unsignedLong', NS.XSD + 'unsignedInt', NS.XSD + 'unsignedShort', NS.XSD + 'unsignedByte',
26
+ NS.XSD + 'float', NS.XSD + 'double', NS.XSD + 'dateTime', NS.XSD + 'dateTimeStamp',
27
+ // Date / time family
28
+ NS.XSD + 'date', NS.XSD + 'time', NS.XSD + 'duration',
29
+ NS.XSD + 'yearMonthDuration', NS.XSD + 'dayTimeDuration',
30
+ NS.XSD + 'gYear', NS.XSD + 'gYearMonth', NS.XSD + 'gMonth', NS.XSD + 'gMonthDay', NS.XSD + 'gDay',
31
+ // String subtypes
32
+ NS.XSD + 'normalizedString', NS.XSD + 'token', NS.XSD + 'language',
33
+ NS.XSD + 'Name', NS.XSD + 'NCName', NS.XSD + 'NMTOKEN',
34
+ // Binary
35
+ NS.XSD + 'hexBinary', NS.XSD + 'base64Binary',
36
+ // IRI-ish
37
+ NS.XSD + 'anyURI',
38
+ // OWL numeric
39
+ NS.OWL + 'real', NS.OWL + 'rational',
40
+ // RDF literals
41
+ NS.RDFS + 'Literal', NS.RDF + 'PlainLiteral', NS.RDF + 'XMLLiteral', NS.RDF + 'HTML',
42
+ NS.RDF + 'langString', NS.RDF + 'JSON'
43
+ ];
44
+
45
+ function sameAsClosure(store) {
46
+ // Build symmetric+transitive sameAs equivalence classes.
47
+ const parent = new Map();
48
+ const find = (x) => {
49
+ if (!parent.has(x)) parent.set(x, x);
50
+ let r = x;
51
+ while (parent.get(r) !== r) r = parent.get(r);
52
+ let c = x;
53
+ while (parent.get(c) !== r) { const n = parent.get(c); parent.set(c, r); c = n; }
54
+ return r;
55
+ };
56
+ const union = (a, b) => { const ra = find(a), rb = find(b); if (ra !== rb) parent.set(ra, rb); };
57
+ for (const [s, , o] of store.match(null, P.sameAs, null)) union(s, o);
58
+ return { find };
59
+ }
60
+
61
+ const rules = {
62
+
63
+ // ---- eq -----------------------------------------------------------------
64
+
65
+ 'eq-ref'(store, add) {
66
+ for (const [s, p, o] of store.all()) {
67
+ add(s, P.sameAs, s);
68
+ if (!p.startsWith('"')) add(p, P.sameAs, p);
69
+ if (!o.startsWith('"')) add(o, P.sameAs, o);
70
+ }
71
+ },
72
+
73
+ 'eq-sym'(store, add) {
74
+ for (const [x, , y] of store.match(null, P.sameAs, null)) add(y, P.sameAs, x);
75
+ },
76
+
77
+ 'eq-trans'(store, add) {
78
+ const { find } = sameAsClosure(store);
79
+ const members = new Map();
80
+ for (const [s] of store.match(null, P.sameAs, null)) {
81
+ const r = find(s);
82
+ if (!members.has(r)) members.set(r, new Set());
83
+ members.get(r).add(s);
84
+ }
85
+ for (const [, , o] of store.match(null, P.sameAs, null)) {
86
+ const r = find(o);
87
+ if (!members.has(r)) members.set(r, new Set());
88
+ members.get(r).add(o);
89
+ }
90
+ for (const set of members.values()) {
91
+ const arr = [...set];
92
+ for (const a of arr) for (const b of arr) if (a !== b) add(a, P.sameAs, b);
93
+ }
94
+ },
95
+
96
+ 'eq-rep-s'(store, add) {
97
+ for (const [s, , sp] of store.match(null, P.sameAs, null)) {
98
+ if (s === sp) continue;
99
+ for (const [, p, o] of store.match(s, null, null)) {
100
+ if (p !== P.sameAs) add(sp, p, o);
101
+ }
102
+ }
103
+ },
104
+
105
+ 'eq-rep-p'(store, add) {
106
+ for (const [p, , pp] of store.match(null, P.sameAs, null)) {
107
+ if (p === pp) continue;
108
+ for (const [s, , o] of store.match(null, p, null)) add(s, pp, o);
109
+ }
110
+ },
111
+
112
+ 'eq-rep-o'(store, add) {
113
+ for (const [o, , op] of store.match(null, P.sameAs, null)) {
114
+ if (o === op) continue;
115
+ for (const [s, p] of store.match(null, null, o)) {
116
+ if (p !== P.sameAs) add(s, p, op);
117
+ }
118
+ }
119
+ },
120
+
121
+ 'eq-diff1'(store, add, conflict) {
122
+ const { find } = sameAsClosure(store);
123
+ for (const [x, , y] of store.match(null, P.differentFrom, null)) {
124
+ if (find(x) === find(y)) conflict('eq-diff1', `${x} sameAs and differentFrom ${y}`);
125
+ }
126
+ },
127
+
128
+ 'eq-diff2'(store, add, conflict) {
129
+ const { find } = sameAsClosure(store);
130
+ for (const x of store.subjects(P.type, C.AllDifferent)) {
131
+ for (const y of store.objects(x, P.members)) {
132
+ const zs = store.listElements(y);
133
+ for (let i = 0; i < zs.length; i++)
134
+ for (let j = i + 1; j < zs.length; j++)
135
+ if (find(zs[i]) === find(zs[j])) conflict('eq-diff2', `${zs[i]} sameAs ${zs[j]} in AllDifferent`);
136
+ }
137
+ }
138
+ },
139
+
140
+ 'eq-diff3'(store, add, conflict) {
141
+ const { find } = sameAsClosure(store);
142
+ for (const x of store.subjects(P.type, C.AllDifferent)) {
143
+ for (const y of store.objects(x, P.distinctMembers)) {
144
+ const zs = store.listElements(y);
145
+ for (let i = 0; i < zs.length; i++)
146
+ for (let j = i + 1; j < zs.length; j++)
147
+ if (find(zs[i]) === find(zs[j])) conflict('eq-diff3', `${zs[i]} sameAs ${zs[j]} in AllDifferent distinctMembers`);
148
+ }
149
+ }
150
+ },
151
+
152
+ // ---- prp ----------------------------------------------------------------
153
+
154
+ 'prp-ap'(store, add) {
155
+ for (const ap of BUILTIN_ANNOTATION_PROPERTIES) add(ap, P.type, C.AnnotationProperty);
156
+ },
157
+
158
+ 'prp-dom'(store, add) {
159
+ for (const [p, , c] of store.match(null, P.domain, null)) {
160
+ for (const [x, , ] of store.match(null, p, null)) add(x, P.type, c);
161
+ }
162
+ },
163
+
164
+ 'prp-rng'(store, add) {
165
+ for (const [p, , c] of store.match(null, P.range, null)) {
166
+ for (const [, , y] of store.match(null, p, null)) {
167
+ if (!y.startsWith('"')) add(y, P.type, c);
168
+ }
169
+ }
170
+ },
171
+
172
+ 'prp-fp'(store, add) {
173
+ for (const p of store.subjects(P.type, C.FunctionalProperty)) {
174
+ const bySubj = new Map();
175
+ for (const [x, , y] of store.match(null, p, null)) {
176
+ if (!bySubj.has(x)) bySubj.set(x, new Set());
177
+ bySubj.get(x).add(y);
178
+ }
179
+ for (const ys of bySubj.values()) {
180
+ const arr = [...ys];
181
+ for (let i = 1; i < arr.length; i++) add(arr[0], P.sameAs, arr[i]);
182
+ }
183
+ }
184
+ },
185
+
186
+ 'prp-ifp'(store, add) {
187
+ for (const p of store.subjects(P.type, C.InverseFunctionalProperty)) {
188
+ const byObj = new Map();
189
+ for (const [x, , y] of store.match(null, p, null)) {
190
+ if (!byObj.has(y)) byObj.set(y, new Set());
191
+ byObj.get(y).add(x);
192
+ }
193
+ for (const xs of byObj.values()) {
194
+ const arr = [...xs];
195
+ for (let i = 1; i < arr.length; i++) add(arr[0], P.sameAs, arr[i]);
196
+ }
197
+ }
198
+ },
199
+
200
+ 'prp-irp'(store, add, conflict) {
201
+ for (const p of store.subjects(P.type, C.IrreflexiveProperty)) {
202
+ for (const [x, , y] of store.match(null, p, null)) {
203
+ if (x === y) conflict('prp-irp', `${x} ${p} itself`);
204
+ }
205
+ }
206
+ },
207
+
208
+ 'prp-symp'(store, add) {
209
+ for (const p of store.subjects(P.type, C.SymmetricProperty)) {
210
+ for (const [x, , y] of store.match(null, p, null)) add(y, p, x);
211
+ }
212
+ },
213
+
214
+ 'prp-asyp'(store, add, conflict) {
215
+ for (const p of store.subjects(P.type, C.AsymmetricProperty)) {
216
+ for (const [x, , y] of store.match(null, p, null)) {
217
+ if (store.has(y, p, x)) conflict('prp-asyp', `${x} ${p} ${y} and reverse`);
218
+ }
219
+ }
220
+ },
221
+
222
+ 'prp-trp'(store, add) {
223
+ for (const p of store.subjects(P.type, C.TransitiveProperty)) {
224
+ // Warshall-style closure along p.
225
+ const edges = store.match(null, p, null).map(([x, , y]) => [x, y]);
226
+ const adj = new Map();
227
+ for (const [x, y] of edges) {
228
+ if (!adj.has(x)) adj.set(x, new Set());
229
+ adj.get(x).add(y);
230
+ }
231
+ for (const [x] of edges) {
232
+ const stack = [...(adj.get(x) || [])];
233
+ const seen = new Set();
234
+ while (stack.length) {
235
+ const y = stack.pop();
236
+ if (seen.has(y)) continue;
237
+ seen.add(y);
238
+ if (y !== x) add(x, p, y);
239
+ for (const z of (adj.get(y) || [])) stack.push(z);
240
+ }
241
+ }
242
+ }
243
+ },
244
+
245
+ 'prp-spo1'(store, add) {
246
+ for (const [p1, , p2] of store.match(null, P.subPropertyOf, null)) {
247
+ for (const [x, , y] of store.match(null, p1, null)) add(x, p2, y);
248
+ }
249
+ },
250
+
251
+ 'prp-spo2'(store, add) {
252
+ for (const [p, , listHead] of store.match(null, P.propertyChainAxiom, null)) {
253
+ const chain = store.listElements(listHead);
254
+ if (!chain.length) continue;
255
+ // Find all paths u1 -p1-> u2 -p2-> ... -> un+1
256
+ const extend = (node, idx) => {
257
+ if (idx === chain.length) return [[node]];
258
+ const out = [];
259
+ for (const [, , next] of store.match(node, chain[idx], null)) {
260
+ for (const rest of extend(next, idx + 1)) out.push([node, ...rest]);
261
+ }
262
+ return out;
263
+ };
264
+ // Collect distinct start nodes.
265
+ const starts = new Set(store.match(null, chain[0], null).map(t => t[0]));
266
+ for (const u1 of starts) {
267
+ for (const path of extend(u1, 0)) {
268
+ add(u1, p, path[path.length - 1]);
269
+ }
270
+ }
271
+ }
272
+ },
273
+
274
+ 'prp-eqp1'(store, add) {
275
+ for (const [p1, , p2] of store.match(null, P.equivalentProperty, null)) {
276
+ for (const [x, , y] of store.match(null, p1, null)) add(x, p2, y);
277
+ }
278
+ },
279
+
280
+ 'prp-eqp2'(store, add) {
281
+ for (const [p1, , p2] of store.match(null, P.equivalentProperty, null)) {
282
+ for (const [x, , y] of store.match(null, p2, null)) add(x, p1, y);
283
+ }
284
+ },
285
+
286
+ 'prp-pdw'(store, add, conflict) {
287
+ for (const [p1, , p2] of store.match(null, P.propertyDisjointWith, null)) {
288
+ const t1 = new Set(store.match(null, p1, null).map(([x, , y]) => x + '' + y));
289
+ for (const [x, , y] of store.match(null, p2, null)) {
290
+ if (t1.has(x + '' + y)) conflict('prp-pdw', `${x} ${p1}/${p2} ${y}`);
291
+ }
292
+ }
293
+ },
294
+
295
+ 'prp-adp'(store, add, conflict) {
296
+ for (const x of store.subjects(P.type, C.AllDisjointProperties)) {
297
+ for (const y of store.objects(x, P.members)) {
298
+ const props = store.listElements(y);
299
+ const seenPair = new Map(); // "u v" -> prop
300
+ for (const p of props) {
301
+ for (const [u, , v] of store.match(null, p, null)) {
302
+ const k = u + '' + v;
303
+ if (seenPair.has(k) && seenPair.get(k) !== p) {
304
+ conflict('prp-adp', `${u} disjoint props on ${v}`);
305
+ }
306
+ seenPair.set(k, p);
307
+ }
308
+ }
309
+ }
310
+ }
311
+ },
312
+
313
+ 'prp-inv1'(store, add) {
314
+ for (const [p1, , p2] of store.match(null, P.inverseOf, null)) {
315
+ for (const [x, , y] of store.match(null, p1, null)) add(y, p2, x);
316
+ }
317
+ },
318
+
319
+ 'prp-inv2'(store, add) {
320
+ for (const [p1, , p2] of store.match(null, P.inverseOf, null)) {
321
+ for (const [x, , y] of store.match(null, p2, null)) add(y, p1, x);
322
+ }
323
+ },
324
+
325
+ 'prp-key'(store, add) {
326
+ for (const [c, , listHead] of store.match(null, P.hasKey, null)) {
327
+ const keys = store.listElements(listHead);
328
+ if (!keys.length) continue;
329
+ const instances = store.subjects(P.type, c);
330
+ const sig = new Map(); // signature -> subject
331
+ for (const x of instances) {
332
+ const vals = keys.map(k => store.objects(x, k).sort().join(','));
333
+ if (vals.some(v => v === '')) continue; // must have all key properties
334
+ const s = vals.join('|');
335
+ if (sig.has(s) && sig.get(s) !== x) add(sig.get(s), P.sameAs, x);
336
+ else sig.set(s, x);
337
+ }
338
+ }
339
+ },
340
+
341
+ 'prp-npa1'(store, add, conflict) {
342
+ for (const x of store.subjects(P.sourceIndividual, null)) {
343
+ const i1 = store.objects(x, P.sourceIndividual)[0];
344
+ const p = store.objects(x, P.assertionProperty)[0];
345
+ const i2 = store.objects(x, P.targetIndividual)[0];
346
+ if (i1 && p && i2 && store.has(i1, p, i2)) {
347
+ conflict('prp-npa1', `negative assertion violated: ${i1} ${p} ${i2}`);
348
+ }
349
+ }
350
+ },
351
+
352
+ 'prp-npa2'(store, add, conflict) {
353
+ for (const x of store.subjects(P.sourceIndividual, null)) {
354
+ const i = store.objects(x, P.sourceIndividual)[0];
355
+ const p = store.objects(x, P.assertionProperty)[0];
356
+ const lt = store.objects(x, P.targetValue)[0];
357
+ if (i && p && lt && store.has(i, p, lt)) {
358
+ conflict('prp-npa2', `negative data assertion violated: ${i} ${p} ${lt}`);
359
+ }
360
+ }
361
+ },
362
+
363
+ // ---- cls ----------------------------------------------------------------
364
+
365
+ 'cls-thing'(store, add) { add(C.Thing, P.type, C.Class); },
366
+
367
+ 'cls-nothing1'(store, add) { add(C.Nothing, P.type, C.Class); },
368
+
369
+ 'cls-nothing2'(store, add, conflict) {
370
+ for (const x of store.subjects(P.type, C.Nothing)) {
371
+ conflict('cls-nothing2', `${x} typed owl:Nothing`);
372
+ }
373
+ },
374
+
375
+ 'cls-int1'(store, add) {
376
+ for (const [c, , listHead] of store.match(null, P.intersectionOf, null)) {
377
+ const cs = store.listElements(listHead);
378
+ if (!cs.length) continue;
379
+ // candidates = subjects typed as the first operand
380
+ for (const y of store.subjects(P.type, cs[0])) {
381
+ if (cs.every(ci => store.has(y, P.type, ci))) add(y, P.type, c);
382
+ }
383
+ }
384
+ },
385
+
386
+ 'cls-int2'(store, add) {
387
+ for (const [c, , listHead] of store.match(null, P.intersectionOf, null)) {
388
+ const cs = store.listElements(listHead);
389
+ for (const y of store.subjects(P.type, c)) {
390
+ for (const ci of cs) add(y, P.type, ci);
391
+ }
392
+ }
393
+ },
394
+
395
+ 'cls-uni'(store, add) {
396
+ for (const [c, , listHead] of store.match(null, P.unionOf, null)) {
397
+ const cs = store.listElements(listHead);
398
+ for (const ci of cs) {
399
+ for (const y of store.subjects(P.type, ci)) add(y, P.type, c);
400
+ }
401
+ }
402
+ },
403
+
404
+ 'cls-com'(store, add, conflict) {
405
+ for (const [c1, , c2] of store.match(null, P.complementOf, null)) {
406
+ const inC1 = new Set(store.subjects(P.type, c1));
407
+ for (const x of store.subjects(P.type, c2)) {
408
+ if (inC1.has(x)) conflict('cls-com', `${x} in ${c1} and complement ${c2}`);
409
+ }
410
+ }
411
+ },
412
+
413
+ 'cls-svf1'(store, add) {
414
+ for (const [x, , y] of store.match(null, P.someValuesFrom, null)) {
415
+ for (const p of store.objects(x, P.onProperty)) {
416
+ for (const [u, , v] of store.match(null, p, null)) {
417
+ if (store.has(v, P.type, y)) add(u, P.type, x);
418
+ }
419
+ }
420
+ }
421
+ },
422
+
423
+ 'cls-svf2'(store, add) {
424
+ for (const [x, , y] of store.match(null, P.someValuesFrom, null)) {
425
+ if (y !== C.Thing) continue;
426
+ for (const p of store.objects(x, P.onProperty)) {
427
+ for (const [u] of store.match(null, p, null)) add(u, P.type, x);
428
+ }
429
+ }
430
+ },
431
+
432
+ 'cls-avf'(store, add) {
433
+ for (const [x, , y] of store.match(null, P.allValuesFrom, null)) {
434
+ for (const p of store.objects(x, P.onProperty)) {
435
+ for (const u of store.subjects(P.type, x)) {
436
+ for (const [, , v] of store.match(u, p, null)) {
437
+ if (!v.startsWith('"')) add(v, P.type, y);
438
+ }
439
+ }
440
+ }
441
+ }
442
+ },
443
+
444
+ 'cls-hv1'(store, add) {
445
+ for (const [x, , y] of store.match(null, P.hasValue, null)) {
446
+ for (const p of store.objects(x, P.onProperty)) {
447
+ for (const u of store.subjects(P.type, x)) add(u, p, y);
448
+ }
449
+ }
450
+ },
451
+
452
+ 'cls-hv2'(store, add) {
453
+ for (const [x, , y] of store.match(null, P.hasValue, null)) {
454
+ for (const p of store.objects(x, P.onProperty)) {
455
+ for (const [u] of store.match(null, p, y)) add(u, P.type, x);
456
+ }
457
+ }
458
+ },
459
+
460
+ 'cls-maxc1'(store, add, conflict) {
461
+ const zero = literal('0', NS.XSD + 'nonNegativeInteger');
462
+ for (const [x, , v] of store.match(null, P.maxCardinality, null)) {
463
+ if (v !== zero) continue;
464
+ for (const p of store.objects(x, P.onProperty)) {
465
+ for (const u of store.subjects(P.type, x)) {
466
+ if (store.match(u, p, null).length) conflict('cls-maxc1', `${u} violates maxCardinality 0 on ${p}`);
467
+ }
468
+ }
469
+ }
470
+ },
471
+
472
+ 'cls-maxc2'(store, add) {
473
+ const one = literal('1', NS.XSD + 'nonNegativeInteger');
474
+ for (const [x, , v] of store.match(null, P.maxCardinality, null)) {
475
+ if (v !== one) continue;
476
+ for (const p of store.objects(x, P.onProperty)) {
477
+ for (const u of store.subjects(P.type, x)) {
478
+ const ys = store.match(u, p, null).map(t => t[2]);
479
+ for (let i = 1; i < ys.length; i++) add(ys[0], P.sameAs, ys[i]);
480
+ }
481
+ }
482
+ }
483
+ },
484
+
485
+ 'cls-maxqc1'(store, add, conflict) {
486
+ const zero = literal('0', NS.XSD + 'nonNegativeInteger');
487
+ for (const [x, , v] of store.match(null, P.maxQualifiedCardinality, null)) {
488
+ if (v !== zero) continue;
489
+ const cs = store.objects(x, P.onClass).filter(c => c !== C.Thing);
490
+ for (const p of store.objects(x, P.onProperty)) {
491
+ for (const u of store.subjects(P.type, x)) {
492
+ for (const [, , y] of store.match(u, p, null)) {
493
+ for (const c of cs) {
494
+ if (store.has(y, P.type, c)) conflict('cls-maxqc1', `${u} violates maxQualifiedCardinality 0`);
495
+ }
496
+ }
497
+ }
498
+ }
499
+ }
500
+ },
501
+
502
+ 'cls-maxqc2'(store, add, conflict) {
503
+ const zero = literal('0', NS.XSD + 'nonNegativeInteger');
504
+ for (const [x, , v] of store.match(null, P.maxQualifiedCardinality, null)) {
505
+ if (v !== zero) continue;
506
+ if (!store.objects(x, P.onClass).includes(C.Thing)) continue;
507
+ for (const p of store.objects(x, P.onProperty)) {
508
+ for (const u of store.subjects(P.type, x)) {
509
+ if (store.match(u, p, null).length) conflict('cls-maxqc2', `${u} violates maxQC 0 on Thing`);
510
+ }
511
+ }
512
+ }
513
+ },
514
+
515
+ 'cls-maxqc3'(store, add) {
516
+ const one = literal('1', NS.XSD + 'nonNegativeInteger');
517
+ for (const [x, , v] of store.match(null, P.maxQualifiedCardinality, null)) {
518
+ if (v !== one) continue;
519
+ const cs = store.objects(x, P.onClass).filter(c => c !== C.Thing);
520
+ for (const p of store.objects(x, P.onProperty)) {
521
+ for (const u of store.subjects(P.type, x)) {
522
+ const ys = store.match(u, p, null).map(t => t[2])
523
+ .filter(y => cs.some(c => store.has(y, P.type, c)));
524
+ for (let i = 1; i < ys.length; i++) add(ys[0], P.sameAs, ys[i]);
525
+ }
526
+ }
527
+ }
528
+ },
529
+
530
+ 'cls-maxqc4'(store, add) {
531
+ const one = literal('1', NS.XSD + 'nonNegativeInteger');
532
+ for (const [x, , v] of store.match(null, P.maxQualifiedCardinality, null)) {
533
+ if (v !== one) continue;
534
+ if (!store.objects(x, P.onClass).includes(C.Thing)) continue;
535
+ for (const p of store.objects(x, P.onProperty)) {
536
+ for (const u of store.subjects(P.type, x)) {
537
+ const ys = store.match(u, p, null).map(t => t[2]);
538
+ for (let i = 1; i < ys.length; i++) add(ys[0], P.sameAs, ys[i]);
539
+ }
540
+ }
541
+ }
542
+ },
543
+
544
+ 'cls-oo'(store, add) {
545
+ for (const [c, , listHead] of store.match(null, P.oneOf, null)) {
546
+ for (const yi of store.listElements(listHead)) add(yi, P.type, c);
547
+ }
548
+ },
549
+
550
+ // ---- cax ----------------------------------------------------------------
551
+
552
+ 'cax-sco'(store, add) {
553
+ for (const [c1, , c2] of store.match(null, P.subClassOf, null)) {
554
+ for (const x of store.subjects(P.type, c1)) add(x, P.type, c2);
555
+ }
556
+ },
557
+
558
+ 'cax-eqc1'(store, add) {
559
+ for (const [c1, , c2] of store.match(null, P.equivalentClass, null)) {
560
+ for (const x of store.subjects(P.type, c1)) add(x, P.type, c2);
561
+ }
562
+ },
563
+
564
+ 'cax-eqc2'(store, add) {
565
+ for (const [c1, , c2] of store.match(null, P.equivalentClass, null)) {
566
+ for (const x of store.subjects(P.type, c2)) add(x, P.type, c1);
567
+ }
568
+ },
569
+
570
+ 'cax-dw'(store, add, conflict) {
571
+ for (const [c1, , c2] of store.match(null, P.disjointWith, null)) {
572
+ const inC1 = new Set(store.subjects(P.type, c1));
573
+ for (const x of store.subjects(P.type, c2)) {
574
+ if (inC1.has(x)) conflict('cax-dw', `${x} in disjoint ${c1} & ${c2}`);
575
+ }
576
+ }
577
+ },
578
+
579
+ 'cax-adc'(store, add, conflict) {
580
+ for (const x of store.subjects(P.type, C.AllDisjointClasses)) {
581
+ for (const y of store.objects(x, P.members)) {
582
+ const cs = store.listElements(y);
583
+ const memberOf = new Map(); // subject -> Set(class)
584
+ for (const ci of cs) {
585
+ for (const z of store.subjects(P.type, ci)) {
586
+ if (!memberOf.has(z)) memberOf.set(z, new Set());
587
+ memberOf.get(z).add(ci);
588
+ }
589
+ }
590
+ for (const [z, set] of memberOf) {
591
+ if (set.size > 1) conflict('cax-adc', `${z} in multiple disjoint classes`);
592
+ }
593
+ }
594
+ }
595
+ },
596
+
597
+ // ---- dt -----------------------------------------------------------------
598
+
599
+ 'dt-type1'(store, add) {
600
+ for (const dt of BUILTIN_DATATYPES) add(dt, P.type, C.Datatype);
601
+ },
602
+
603
+ 'dt-type2'(store, add) {
604
+ for (const [, , o] of store.all()) {
605
+ if (o.startsWith('"')) {
606
+ const m = /\^\^<([^>]+)>$/.exec(o);
607
+ if (m) add(o, P.type, m[1]);
608
+ else add(o, P.type, NS.RDFS + 'Literal');
609
+ }
610
+ }
611
+ },
612
+
613
+ 'dt-eq'(store, add) {
614
+ const byDt = new Map();
615
+ for (const [, , o] of store.all()) {
616
+ if (!o.startsWith('"')) continue;
617
+ if (!byDt.has(o)) byDt.set(o, o);
618
+ }
619
+ // same lexical+datatype -> sameAs (they are identical canonical terms already)
620
+ for (const o of byDt.keys()) add(o, P.sameAs, o);
621
+ },
622
+
623
+ 'dt-diff'(store, add) {
624
+ const lits = new Set();
625
+ for (const [, , o] of store.all()) if (o.startsWith('"')) lits.add(o);
626
+ const arr = [...lits];
627
+ const byDt = new Map();
628
+ for (const o of arr) {
629
+ const m = /\^\^<([^>]+)>$/.exec(o);
630
+ const dt = m ? m[1] : NS.RDFS + 'Literal';
631
+ if (!byDt.has(dt)) byDt.set(dt, []);
632
+ byDt.get(dt).push(o);
633
+ }
634
+ for (const group of byDt.values()) {
635
+ for (let i = 0; i < group.length; i++)
636
+ for (let j = i + 1; j < group.length; j++)
637
+ if (group[i] !== group[j]) { add(group[i], P.differentFrom, group[j]); add(group[j], P.differentFrom, group[i]); }
638
+ }
639
+ },
640
+
641
+ 'dt-not-type'(store, add, conflict) {
642
+ for (const [lt, , dt] of store.match(null, P.type, null)) {
643
+ if (!lt.startsWith('"')) continue;
644
+ const m = /^"((?:[^"\\])*)"\^\^<([^>]+)>$/.exec(lt);
645
+ if (!m) continue;
646
+ const lex = m[1], declared = m[2];
647
+ if (declared !== dt) continue;
648
+ // validate value space for a few numeric datatypes
649
+ if (dt === NS.XSD + 'nonNegativeInteger' && !/^\d+$/.test(lex)) {
650
+ conflict('dt-not-type', `"${lex}" not in value space of nonNegativeInteger`);
651
+ } else if (dt === NS.XSD + 'integer' && !/^-?\d+$/.test(lex)) {
652
+ conflict('dt-not-type', `"${lex}" not an integer`);
653
+ } else if (dt === NS.XSD + 'boolean' && !/^(true|false|0|1)$/.test(lex)) {
654
+ conflict('dt-not-type', `"${lex}" not a boolean`);
655
+ }
656
+ }
657
+ },
658
+
659
+ // ---- scm ----------------------------------------------------------------
660
+
661
+ 'scm-cls'(store, add) {
662
+ for (const c of store.subjects(P.type, C.Class)) {
663
+ add(c, P.subClassOf, c);
664
+ add(c, P.equivalentClass, c);
665
+ add(c, P.subClassOf, C.Thing);
666
+ add(C.Nothing, P.subClassOf, c);
667
+ }
668
+ },
669
+
670
+ 'scm-sco'(store, add) {
671
+ for (const [c1, , c2] of store.match(null, P.subClassOf, null)) {
672
+ for (const [, , c3] of store.match(c2, P.subClassOf, null)) add(c1, P.subClassOf, c3);
673
+ }
674
+ },
675
+
676
+ 'scm-eqc1'(store, add) {
677
+ for (const [c1, , c2] of store.match(null, P.equivalentClass, null)) {
678
+ add(c1, P.subClassOf, c2);
679
+ add(c2, P.subClassOf, c1);
680
+ }
681
+ },
682
+
683
+ 'scm-eqc2'(store, add) {
684
+ for (const [c1, , c2] of store.match(null, P.subClassOf, null)) {
685
+ if (store.has(c2, P.subClassOf, c1)) add(c1, P.equivalentClass, c2);
686
+ }
687
+ },
688
+
689
+ 'scm-op'(store, add) {
690
+ for (const p of store.subjects(P.type, C.ObjectProperty)) {
691
+ add(p, P.subPropertyOf, p);
692
+ add(p, P.equivalentProperty, p);
693
+ }
694
+ },
695
+
696
+ 'scm-dp'(store, add) {
697
+ for (const p of store.subjects(P.type, C.DatatypeProperty)) {
698
+ add(p, P.subPropertyOf, p);
699
+ add(p, P.equivalentProperty, p);
700
+ }
701
+ },
702
+
703
+ 'scm-spo'(store, add) {
704
+ for (const [p1, , p2] of store.match(null, P.subPropertyOf, null)) {
705
+ for (const [, , p3] of store.match(p2, P.subPropertyOf, null)) add(p1, P.subPropertyOf, p3);
706
+ }
707
+ },
708
+
709
+ 'scm-eqp1'(store, add) {
710
+ for (const [p1, , p2] of store.match(null, P.equivalentProperty, null)) {
711
+ add(p1, P.subPropertyOf, p2);
712
+ add(p2, P.subPropertyOf, p1);
713
+ }
714
+ },
715
+
716
+ 'scm-eqp2'(store, add) {
717
+ for (const [p1, , p2] of store.match(null, P.subPropertyOf, null)) {
718
+ if (store.has(p2, P.subPropertyOf, p1)) add(p1, P.equivalentProperty, p2);
719
+ }
720
+ },
721
+
722
+ 'scm-dom1'(store, add) {
723
+ for (const [p, , c1] of store.match(null, P.domain, null)) {
724
+ for (const [, , c2] of store.match(c1, P.subClassOf, null)) add(p, P.domain, c2);
725
+ }
726
+ },
727
+
728
+ 'scm-dom2'(store, add) {
729
+ for (const [p2, , c] of store.match(null, P.domain, null)) {
730
+ for (const [p1] of store.match(null, P.subPropertyOf, p2)) add(p1, P.domain, c);
731
+ }
732
+ },
733
+
734
+ 'scm-rng1'(store, add) {
735
+ for (const [p, , c1] of store.match(null, P.range, null)) {
736
+ for (const [, , c2] of store.match(c1, P.subClassOf, null)) add(p, P.range, c2);
737
+ }
738
+ },
739
+
740
+ 'scm-rng2'(store, add) {
741
+ for (const [p2, , c] of store.match(null, P.range, null)) {
742
+ for (const [p1] of store.match(null, P.subPropertyOf, p2)) add(p1, P.range, c);
743
+ }
744
+ },
745
+
746
+ 'scm-hv'(store, add) {
747
+ const hv = store.match(null, P.hasValue, null);
748
+ for (const [c1, , i] of hv) {
749
+ for (const p1 of store.objects(c1, P.onProperty)) {
750
+ for (const [c2, , i2] of hv) {
751
+ if (c1 === c2 || i !== i2) continue;
752
+ for (const p2 of store.objects(c2, P.onProperty)) {
753
+ if (store.has(p1, P.subPropertyOf, p2)) add(c1, P.subClassOf, c2);
754
+ }
755
+ }
756
+ }
757
+ }
758
+ },
759
+
760
+ 'scm-svf1'(store, add) {
761
+ for (const [c1, , y1] of store.match(null, P.someValuesFrom, null)) {
762
+ for (const p of store.objects(c1, P.onProperty)) {
763
+ for (const [c2, , y2] of store.match(null, P.someValuesFrom, null)) {
764
+ if (c1 === c2) continue;
765
+ if (!store.objects(c2, P.onProperty).includes(p)) continue;
766
+ if (store.has(y1, P.subClassOf, y2)) add(c1, P.subClassOf, c2);
767
+ }
768
+ }
769
+ }
770
+ },
771
+
772
+ 'scm-svf2'(store, add) {
773
+ for (const [c1, , y] of store.match(null, P.someValuesFrom, null)) {
774
+ for (const p1 of store.objects(c1, P.onProperty)) {
775
+ for (const [c2, , y2] of store.match(null, P.someValuesFrom, null)) {
776
+ if (c1 === c2 || y !== y2) continue;
777
+ for (const p2 of store.objects(c2, P.onProperty)) {
778
+ if (store.has(p1, P.subPropertyOf, p2)) add(c1, P.subClassOf, c2);
779
+ }
780
+ }
781
+ }
782
+ }
783
+ },
784
+
785
+ 'scm-avf1'(store, add) {
786
+ for (const [c1, , y1] of store.match(null, P.allValuesFrom, null)) {
787
+ for (const p of store.objects(c1, P.onProperty)) {
788
+ for (const [c2, , y2] of store.match(null, P.allValuesFrom, null)) {
789
+ if (c1 === c2) continue;
790
+ if (!store.objects(c2, P.onProperty).includes(p)) continue;
791
+ if (store.has(y1, P.subClassOf, y2)) add(c1, P.subClassOf, c2);
792
+ }
793
+ }
794
+ }
795
+ },
796
+
797
+ 'scm-avf2'(store, add) {
798
+ for (const [c1, , y] of store.match(null, P.allValuesFrom, null)) {
799
+ for (const p1 of store.objects(c1, P.onProperty)) {
800
+ for (const [c2, , y2] of store.match(null, P.allValuesFrom, null)) {
801
+ if (c1 === c2 || y !== y2) continue;
802
+ for (const p2 of store.objects(c2, P.onProperty)) {
803
+ if (store.has(p1, P.subPropertyOf, p2)) add(c2, P.subClassOf, c1);
804
+ }
805
+ }
806
+ }
807
+ }
808
+ },
809
+
810
+ 'scm-int'(store, add) {
811
+ for (const [c, , listHead] of store.match(null, P.intersectionOf, null)) {
812
+ for (const ci of store.listElements(listHead)) add(c, P.subClassOf, ci);
813
+ }
814
+ },
815
+
816
+ 'scm-uni'(store, add) {
817
+ for (const [c, , listHead] of store.match(null, P.unionOf, null)) {
818
+ for (const ci of store.listElements(listHead)) add(ci, P.subClassOf, c);
819
+ }
820
+ }
821
+ };
822
+
823
+ module.exports = { rules, BUILTIN_ANNOTATION_PROPERTIES, BUILTIN_DATATYPES };