UNPKG

rdf-stores

Version:

A TypeScript/JavaScript implementation of the RDF/JS store interface with support for quoted triples.

183 lines 8.63 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TermDictionaryQuotedIndexed = void 0; const rdf_data_factory_1 = require("rdf-data-factory"); const RdfStoreIndexNestedMap_1 = require("../index/RdfStoreIndexNestedMap"); const OrderUtils_1 = require("../OrderUtils"); /** * A term dictionary for quoted triples. * * Plain terms are stored in a regular dictionary. * Quoted triples are stored separately using an index, which is backed the same dictionary. * * Finding quoted triples is done through indexed lookups. */ class TermDictionaryQuotedIndexed { constructor(rawTermDictionary, dataFactory = new rdf_data_factory_1.DataFactory()) { this.quotedTriplesDictionary = []; this.features = { quotedTriples: true }; this.plainTermDictionary = rawTermDictionary; const subIndexOpts = { // Not required indexCombinations: [], // Not required indexConstructor: undefined, dictionary: this, dataFactory, }; this.quotedTriplesReverseDictionaries = [ new RdfStoreIndexNestedMap_1.RdfStoreIndexNestedMap(subIndexOpts), new RdfStoreIndexNestedMap_1.RdfStoreIndexNestedMap(subIndexOpts), new RdfStoreIndexNestedMap_1.RdfStoreIndexNestedMap(subIndexOpts), ]; this.dataFactory = dataFactory; } encode(term) { if (term.termType === 'Quad') { return this.encodeQuotedTriple(term, false); } return this.plainTermDictionary.encode(term); } encodeQuotedTriple(quad, optional) { // Only quoted triples are supported if (quad.graph.termType !== 'DefaultGraph') { throw new Error('Encoding of quoted quads outside of the default graph is not allowed'); } // Check if the quad was already encoded const encodedTripleOptional = (0, OrderUtils_1.encodeOptionalTerms)([quad.subject, quad.predicate, quad.object, quad.graph], this); const id = encodedTripleOptional && encodedTripleOptional.every(encoded => encoded !== undefined) ? this.quotedTriplesReverseDictionaries[0].getEncoded(encodedTripleOptional) : undefined; // Return the encoding if we found one if (id !== undefined || optional) { // Mask MSB to indicate that the encoding should refer to the quoted triples dictionary. return (id === undefined ? undefined : TermDictionaryQuotedIndexed.BITMASK | id); } // If the quad was not encoded yet, add a new entry for it in the dictionary. const encodedTriple = [ this.encode(quad.subject), this.encode(quad.predicate), this.encode(quad.object), ]; const encodingBase = this.quotedTriplesDictionary.length + 1; this.quotedTriplesDictionary.push(encodedTriple); const encodedGraph = this.encode(this.dataFactory.defaultGraph()); this.quotedTriplesReverseDictionaries[0].set([ encodedTriple[0], encodedTriple[1], encodedTriple[2], encodedGraph, ], encodingBase); this.quotedTriplesReverseDictionaries[1].set([ encodedTriple[1], encodedTriple[2], encodedTriple[0], encodedGraph, ], encodingBase); this.quotedTriplesReverseDictionaries[2].set([ encodedTriple[2], encodedTriple[0], encodedTriple[1], encodedGraph, ], encodingBase); // Mask MSB to indicate that the encoding should refer to the quoted triples dictionary. return TermDictionaryQuotedIndexed.BITMASK | encodingBase; } encodeOptional(term) { if (term.termType === 'Quad') { return this.encodeQuotedTriple(term, true); } return this.plainTermDictionary.encodeOptional(term); } decode(encoding) { if (TermDictionaryQuotedIndexed.BITMASK & encoding) { // Term comes from the quoted triples dictionary const encodingBase = (~TermDictionaryQuotedIndexed.BITMASK & encoding) - 1; if (encodingBase >= this.quotedTriplesDictionary.length) { throw new Error(`The value ${encoding} is not present in the quoted triples range of the dictionary`); } const encodedTerms = this.quotedTriplesDictionary[encodingBase]; return this.dataFactory.quad(this.decode(encodedTerms[0]), this.decode(encodedTerms[1]), this.decode(encodedTerms[2])); } // Term comes from the plain terms dictionary return this.plainTermDictionary.decode(encoding); } *encodings() { for (const encoding of this.plainTermDictionary.encodings()) { yield encoding; } for (const encoding of this.quotedTriplesDictionary.keys()) { yield TermDictionaryQuotedIndexed.BITMASK | (1 + encoding); } } *findQuotedTriples(quotedTriplePattern) { for (const termEncoded of this.findQuotedTriplesEncoded(quotedTriplePattern)) { yield this.decode(termEncoded); } } *findQuotedTriplesEncoded(quotedTriplePattern) { const [patternIn, requireQuotedTripleFiltering] = (0, OrderUtils_1.quadToPattern)(quotedTriplePattern.subject, quotedTriplePattern.predicate, quotedTriplePattern.object, quotedTriplePattern.graph, true); // Find all matching terms iteratively for (const termS of this.patternToIterable(patternIn[0])) { for (const termP of this.patternToIterable(patternIn[1])) { for (const termO of this.patternToIterable(patternIn[2])) { for (const termG of this.patternToIterable(patternIn[3])) { // Find all terms matching the pattern from the reverse indexes // We select the reverse index according to the current triple pattern if ((termS && termP) || (!termP && !termO)) { // SPO const pattern = [termS, termP, termO, termG]; for (const termEncoded of this.quotedTriplesReverseDictionaries[0].findEncoded(pattern, patternIn)) { yield TermDictionaryQuotedIndexed.BITMASK | this.quotedTriplesReverseDictionaries[0].getEncoded(termEncoded); } } else if (!termS && termP) { // POS const pattern = [termP, termO, termS, termG]; for (const termEncoded of this.quotedTriplesReverseDictionaries[1].findEncoded(pattern, patternIn)) { yield TermDictionaryQuotedIndexed.BITMASK | this.quotedTriplesReverseDictionaries[1].getEncoded(termEncoded); } } else { // OSP const pattern = [termO, termS, termP, termG]; for (const termEncoded of this.quotedTriplesReverseDictionaries[2].findEncoded(pattern, patternIn)) { yield TermDictionaryQuotedIndexed.BITMASK | this.quotedTriplesReverseDictionaries[2].getEncoded(termEncoded); } } } } } } } /** * Helper function to convert a term to an iterator over encoded terms. * @param patternTerm A term. * @protected */ *patternToIterable(patternTerm) { // If the term is another quoted quad, recursively find other quoted triples if (patternTerm?.termType === 'Quad') { yield* this.findQuotedTriplesEncoded(patternTerm); return; } // Undefined terms indicate a variable if (patternTerm === undefined) { // eslint-disable-next-line unicorn/no-useless-undefined yield undefined; return; } // Defined terms indicate a precise match const enc = this.encodeOptional(patternTerm); if (enc === undefined) { return; } yield enc; } } exports.TermDictionaryQuotedIndexed = TermDictionaryQuotedIndexed; TermDictionaryQuotedIndexed.BITMASK = 1 << 31; //# sourceMappingURL=TermDictionaryQuotedIndexed.js.map