All files / rdf/reasoners skos-reasoner.ts

100% Statements 51/51
100% Branches 27/27
100% Functions 9/9
100% Lines 51/51

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          13x           24x   24x   24x     24x       466394x 466394x       15810x   15810x       15810x   15810x       14527x           466394x 466394x 466394x   466394x 211283x     255111x   58150x   13248x 44902x   13x   58150x     13412x 13412x 13412x     1195x 1195x 1195x     1203x 1203x 1203x           9149x   9149x       3x     3x       466394x 466394x 466394x   466394x 211283x     255111x   58150x   193x 57957x   3x   58150x     9149x 9149x     3x 3x        
import * as rdfjs from "@rdfjs/types";
import { rdf, skos } from "../../ontologies";
import { DefaultInferenceGraphHandler, GraphUriGenerator, ReasonerBase } from "./reasoner";
import { dataFactory } from "../data-factory";
 
const { quad } = dataFactory
 
/**
 * 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();
 
    constructor(targetUriGenerator: GraphUriGenerator = new DefaultInferenceGraphHandler()) {
        super(targetUriGenerator);
    }
 
    applyInference(quad: rdfjs.Quad): void {
        this.inferConceptAxioms(quad);
        this.inferCollectionAxioms(quad);
    }
 
    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: {
                this.assertConcept(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;
            }
        }
    }
}