UNPKG

@comunica/actor-init-query

Version:
175 lines 7.08 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.VoidMetadataEmitter = void 0; const quad = require('rdf-quad'); /** * A VoID metadata emitter that emits metadata used in VoID description of the HTTP service sparql endpoint. */ class VoidMetadataEmitter { static STRING_LITERALS = new Set([ 'alternative', 'description', 'title', ]); static DATE_LITERALS = new Set([ 'available', 'created', 'date', 'dateAccepted', 'dateCopyrighted', 'dateSubmitted', 'issued', 'modified', 'valid', ]); context; cachedStatistics = []; constructor(context) { this.context = context; } invalidateCache() { this.cachedStatistics = []; } /** * Returns a list of all necessary VoID quads. * @param {QueryEngineBase} engine A SPARQL engine. * @param {module:stream.internal.Writable} stdout * @param {module:http.IncomingMessage} request * @param {module:http.ServerResponse} response */ async getVoIDQuads(engine, stdout, request, response) { const s = request.url; const sd = 'http://www.w3.org/ns/sparql-service-description#'; const vd = 'http://rdfs.org/ns/void#'; const rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; const rdfType = `${rdf}type`; const dataset = '_:defaultDataset'; const graph = '_:defaultGraph'; const vocabulary = `${vd}vocabulary`; const dcterms = 'http://purl.org/dc/terms/'; const quads = [ quad(s, `${sd}defaultDataset`, dataset), quad(dataset, rdfType, `${sd}Dataset`), // Basic VoID metadata quad(dataset, rdfType, `${vd}Dataset`), quad(dataset, `${vd}sparqlEndpoint`, '/sparql'), ]; // Dublin Core Metadata Terms if (this.context.dcterms) { quads.push(quad(dataset, vocabulary, dcterms)); for (const key in this.context.dcterms) { quads.push(quad(dataset, `${dcterms}${key}`, this.convertValue(key, this.context.dcterms[key]))); } } // Statistics // Default graph for statistics quads.push(quad(dataset, `${sd}defaultGraph`, graph)); quads.push(quad(graph, rdfType, `${sd}Graph`)); if (this.cachedStatistics.length === 0) { try { await this.fetchVoIDStatistics(engine); } catch (error) { stdout.write(`[500] Server error in results: ${error.message} \n`); response.end('An internal server error occurred.\n'); return []; } } for (const q of this.cachedStatistics) { quads.push(q); } return quads; } convertValue(key, value) { if (VoidMetadataEmitter.STRING_LITERALS.has(key)) { return `"${value}"`; } if (VoidMetadataEmitter.DATE_LITERALS.has(key)) { return `"${value}"^^http://www.w3.org/2001/XMLSchema#date`; } return value; } /** * Fetches the necessary VoID statistics quads and assigns them to this.cachedStatistics * @param {QueryEngineBase} engine A SPARQL engine. * @private */ async fetchVoIDStatistics(engine) { const vd = 'http://rdfs.org/ns/void#'; const rdf = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'; const rdfType = `${rdf}type`; const dataset = '_:defaultDataset'; const graph = '_:defaultGraph'; const [globalStatistics, classesStatistic, classPartitions, propertyPartitions] = await Promise.all([ engine.queryBindings(` SELECT (COUNT(*) AS ?triples) (SUM(IF(isIRI(?s), 1, 0)) AS ?entities) (COUNT(DISTINCT ?s) AS ?distinctSubjects) (COUNT(DISTINCT ?p) AS ?properties) (COUNT(DISTINCT ?o) AS ?distinctObjects) WHERE { ?s ?p ?o } `, this.context), engine.queryBindings(` SELECT (COUNT(DISTINCT ?c) AS ?classes) WHERE { ?s a ?c } `, this.context), engine.queryBindings(` SELECT ?class (COUNT(*) AS ?count) WHERE { ?s a ?class } GROUP BY ?class `, this.context), engine.queryBindings(` SELECT ?property (COUNT(*) AS ?count) WHERE { ?s ?property ?o } GROUP BY ?property `, this.context), ]); const xsdInteger = (n) => `"${n}"^^http://www.w3.org/2001/XMLSchema#integer`; await Promise.all([ (async () => { for await (const bindings of globalStatistics) { this.cachedStatistics.push(quad(graph, `${vd}triples`, xsdInteger(bindings.get('triples').value))); this.cachedStatistics.push(quad(graph, `${vd}entities`, xsdInteger(bindings.get('entities').value))); this.cachedStatistics.push(quad(graph, `${vd}distinctSubjects`, xsdInteger(bindings.get('distinctSubjects').value))); this.cachedStatistics.push(quad(graph, `${vd}properties`, xsdInteger(bindings.get('properties').value))); this.cachedStatistics.push(quad(graph, `${vd}distinctObjects`, xsdInteger(bindings.get('distinctObjects').value))); } })(), (async () => { for await (const bindings of classesStatistic) { this.cachedStatistics.push(quad(graph, `${vd}classes`, xsdInteger(bindings.get('classes').value))); } })(), (async () => { let i = 0; for await (const bindings of classPartitions) { const classPartition = `_:classPartition${i}`; this.cachedStatistics.push(quad(dataset, `${vd}classPartition`, classPartition)); this.cachedStatistics.push(quad(classPartition, rdfType, `${vd}ClassPartition`)); this.cachedStatistics.push(quad(classPartition, `${vd}class`, bindings.get('class').value)); this.cachedStatistics.push(quad(classPartition, `${vd}entities`, xsdInteger(bindings.get('count').value))); i++; } })(), (async () => { let i = 0; for await (const bindings of propertyPartitions) { const propertyPartition = `_:propertyPartition${i}`; this.cachedStatistics.push(quad(dataset, `${vd}propertyPartition`, propertyPartition)); this.cachedStatistics.push(quad(propertyPartition, rdfType, `${vd}PropertyPartition`)); this.cachedStatistics.push(quad(propertyPartition, `${vd}property`, bindings.get('property').value)); this.cachedStatistics.push(quad(propertyPartition, `${vd}triples`, xsdInteger(bindings.get('count').value))); i++; } })(), ]); } } exports.VoidMetadataEmitter = VoidMetadataEmitter; //# sourceMappingURL=VoidMetadataEmitter.js.map