rdflib
Version:
an RDF library for node.js. Suitable for client and server side.
109 lines (100 loc) • 4.39 kB
JavaScript
/* Lists form conversion
*/
// import DataFactory from './factories/extended-term-factory'
// import jsonldParser from './jsonldparser'
// @ts-ignore is this injected?
// @@ Goal: remove this dependency
// import N3Parser from './n3parser'
// import { parseRDFaDOM } from './rdfaparser'
// import RDFParser from './rdfxmlparser'
// import sparqlUpdateParser from './patch-parser'
// import * as Util from './utils-js'
// import BlankNode from './blank-node'
// import NamedNode from './named-node'
import Collection from './collection';
import Statement from './statement';
// import Formula from './formula'
// import { ContentType, TurtleContentType, N3ContentType, RDFXMLContentType, XHTMLContentType, HTMLContentType, SPARQLUpdateContentType, SPARQLUpdateSingleMatchContentType, JSONLDContentType, NQuadsContentType, NQuadsAltContentType } from './types'
// import { Quad } from './tf-types'
import Namespace from './namespace';
const RDF = Namespace('http://www.w3.org/1999/02/22-rdf-syntax-ns#');
/* Replace a given node with another node throughout a given document
*
* we do the predicate as well for complenesss though we don't expect Collections to use it
*/
export function substituteInDoc(store, x, y, doc) {
// console.log(`substituteInDoc put ${x} for ${y} in ${doc}}`)
for (const quad of store.statementsMatching(y, null, null, doc)) {
const newStatement = new Statement(x, quad.predicate, quad.object, doc);
store.remove(quad);
store.add(newStatement);
}
for (const quad of store.statementsMatching(null, y, null, doc)) {
store.remove(quad);
// console.log(` substituteInDoc predicate ${x} in ${quad}}`)
store.add(new Statement(quad.subject, x, quad.object, doc));
}
for (const quad of store.statementsMatching(null, null, y, doc)) {
store.remove(quad);
store.add(new Statement(quad.subject, quad.predicate, x, doc));
}
}
/* Change all lone rdf:nil nodes into empty Collections
*/
export function substituteNillsInDoc(store, doc) {
const x = RDF('nil');
for (const quad of store.statementsMatching(x, null, null, doc)) {
store.remove(quad);
const y = new Collection();
store.add(new Statement(y, quad.predicate, quad.object, doc));
}
for (const quad of store.statementsMatching(null, null, x, doc)) {
if (!quad.predicate.sameTerm(RDF('rest'))) {
// If not a tail
store.remove(quad);
const y = new Collection();
store.add(new Statement(quad.subject, quad.predicate, y, doc));
}
}
}
/**
* Convert lists reified as rdf:first, rest
* Normal method is sync.
* Unfortunately jsdonld is currently written to need to be called async.
* Hence the mess below with executeCallback.
* @param store - The quadstore
* @param doc - The document in which the conversion is done
*/
export function convertFirstRestNil(store, doc // Do whole store?
) {
function preceding(ele, listSoFar, trash) {
const rests = store.statementsMatching(ele, RDF('rest'), null, doc);
if (rests.length !== 1) throw new Error(`Bad list structure: no rest at ${ele}`);
const firsts = store.statementsMatching(ele, RDF('first'), null, doc);
if (firsts.length !== 1) throw new Error(`Bad list structure: rest but ${firsts.length} firsts at ${ele}`);
const value = firsts[0].object;
const total = [value].concat(listSoFar);
// console.log(' List now is: ', total)
const totalTrash = trash.concat(rests).concat(firsts);
const pres = store.statementsMatching(null, RDF('rest'), ele, doc);
if (pres.length === 0) {
// Head of the list
const newList = new Collection(total);
store.remove(totalTrash);
// Replace old list with new list:
substituteInDoc(store, newList, ele, doc);
return;
}
if (pres.length !== 1) throw new Error(`Bad list structure: ${pres.length} pres at ${ele}`);
const pre = pres[0].subject;
if (pre.termType !== 'BlankNode') throw new Error(`Bad list element node ${pre} type: ${pre.termType} `);
preceding(pre, total, totalTrash);
return;
}
substituteNillsInDoc(store, doc); // lone ones only
const tails = store.statementsMatching(null, RDF('rest'), RDF('nil'), doc);
tails.forEach(tail => {
if (tail.subject.termType !== 'BlankNode') throw new Error(`Bad list element node ${tail.subject} type: ${tail.subject.termType} `);
preceding(tail.subject, [], []);
});
}