@oml/owl 0.16.6 → 0.18.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.
- package/out/owl/owl-abox.d.ts +3 -0
- package/out/owl/owl-abox.js +38 -0
- package/out/owl/owl-abox.js.map +1 -1
- package/out/owl/owl-mapper.js +4 -1
- package/out/owl/owl-mapper.js.map +1 -1
- package/out/owl/owl-shacl.d.ts +10 -0
- package/out/owl/owl-shacl.js +238 -36
- package/out/owl/owl-shacl.js.map +1 -1
- package/out/owl/owl-tbox.d.ts +15 -0
- package/out/owl/owl-tbox.js +67 -1
- package/out/owl/owl-tbox.js.map +1 -1
- package/package.json +2 -2
- package/src/owl/owl-abox.ts +43 -1
- package/src/owl/owl-mapper.ts +4 -1
- package/src/owl/owl-shacl.ts +271 -37
- package/src/owl/owl-tbox.ts +73 -1
package/src/owl/owl-tbox.ts
CHANGED
|
@@ -52,6 +52,11 @@ const OML = {
|
|
|
52
52
|
hasTarget: namedNode('http://opencaesar.io/oml#hasTarget'),
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
+
export interface HasValueRestriction {
|
|
56
|
+
property: string;
|
|
57
|
+
value: { kind: 'named'; iri: string } | { kind: 'literal'; value: string; datatype: string; language: string };
|
|
58
|
+
}
|
|
59
|
+
|
|
55
60
|
export interface TBoxIndex {
|
|
56
61
|
superClasses: Map<string, string[]>;
|
|
57
62
|
subProperties: Map<string, string[]>;
|
|
@@ -64,6 +69,7 @@ export interface TBoxIndex {
|
|
|
64
69
|
transitiveProperties: Set<string>;
|
|
65
70
|
functionalProperties: Set<string>;
|
|
66
71
|
inverseFunctionalProperties: Set<string>;
|
|
72
|
+
hasValueRestrictions: Map<string, HasValueRestriction[]>;
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
export interface ForwardRuleDefinition {
|
|
@@ -152,6 +158,42 @@ export class TBoxIndexBuilder {
|
|
|
152
158
|
}
|
|
153
159
|
}
|
|
154
160
|
|
|
161
|
+
// cls-hv1: collect owl:hasValue restrictions from blank node restriction nodes.
|
|
162
|
+
// Pattern: C rdfs:subClassOf _:r, _:r owl:onProperty P, _:r owl:hasValue V
|
|
163
|
+
const bnodeProperty = new Map<string, string>();
|
|
164
|
+
const bnodeValue = new Map<string, HasValueRestriction['value']>();
|
|
165
|
+
const classToRestrictionBnodes = new Map<string, string[]>();
|
|
166
|
+
for (const q of quads) {
|
|
167
|
+
if (q.subject.termType === 'BlankNode') {
|
|
168
|
+
if (q.predicate.value === 'http://www.w3.org/2002/07/owl#onProperty' && q.object.termType === 'NamedNode') {
|
|
169
|
+
bnodeProperty.set(q.subject.value, q.object.value);
|
|
170
|
+
} else if (q.predicate.value === 'http://www.w3.org/2002/07/owl#hasValue') {
|
|
171
|
+
if (q.object.termType === 'NamedNode') {
|
|
172
|
+
bnodeValue.set(q.subject.value, { kind: 'named', iri: q.object.value });
|
|
173
|
+
} else if (q.object.termType === 'Literal') {
|
|
174
|
+
bnodeValue.set(q.subject.value, { kind: 'literal', value: q.object.value, datatype: q.object.datatype?.value ?? '', language: q.object.language ?? '' });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
} else if (q.subject.termType === 'NamedNode' && q.predicate.value === RDFS.subClassOf.value && q.object.termType === 'BlankNode') {
|
|
178
|
+
const list = classToRestrictionBnodes.get(q.subject.value) ?? [];
|
|
179
|
+
list.push(q.object.value);
|
|
180
|
+
classToRestrictionBnodes.set(q.subject.value, list);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
for (const [classIri, bnodeIds] of classToRestrictionBnodes) {
|
|
184
|
+
for (const bnodeId of bnodeIds) {
|
|
185
|
+
const property = bnodeProperty.get(bnodeId);
|
|
186
|
+
const value = bnodeValue.get(bnodeId);
|
|
187
|
+
if (property && value) {
|
|
188
|
+
const list = index.hasValueRestrictions.get(classIri) ?? [];
|
|
189
|
+
if (!list.some((r) => r.property === property && this.sameHasValue(r.value, value))) {
|
|
190
|
+
list.push({ property, value });
|
|
191
|
+
index.hasValueRestrictions.set(classIri, list);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
155
197
|
if (ontology && isVocabulary(ontology)) {
|
|
156
198
|
index.forwardRules.push(...this.buildForwardRules(ontology));
|
|
157
199
|
}
|
|
@@ -189,6 +231,7 @@ export class TBoxIndexBuilder {
|
|
|
189
231
|
this.mergeSet(merged.transitiveProperties, own.transitiveProperties);
|
|
190
232
|
this.mergeSet(merged.functionalProperties, own.functionalProperties);
|
|
191
233
|
this.mergeSet(merged.inverseFunctionalProperties, own.inverseFunctionalProperties);
|
|
234
|
+
this.mergeHasValueRestrictions(merged.hasValueRestrictions, own.hasValueRestrictions);
|
|
192
235
|
}
|
|
193
236
|
|
|
194
237
|
this.closeSuperClassesTransitively(merged.superClasses);
|
|
@@ -224,9 +267,23 @@ export class TBoxIndexBuilder {
|
|
|
224
267
|
transitiveProperties: new Set<string>(),
|
|
225
268
|
functionalProperties: new Set<string>(),
|
|
226
269
|
inverseFunctionalProperties: new Set<string>(),
|
|
270
|
+
hasValueRestrictions: new Map<string, HasValueRestriction[]>(),
|
|
227
271
|
};
|
|
228
272
|
}
|
|
229
273
|
|
|
274
|
+
private sameHasValue(a: HasValueRestriction['value'], b: HasValueRestriction['value']): boolean {
|
|
275
|
+
if (a.kind !== b.kind) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
if (a.kind === 'named' && b.kind === 'named') {
|
|
279
|
+
return a.iri === b.iri;
|
|
280
|
+
}
|
|
281
|
+
if (a.kind === 'literal' && b.kind === 'literal') {
|
|
282
|
+
return a.value === b.value && a.datatype === b.datatype && a.language === b.language;
|
|
283
|
+
}
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
|
|
230
287
|
private mergeStringArrayMap(target: Map<string, string[]>, source: Map<string, string[]>): void {
|
|
231
288
|
for (const [key, values] of source.entries()) {
|
|
232
289
|
const existing = target.get(key) ?? [];
|
|
@@ -245,6 +302,18 @@ export class TBoxIndexBuilder {
|
|
|
245
302
|
}
|
|
246
303
|
}
|
|
247
304
|
|
|
305
|
+
private mergeHasValueRestrictions(target: Map<string, HasValueRestriction[]>, source: Map<string, HasValueRestriction[]>): void {
|
|
306
|
+
for (const [classIri, restrictions] of source.entries()) {
|
|
307
|
+
const existing = target.get(classIri) ?? [];
|
|
308
|
+
for (const r of restrictions) {
|
|
309
|
+
if (!existing.some((e) => e.property === r.property && this.sameHasValue(e.value, r.value))) {
|
|
310
|
+
existing.push(r);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
target.set(classIri, existing);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
248
317
|
private mergeForwardRules(target: ForwardRuleDefinition[], source: ForwardRuleDefinition[]): void {
|
|
249
318
|
const merged = new Map<string, ForwardRuleDefinition>();
|
|
250
319
|
for (const rule of target) {
|
|
@@ -393,7 +462,10 @@ export class TBoxIndexBuilder {
|
|
|
393
462
|
return { kind: 'literal', value: String(literalValue.value), datatype: 'http://www.w3.org/2001/XMLSchema#decimal', language: '' };
|
|
394
463
|
}
|
|
395
464
|
if (isDoubleLiteral(literalValue)) {
|
|
396
|
-
|
|
465
|
+
const v = literalValue.value;
|
|
466
|
+
const doubleStr = typeof v === 'string' ? v
|
|
467
|
+
: Number.isInteger(v as number) ? `${v}.0e0` : `${v}e0`;
|
|
468
|
+
return { kind: 'literal', value: doubleStr, datatype: 'http://www.w3.org/2001/XMLSchema#double', language: '' };
|
|
397
469
|
}
|
|
398
470
|
if (isQuotedLiteral(literalValue)) {
|
|
399
471
|
if (literalValue.type) {
|