Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | 13x 47x 47x 47x 47x 47x 543752x 543752x 122x 122x 13455x 13254x 122x 122x 122x 122x 122x 15666x 15666x 15867x 15867x 17982x 543752x 543752x 543752x 543752x 231105x 312647x 72348x 13286x 59062x 22x 72348x 13455x 13455x 13455x 1199x 1199x 1199x 1213x 1213x 1213x 9171x 9171x 8x 8x 543752x 543752x 543752x 543752x 231105x 312647x 72348x 204x 72144x 6x 72348x 9171x 9171x 8x 8x | import * as rdfjs from "@rdfjs/types";
import { rdf, skos } from "../../ontologies";
import { DefaultInferenceGraphHandler, GraphUriGenerator, ReasonerBase } from "./reasoner";
import { RdfDataFactory } from "../rdf-data-factory";
const { quad } = RdfDataFactory
/**
* A simple SKOS reasoner that expands the graph with inferred triples.
*/
export class SkosReasoner extends ReasonerBase {
protected concepts: Set<string> = new Set();
protected conceptSchemes: Set<string> = new Set();
protected collections: Set<string> = new Set();
/**
* Subjects of `skos:inScheme` triples, keyed by their value. Whether they are concepts can only
* be decided once all triples of the graph were processed, see {@link afterInference}.
*/
private readonly _inSchemeSubjects: Map<string, rdfjs.Quad_Subject> = new Map();
constructor(targetUriGenerator: GraphUriGenerator = new DefaultInferenceGraphHandler()) {
super(targetUriGenerator);
}
applyInference(quad: rdfjs.Quad): void {
this.inferConceptAxioms(quad);
this.inferCollectionAxioms(quad);
}
/**
* Infers the subjects of `skos:inScheme` triples to be concepts, unless they are collections.
* `skos:inScheme` has no domain, and `skos:Collection` is disjoint with `skos:Concept`. The
* type of a collection may be processed after its `skos:inScheme` triple, so this is done after
* all triples of the graph were processed.
*/
protected afterInference(): void {
super.afterInference();
for (let [id, subject] of this._inSchemeSubjects) {
if (!this.collections.has(id)) {
this.assertConcept(subject);
}
}
}
/**
* Clears the state that was collected for the graph, so it does not affect the next graph.
*/
protected resetState(): void {
super.resetState();
this.concepts.clear();
this.conceptSchemes.clear();
this.collections.clear();
this._inSchemeSubjects.clear();
}
protected assertConcept(subject: rdfjs.Quad_Subject) {
this.store.add(quad(subject, rdf.type, skos.Concept, this.targetGraph));
this.concepts.add(subject.value);
}
protected assertConceptScheme(subject: rdfjs.Quad_Subject) {
this.store.add(quad(subject, rdf.type, skos.ConceptScheme, this.targetGraph));
this.conceptSchemes.add(subject.value);
}
protected isClass(id: string): boolean {
return this.concepts.has(id) ||
this.conceptSchemes.has(id) ||
this.collections.has(id);
}
inferConceptAxioms(quad: rdfjs.Quad) {
let s = quad.subject;
let p = quad.predicate;
let o = quad.object.termType != "Literal" ? quad.object : undefined;
if (!o) {
return;
}
switch (p.value) {
case rdf.type.value: {
if (o.equals(skos.Concept)) {
// No need to infer the type, as it is already asserted.
this.concepts.add(s.value);
} else if (o.equals(skos.ConceptScheme)) {
// No need to infer the type, as it is already asserted.
this.conceptSchemes.add(s.value);
}
return;
}
case skos.inScheme.value: {
// The subject may be a collection, so it is only inferred to be a concept after
// all triples were processed.
this._inSchemeSubjects.set(s.value, s);
this.assertConceptScheme(o);
return;
}
case skos.topConceptOf.value: {
this.assertConcept(s);
this.assertConceptScheme(o);
return;
}
case skos.hasTopConcept.value: {
this.assertConcept(o);
this.assertConceptScheme(s);
return;
}
}
}
protected assertCollection(subject: rdfjs.Quad_Subject) {
this.store.add(quad(subject, rdf.type, skos.Collection, this.targetGraph));
this.collections.add(subject.value);
}
protected assertOrderedCollection(subject: rdfjs.Quad_Subject) {
this.store.add(quad(subject, rdf.type, skos.OrderedCollection, this.targetGraph));
// We do not make a distinction between collections and ordered collections here.
this.collections.add(subject.value);
}
inferCollectionAxioms(quad: rdfjs.Quad) {
let s = quad.subject;
let p = quad.predicate;
let o = quad.object.termType != "Literal" ? quad.object : undefined;
if (!o) {
return;
}
switch (p.value) {
case rdf.type.value: {
if (o.equals(skos.Collection)) {
// No need to infer the type, as it is already asserted.
this.collections.add(s.value);
} else if (o.equals(skos.OrderedCollection)) {
// No need to infer the type, as it is already asserted.
this.collections.add(s.value);
}
return;
}
case skos.member.value: {
this.assertCollection(s);
return;
}
case skos.memberList.value: {
this.assertOrderedCollection(s);
return;
}
}
}
} |