UNPKG

sparqljson-parse

Version:
171 lines 7.52 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SparqlJsonParser = void 0; const rdf_data_factory_1 = require("rdf-data-factory"); const readable_stream_1 = require("readable-stream"); // tslint:disable-next-line:no-var-requires const JsonParser = require('@bergos/jsonparse'); /** * Parser for the SPARQL 1.1 Query Results JSON format. * @see https://www.w3.org/TR/sparql11-results-json/ */ class SparqlJsonParser { constructor(settings) { var _a; settings = settings || {}; this.dataFactory = settings.dataFactory || new rdf_data_factory_1.DataFactory(); this.prefixVariableQuestionMark = !!settings.prefixVariableQuestionMark; this.suppressMissingStreamResultsError = (_a = settings.suppressMissingStreamResultsError) !== null && _a !== void 0 ? _a : true; } /** * Convert a SPARQL JSON bindings response to an array of bindings objects. * @param sparqlResponse A SPARQL JSON response. * @return {IBindings[]} An array of bindings. */ parseJsonResults(sparqlResponse) { return sparqlResponse.results.bindings.map((rawBindings) => this.parseJsonBindings(rawBindings)); } /** * Convert a SPARQL JSON bindings response stream to a stream of bindings objects. * * The bindings stream will emit a 'variables' event that will contain * the array of variables (as RDF.Variable[]), as defined in the response head. * * @param {NodeJS.ReadableStream} sparqlResponseStream A SPARQL JSON response stream. * @return {NodeJS.ReadableStream} A stream of bindings. */ parseJsonResultsStream(sparqlResponseStream) { const errorListener = (error) => resultStream.emit('error', error); sparqlResponseStream.on('error', errorListener); const jsonParser = new JsonParser(); jsonParser.onError = errorListener; let variablesFound = false; let resultsFound = false; jsonParser.onValue = (value) => { if (jsonParser.key === "vars" && jsonParser.stack.length === 2 && jsonParser.stack[1].key === 'head') { resultStream.emit('variables', value.map((v) => this.dataFactory.variable(v))); variablesFound = true; } else if (jsonParser.key === "results" && jsonParser.stack.length === 1) { resultsFound = true; } else if (typeof jsonParser.key === 'number' && jsonParser.stack.length === 3 && jsonParser.stack[1].key === 'results' && jsonParser.stack[2].key === 'bindings') { try { resultStream.push(this.parseJsonBindings(value)); } catch (error) { resultStream.emit("error", error); } } else if (jsonParser.key === "metadata" && jsonParser.stack.length === 1) { resultStream.emit('metadata', value); } }; const resultStream = sparqlResponseStream .on("end", _ => { if (!resultsFound && !this.suppressMissingStreamResultsError) { resultStream.emit("error", new Error("No valid SPARQL query results were found.")); } else if (!variablesFound) { resultStream.emit('variables', []); } }) .pipe(new readable_stream_1.Transform({ objectMode: true, transform(chunk, encoding, callback) { jsonParser.write(chunk); callback(); } })); return resultStream; } /** * Convert a SPARQL JSON result binding to a bindings object. * @param rawBindings A SPARQL JSON result binding. * @return {IBindings} A bindings object. */ parseJsonBindings(rawBindings) { const bindings = {}; for (const key in rawBindings) { const rawValue = rawBindings[key]; bindings[this.prefixVariableQuestionMark ? ('?' + key) : key] = this.parseJsonValue(rawValue); } return bindings; } /** * Convert a SPARQL JSON result value to an RDF term. * @param rawValue A SPARQL JSON result value * @return {RDF.Term} An RDF term. */ parseJsonValue(rawValue) { let value; switch (rawValue.type) { case 'bnode': value = this.dataFactory.blankNode(rawValue.value); break; case 'literal': if (rawValue['xml:lang']) { const language = rawValue['xml:lang']; const direction = rawValue['its:dir']; value = this.dataFactory.literal(rawValue.value, { language, direction }); } else if (rawValue.datatype) { value = this.dataFactory.literal(rawValue.value, this.dataFactory.namedNode(rawValue.datatype)); } else { value = this.dataFactory.literal(rawValue.value); } break; case 'typed-literal': // Virtuoso uses this non-spec-compliant way of defining typed literals value = this.dataFactory.literal(rawValue.value, this.dataFactory.namedNode(rawValue.datatype)); break; case 'triple': const tripleValue = rawValue.value; if (!tripleValue || !tripleValue.subject || !tripleValue.predicate || !tripleValue.object) { throw new Error('Invalid quoted triple: ' + JSON.stringify(rawValue)); } value = this.dataFactory.quad(this.parseJsonValue(tripleValue.subject), this.parseJsonValue(tripleValue.predicate), this.parseJsonValue(tripleValue.object)); break; default: value = this.dataFactory.namedNode(rawValue.value); break; } return value; } /** * Convert a SPARQL JSON boolean response to a boolean. * This will throw an error if the given reponse was not a valid boolean response. * @param sparqlResponse A SPARQL JSON response. * @return {IBindings[]} An array of bindings. */ parseJsonBoolean(sparqlResponse) { if ('boolean' in sparqlResponse) { return sparqlResponse.boolean; } throw new Error('No valid ASK response was found.'); } /** * Convert a SPARQL JSON boolean response stream to a promise resolving to a boolean. * This will reject if the given reponse was not a valid boolean response. * @param {NodeJS.ReadableStream} sparqlResponseStream A SPARQL JSON response stream. * @return {Promise<boolean>} The response boolean. */ parseJsonBooleanStream(sparqlResponseStream) { return new Promise((resolve, reject) => { const parser = new JsonParser(); parser.onError = reject; parser.onValue = (value) => { if (parser.key === "boolean" && typeof value === 'boolean' && parser.stack.length === 1) { resolve(value); } }; sparqlResponseStream .on('error', reject) .on('data', d => parser.write(d)) .on('end', () => reject(new Error('No valid ASK response was found.'))); }); } } exports.SparqlJsonParser = SparqlJsonParser; //# sourceMappingURL=SparqlJsonParser.js.map