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          12x           25x   25x   25x     25x       472056x 472056x       15810x   15810x       15810x   15810x       14735x           472056x 472056x 472056x   472056x 212688x     259368x   59179x   13248x 45931x   13x   59179x     13412x 13412x 13412x     1195x 1195x 1195x     1203x 1203x 1203x           9149x   9149x       3x     3x       472056x 472056x 472056x   472056x 212688x     259368x   59179x   193x 58986x   3x   59179x     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;
            }
        }
    }
}