UNPKG

@rdfc/sparql-ingest-processor-ts

Version:
143 lines (142 loc) 5.95 kB
import { XSD } from "@treecg/types"; import { DataFactory } from "rdf-data-factory"; import { RdfStore } from "rdf-stores"; import { Writer as N3Writer } from "n3"; const df = new DataFactory(); export function getSubjects(store, predicate, object, graph) { return store.getQuads(null, predicate, object, graph).map((quad) => { return quad.subject; }); } export function getObjects(store, subject, predicate, graph) { return store.getQuads(subject, predicate, null, graph).map((quad) => { return quad.object; }); } export function splitStorePerNamedGraph(store) { const stores = []; const namedGraphs = new Set(); store.getQuads(null, null, null, null) .forEach(q => namedGraphs.add(q.graph)); namedGraphs.forEach(ng => { const subStore = RdfStore.createDefault(); const quads = store.getQuads(null, null, null, ng); quads.forEach(q => subStore.addQuad(q)); stores.push({ graph: ng, store: subStore }); }); return stores; } export function splitStoreOnSize(store, threshold) { const stores = []; if (store.size < threshold) { stores.push(store); } else { const quads = store.getQuads(); const bnSet = new Set(); let subStore = RdfStore.createDefault(); for (let i = 0; i < quads.length; i++) { if (bnSet.has(`${quads[i].subject.value}${quads[i].predicate.value}${quads[i].object.value}${quads[i].graph.value}`)) { continue; } if (subStore.size >= threshold) { stores.push(subStore); subStore = RdfStore.createDefault(); } if (quads[i].subject.termType === "BlankNode") { const subjectQuads = store.getQuads(quads[i].subject); const objectQuads = store.getQuads(null, null, quads[i].subject); [...subjectQuads, ...objectQuads].forEach((q) => { subStore.addQuad(q); bnSet.add(`${q.subject.value}${q.predicate.value}${q.object.value}${q.graph.value}`); }); } if (quads[i].object.termType === "BlankNode") { const subjectQuads = store.getQuads(quads[i].object); const objectQuads = store.getQuads(null, null, quads[i].object); [...subjectQuads, ...objectQuads].forEach((q) => { subStore.addQuad(q); bnSet.add(`${q.subject.value}${q.predicate.value}${q.object.value}${q.graph.value}`); }); } subStore.addQuad(quads[i]); } stores.push(subStore); } return stores; } export function sanitizeQuads(store) { for (const q of store.getQuads()) { if (q.object.termType === "Literal" && q.object.datatype.value === XSD.integer) { if (/\+\d+/.test(q.object.value) && q.object.value.startsWith("+")) { store.removeQuad(q); store.addQuad(df.quad(q.subject, q.predicate, df.literal(q.object.value.substring(1), df.namedNode(XSD.integer)), q.graph)); } } } } export async function doSPARQLRequest(query, config, dispatcher, logger) { try { const timeout = config.measurePerformance?.queryTimeout || 1800; if (query.length > 0 && typeof query[0] !== 'string') { const quads = query; let hasQuads = config.targetNamedGraph !== undefined; if (quads.some(q => !q.graph.equals(df.defaultGraph()))) { hasQuads = true; } const writer = new N3Writer({ format: hasQuads ? "N-Quads" : "N-Triples" }); const serialized = writer.quadsToString(quads); const url = new URL(config.graphStoreUrl); if (config.accessToken) { url.searchParams.append("access-token", config.accessToken); } logger.verbose(`[doSPARQLRequest] Executing SPARQL Graph Store request (POST) with ${quads.length} quads.`); logger.debug(`[doSPARQLRequest] POSTing the following RDF quads:\n${serialized}`); const res = await fetch(url.toString(), { method: "POST", headers: { 'Content-Type': hasQuads ? 'application/n-quads' : 'application/n-triples', }, body: serialized, dispatcher, }); if (!res.ok) { throw new Error(`HTTP request failed with code ${res.status} and message: \n${await res.text()}`); } await res.text(); return; } let queries = []; const jointQuery = query.join(";\n"); if (config.forVirtuoso && Buffer.byteLength(jointQuery, 'utf8') > 1e6) { queries = query; } else { queries.push(jointQuery); } for (const q of queries) { logger.debug(`[doSPARQLRequest] Executing SPARQL query: \n${q}`); const res = await fetch(config.graphStoreUrl, { method: "POST", headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', }, body: `update=${fixedEncodeURIComponent(q)}${config.accessToken ? `&access-token=${config.accessToken}` : ''}`, dispatcher, }); if (!res.ok) { throw new Error(`HTTP request failed with code ${res.status} and message: \n${await res.text()}`); } await res.text(); } } catch (err) { logger.error(`Error while executing SPARQL request: ${err.message} - ${err.cause}`); throw err; } } function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { return '%' + c.charCodeAt(0).toString(16); }); }