@faubulous/mentor-rdf 2.6.0 → 2.6.1
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/dist/index.js +228 -71
- package/dist/index.js.map +2 -2
- package/dist/rdf/resource-repository.d.ts +69 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -480,6 +480,163 @@ var ResourceRepository = class {
|
|
|
480
480
|
}
|
|
481
481
|
return primary;
|
|
482
482
|
}
|
|
483
|
+
/**
|
|
484
|
+
* Get the hierarchy relations of a predicate such as `rdfs:subClassOf`, read in a single pass.
|
|
485
|
+
* @param graphUris URIs of the graphs to search, `undefined` for the default graph.
|
|
486
|
+
* @param predicate The hierarchy predicate, e.g. `rdfs:subClassOf` or `rdfs:subPropertyOf`.
|
|
487
|
+
* @param options Optional query parameters.
|
|
488
|
+
* @returns A map from a node, named or blank, to its named parents, excluding the node itself.
|
|
489
|
+
*/
|
|
490
|
+
getParentMap(graphUris, predicate, options) {
|
|
491
|
+
const result = /* @__PURE__ */ new Map();
|
|
492
|
+
for (let q of this.store.matchAll(graphUris, null, predicate, null, options?.includeInferred)) {
|
|
493
|
+
if (q.subject.termType != "NamedNode" && q.subject.termType != "BlankNode" || q.object.termType != "NamedNode" || q.subject.value == q.object.value) {
|
|
494
|
+
continue;
|
|
495
|
+
}
|
|
496
|
+
const parents = result.get(q.subject.value);
|
|
497
|
+
if (!parents) {
|
|
498
|
+
result.set(q.subject.value, [q.object.value]);
|
|
499
|
+
} else if (!parents.includes(q.object.value)) {
|
|
500
|
+
parents.push(q.object.value);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return result;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Get the root nodes of a hierarchy such as the class or the property hierarchy. A member with no
|
|
507
|
+
* visible parent is a root. A parent that is not one of the document's own nodes is referenced:
|
|
508
|
+
* the roots are then the top nodes of its chains of parents, as far as the graphs state them.
|
|
509
|
+
* @param members The nodes whose roots are wanted, e.g. the classes of the document.
|
|
510
|
+
* @param parents The parents of every node, see {@link getParentMap}.
|
|
511
|
+
* @param isOwn Whether a node belongs to the document; a chain that reaches one has no top of its own.
|
|
512
|
+
* @param isVisible Whether a parent is shown in the hierarchy at all.
|
|
513
|
+
* @param canBeRoot Whether a node is listed as a root, be it a member without visible parents or the top of a referenced chain.
|
|
514
|
+
* @returns An iterator of the root nodes.
|
|
515
|
+
*/
|
|
516
|
+
*getHierarchyRoots(members, parents, isOwn, isVisible, canBeRoot = () => true) {
|
|
517
|
+
const yielded = /* @__PURE__ */ new Set();
|
|
518
|
+
const getVisibleParents = (iri) => (parents.get(iri) ?? []).filter(isVisible);
|
|
519
|
+
const finished = /* @__PURE__ */ new Set();
|
|
520
|
+
for (let m of members) {
|
|
521
|
+
let hasParent = false;
|
|
522
|
+
for (let p of getVisibleParents(m)) {
|
|
523
|
+
hasParent = true;
|
|
524
|
+
if (!isOwn(p)) {
|
|
525
|
+
for (let r of this._getTopNodes(p, getVisibleParents, isOwn, finished, /* @__PURE__ */ new Set())) {
|
|
526
|
+
if (!yielded.has(r) && canBeRoot(r)) {
|
|
527
|
+
yielded.add(r);
|
|
528
|
+
yield r;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
if (!hasParent && !yielded.has(m) && canBeRoot(m)) {
|
|
534
|
+
yielded.add(m);
|
|
535
|
+
yield m;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
/**
|
|
540
|
+
* Get the top nodes of the chains of parents of a referenced node.
|
|
541
|
+
* @param iri URI of a referenced node.
|
|
542
|
+
* @param getParents A function returning the visible parents of a node.
|
|
543
|
+
* @param isOwn Whether a node belongs to the document; a chain that reaches one has no top of its own.
|
|
544
|
+
* @param finished The referenced nodes whose top nodes were already yielded.
|
|
545
|
+
* @param path The nodes on the current chain, to stop at cycles.
|
|
546
|
+
* @returns An iterator of the top nodes not yielded for another chain before.
|
|
547
|
+
*/
|
|
548
|
+
*_getTopNodes(iri, getParents, isOwn, finished, path) {
|
|
549
|
+
if (finished.has(iri)) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
path.add(iri);
|
|
553
|
+
let isTop = true;
|
|
554
|
+
for (let p of getParents(iri)) {
|
|
555
|
+
if (isOwn(p) || finished.has(p)) {
|
|
556
|
+
isTop = false;
|
|
557
|
+
} else if (!path.has(p)) {
|
|
558
|
+
isTop = false;
|
|
559
|
+
yield* this._getTopNodes(p, getParents, isOwn, finished, path);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
path.delete(iri);
|
|
563
|
+
finished.add(iri);
|
|
564
|
+
if (isTop) {
|
|
565
|
+
yield iri;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Indicate if a node is only referenced by the document: it is included if referenced terms
|
|
570
|
+
* are included, and it is not defined by another ontology of the document. Annotations or a
|
|
571
|
+
* declaration of a term from another vocabulary do not define it.
|
|
572
|
+
* @param graphUris URIs of the graphs to search, `undefined` for the default graph.
|
|
573
|
+
* @param node A node.
|
|
574
|
+
* @param options Optional query parameters.
|
|
575
|
+
* @param ontologies The other ontologies in the graphs, see {@link getOtherOntologiesOnce}.
|
|
576
|
+
* @returns `true` if the node is a referenced named node, `false` otherwise.
|
|
577
|
+
*/
|
|
578
|
+
isReferenced(graphUris, node, options, ontologies) {
|
|
579
|
+
if (!(options?.includeReferenced ?? false) || node.termType != "NamedNode") {
|
|
580
|
+
return false;
|
|
581
|
+
}
|
|
582
|
+
return !ontologies().some((o) => this.isDefinedBy(graphUris, node, o));
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Indicate if a node is a referenced term with one of the document's own terms below it in a
|
|
586
|
+
* hierarchy, so that the hierarchy from a referenced root down to the document is not broken.
|
|
587
|
+
* @param graphUris URIs of the graphs to search, `undefined` for the default graph.
|
|
588
|
+
* @param node A node.
|
|
589
|
+
* @param predicate The hierarchy predicate, e.g. `rdfs:subClassOf` or `rdfs:subPropertyOf`.
|
|
590
|
+
* @param options Optional query parameters.
|
|
591
|
+
* @param ontologies The other ontologies in the graphs, see {@link getOtherOntologiesOnce}.
|
|
592
|
+
* @param visited The nodes already visited, to stop at cycles.
|
|
593
|
+
* @returns `true` if a term of the document is a direct or indirect child of the node.
|
|
594
|
+
*/
|
|
595
|
+
isReferencedAbove(graphUris, node, predicate, options, ontologies, visited = /* @__PURE__ */ new Set()) {
|
|
596
|
+
if (!this.isReferenced(graphUris, node, options, ontologies)) {
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
visited.add(node.value);
|
|
600
|
+
for (let q of this.store.matchAll(graphUris, null, predicate, node, options?.includeInferred)) {
|
|
601
|
+
if (visited.has(q.subject.value)) {
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
if (!this.skip(graphUris, q.subject, options) || this.isReferencedAbove(graphUris, q.subject, predicate, options, ontologies, visited)) {
|
|
605
|
+
return true;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Get an accessor for the other ontologies in the graphs that queries them on its first call
|
|
612
|
+
* only, as most queries never need them.
|
|
613
|
+
* @param graphUris URIs of the graphs to search, `undefined` for the default graph.
|
|
614
|
+
* @param options Optional query parameters.
|
|
615
|
+
* @returns A function returning the URIs of the other ontologies, see {@link _getOtherOntologies}.
|
|
616
|
+
*/
|
|
617
|
+
getOtherOntologiesOnce(graphUris, options) {
|
|
618
|
+
let ontologies;
|
|
619
|
+
return () => ontologies ?? (ontologies = this._getOtherOntologies(graphUris, options));
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Get the ontologies declared in the graphs other than the one the options select with `definedBy`.
|
|
623
|
+
* @param graphUris URIs of the graphs to search, `undefined` for the default graph.
|
|
624
|
+
* @param options Optional query parameters.
|
|
625
|
+
* @returns The URIs of the other ontologies, or none if the options select no ontology.
|
|
626
|
+
*/
|
|
627
|
+
_getOtherOntologies(graphUris, options) {
|
|
628
|
+
if (!options?.definedBy) {
|
|
629
|
+
return [];
|
|
630
|
+
}
|
|
631
|
+
const definedBy = Uri.getNormalizedUri(options.definedBy);
|
|
632
|
+
const result = /* @__PURE__ */ new Set();
|
|
633
|
+
for (let q of this.store.matchAll(graphUris, null, rdf.type, owl.Ontology, false)) {
|
|
634
|
+
if (q.subject.termType == "NamedNode" && Uri.getNormalizedUri(q.subject.value) != definedBy) {
|
|
635
|
+
result.add(q.subject.value);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return [...result];
|
|
639
|
+
}
|
|
483
640
|
};
|
|
484
641
|
|
|
485
642
|
// src/rdf/concept-repository.ts
|
|
@@ -1403,8 +1560,9 @@ var ClassRepository = class extends ConceptRepository {
|
|
|
1403
1560
|
*/
|
|
1404
1561
|
hasSubClasses(graphUris, subjectUri, options) {
|
|
1405
1562
|
const o = namedNode2(subjectUri);
|
|
1563
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
1406
1564
|
for (let q of this.store.matchAll(graphUris, null, rdfs.subClassOf, o)) {
|
|
1407
|
-
if (!this.skip(graphUris, q.subject, options)) {
|
|
1565
|
+
if (!this.skip(graphUris, q.subject, options) || this.isReferencedAbove(graphUris, q.subject, rdfs.subClassOf, options, ontologies)) {
|
|
1408
1566
|
return true;
|
|
1409
1567
|
}
|
|
1410
1568
|
}
|
|
@@ -1419,8 +1577,12 @@ var ClassRepository = class extends ConceptRepository {
|
|
|
1419
1577
|
if (subjectUri) {
|
|
1420
1578
|
const yielded = /* @__PURE__ */ new Set();
|
|
1421
1579
|
const o = namedNode2(subjectUri);
|
|
1580
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
1422
1581
|
for (let q of this.store.matchAll(graphUris, null, rdfs.subClassOf, o, options?.includeInferred)) {
|
|
1423
|
-
if (
|
|
1582
|
+
if (yielded.has(q.subject.value)) {
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1585
|
+
if (!this.skip(graphUris, q.subject, options) || this.isReferencedAbove(graphUris, q.subject, rdfs.subClassOf, options, ontologies)) {
|
|
1424
1586
|
yielded.add(q.subject.value);
|
|
1425
1587
|
yield q.subject.value;
|
|
1426
1588
|
}
|
|
@@ -1601,28 +1763,23 @@ var ClassRepository = class extends ConceptRepository {
|
|
|
1601
1763
|
* @returns An iterator of root classes in the repository.
|
|
1602
1764
|
*/
|
|
1603
1765
|
*getRootClasses(graphUris, options) {
|
|
1604
|
-
const yielded = /* @__PURE__ */ new Set();
|
|
1605
1766
|
const classes = new Set(this.getClasses(graphUris, options));
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
continue;
|
|
1613
|
-
}
|
|
1614
|
-
hasSuperClass = q.object.value != q.subject.value;
|
|
1615
|
-
if (!classes.has(q.object.value) && !yielded.has(q.object.value)) {
|
|
1616
|
-
yielded.add(q.object.value);
|
|
1617
|
-
yield q.object.value;
|
|
1618
|
-
}
|
|
1619
|
-
break;
|
|
1767
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
1768
|
+
const superClasses = this.getParentMap(graphUris, rdfs.subClassOf, options);
|
|
1769
|
+
const visible = /* @__PURE__ */ new Map();
|
|
1770
|
+
const isVisible = (iri) => {
|
|
1771
|
+
if (classes.has(iri)) {
|
|
1772
|
+
return true;
|
|
1620
1773
|
}
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1774
|
+
let result = visible.get(iri);
|
|
1775
|
+
if (result === void 0) {
|
|
1776
|
+
const node = namedNode2(iri);
|
|
1777
|
+
result = !this.skip(graphUris, node, options) || this.isReferenced(graphUris, node, options, ontologies);
|
|
1778
|
+
visible.set(iri, result);
|
|
1624
1779
|
}
|
|
1625
|
-
|
|
1780
|
+
return result;
|
|
1781
|
+
};
|
|
1782
|
+
yield* this.getHierarchyRoots(classes, superClasses, (iri) => classes.has(iri), isVisible);
|
|
1626
1783
|
}
|
|
1627
1784
|
/**
|
|
1628
1785
|
* Indicate if there is an equivalent class of a given class.
|
|
@@ -1888,38 +2045,41 @@ var PropertyRepository = class extends ClassRepository {
|
|
|
1888
2045
|
* @returns An iterator of properties of the given type.
|
|
1889
2046
|
*/
|
|
1890
2047
|
*getRootPropertiesOfType(graphUris, typeUri, options) {
|
|
1891
|
-
const
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
2048
|
+
const members = /* @__PURE__ */ new Map();
|
|
2049
|
+
for (let q of this.store.matchAll(graphUris, null, rdf.type, namedNode3(typeUri), options?.includeInferred)) {
|
|
2050
|
+
if (!this.skip(graphUris, q.subject, options)) {
|
|
2051
|
+
members.set(q.subject.value, q.subject);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
2055
|
+
const superProperties = this.getParentMap(graphUris, rdfs.subPropertyOf, options);
|
|
2056
|
+
const referenced = /* @__PURE__ */ new Map();
|
|
2057
|
+
const own = /* @__PURE__ */ new Map();
|
|
2058
|
+
const isReferenced = (iri) => {
|
|
2059
|
+
let result = referenced.get(iri);
|
|
2060
|
+
if (result === void 0) {
|
|
2061
|
+
const node = namedNode3(iri);
|
|
2062
|
+
if (!(options?.includeReferenced ?? false)) {
|
|
2063
|
+
result = false;
|
|
2064
|
+
} else if (options?.definedBy) {
|
|
2065
|
+
result = this.skip(graphUris, node, options) && this.isReferenced(graphUris, node, options, ontologies);
|
|
2066
|
+
} else {
|
|
2067
|
+
result = !this.hasSubject(graphUris, iri);
|
|
1904
2068
|
}
|
|
1905
|
-
|
|
1906
|
-
break;
|
|
2069
|
+
referenced.set(iri, result);
|
|
1907
2070
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
if (
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
if (typeUri === RDF.Property && this._hasSpecificType(graphUris, q.subject)) {
|
|
1916
|
-
continue;
|
|
1917
|
-
}
|
|
1918
|
-
if (!yielded.has(q.subject.value)) {
|
|
1919
|
-
yielded.add(q.subject.value);
|
|
1920
|
-
yield q.subject.value;
|
|
2071
|
+
return result;
|
|
2072
|
+
};
|
|
2073
|
+
const isOwn = (iri) => {
|
|
2074
|
+
let result = own.get(iri);
|
|
2075
|
+
if (result === void 0) {
|
|
2076
|
+
result = !isReferenced(iri) && !this.skip(graphUris, namedNode3(iri), options);
|
|
2077
|
+
own.set(iri, result);
|
|
1921
2078
|
}
|
|
1922
|
-
|
|
2079
|
+
return result;
|
|
2080
|
+
};
|
|
2081
|
+
const canBeRoot = (iri) => typeUri !== RDF.Property || !this._hasSpecificType(graphUris, members.get(iri) ?? namedNode3(iri));
|
|
2082
|
+
yield* this.getHierarchyRoots(members.keys(), superProperties, isOwn, (iri) => isOwn(iri) || isReferenced(iri), canBeRoot);
|
|
1923
2083
|
}
|
|
1924
2084
|
/**
|
|
1925
2085
|
* Indicate whether a property is stated to be of a type that is more specific than rdf:Property.
|
|
@@ -1999,8 +2159,9 @@ var PropertyRepository = class extends ClassRepository {
|
|
|
1999
2159
|
*/
|
|
2000
2160
|
hasSubProperties(graphUris, subjectUri, options) {
|
|
2001
2161
|
const o = namedNode3(subjectUri);
|
|
2162
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
2002
2163
|
for (let q of this.store.matchAll(graphUris, null, rdfs.subPropertyOf, o, options?.includeInferred)) {
|
|
2003
|
-
if (!this.skip(graphUris, q.subject, options)) {
|
|
2164
|
+
if (!this.skip(graphUris, q.subject, options) || this.isReferencedAbove(graphUris, q.subject, rdfs.subPropertyOf, options, ontologies)) {
|
|
2004
2165
|
return true;
|
|
2005
2166
|
}
|
|
2006
2167
|
}
|
|
@@ -2016,8 +2177,9 @@ var PropertyRepository = class extends ClassRepository {
|
|
|
2016
2177
|
if (subjectUri) {
|
|
2017
2178
|
const yielded = /* @__PURE__ */ new Set();
|
|
2018
2179
|
const o = namedNode3(subjectUri);
|
|
2180
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
2019
2181
|
for (let q of this.store.matchAll(graphUris, null, rdfs.subPropertyOf, o, options?.includeInferred)) {
|
|
2020
|
-
if (this.skip(graphUris, q.subject, options)) {
|
|
2182
|
+
if (this.skip(graphUris, q.subject, options) && !this.isReferencedAbove(graphUris, q.subject, rdfs.subPropertyOf, options, ontologies)) {
|
|
2021
2183
|
continue;
|
|
2022
2184
|
}
|
|
2023
2185
|
if (!yielded.has(q.subject.value)) {
|
|
@@ -2035,28 +2197,23 @@ var PropertyRepository = class extends ClassRepository {
|
|
|
2035
2197
|
* @returns An iterator of root properties in the repository.
|
|
2036
2198
|
*/
|
|
2037
2199
|
*getRootProperties(graphUris, options) {
|
|
2038
|
-
const yielded = /* @__PURE__ */ new Set();
|
|
2039
2200
|
const properties = new Set(this.getProperties(graphUris, options));
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
continue;
|
|
2047
|
-
}
|
|
2048
|
-
hasSuperProperty = q.object.value != q.subject.value;
|
|
2049
|
-
if (!properties.has(q.object.value) && !yielded.has(q.object.value)) {
|
|
2050
|
-
yielded.add(q.object.value);
|
|
2051
|
-
yield q.object.value;
|
|
2052
|
-
}
|
|
2053
|
-
break;
|
|
2201
|
+
const ontologies = this.getOtherOntologiesOnce(graphUris, options);
|
|
2202
|
+
const superProperties = this.getParentMap(graphUris, rdfs.subPropertyOf, options);
|
|
2203
|
+
const visible = /* @__PURE__ */ new Map();
|
|
2204
|
+
const isVisible = (iri) => {
|
|
2205
|
+
if (properties.has(iri)) {
|
|
2206
|
+
return true;
|
|
2054
2207
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2208
|
+
let result = visible.get(iri);
|
|
2209
|
+
if (result === void 0) {
|
|
2210
|
+
const node = namedNode3(iri);
|
|
2211
|
+
result = !this.skip(graphUris, node, options) || this.isReferenced(graphUris, node, options, ontologies);
|
|
2212
|
+
visible.set(iri, result);
|
|
2058
2213
|
}
|
|
2059
|
-
|
|
2214
|
+
return result;
|
|
2215
|
+
};
|
|
2216
|
+
yield* this.getHierarchyRoots(properties, superProperties, (iri) => properties.has(iri), isVisible);
|
|
2060
2217
|
}
|
|
2061
2218
|
/**
|
|
2062
2219
|
* Indicate if there is an equivalent property of a given property.
|