Comparing version 1.2.1 to 1.3.0
@@ -12,2 +12,4 @@ "use strict"; | ||
var _IRIs = _interopRequireDefault(require("./IRIs")); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -389,3 +391,2 @@ | ||
match(subject, predicate, object, graph) { | ||
var self = this; | ||
var stream = new _stream.Readable({ | ||
@@ -395,11 +396,5 @@ objectMode: true | ||
stream._read = function () { | ||
stream._read = function () {}; | ||
stream._read = () => { | ||
for (var quad of this.getQuads(subject, predicate, object, graph)) stream.push(quad); | ||
var quads = self.getQuads(subject, predicate, object, graph); | ||
for (var quad of quads) { | ||
stream.push(quad); | ||
} | ||
stream.push(null); | ||
@@ -692,2 +687,83 @@ }; | ||
return this._factory.blankNode(name.substr(2)); | ||
} // ### `extractLists` finds and removes all list triples | ||
// and returns the items per list. | ||
extractLists({ | ||
remove = false, | ||
ignoreErrors = false | ||
} = {}) { | ||
var lists = {}; // has scalar keys so could be a simple Object | ||
var onError = ignoreErrors ? () => true : (node, message) => { | ||
throw new Error(`${node.value} ${message}`); | ||
}; // Traverse each list from its tail | ||
var tails = this.getQuads(null, _IRIs.default.rdf.rest, _IRIs.default.rdf.nil, null); | ||
var toRemove = remove ? [...tails] : []; | ||
tails.forEach(tailQuad => { | ||
var items = []; // the members found as objects of rdf:first quads | ||
var malformed = false; // signals whether the current list is malformed | ||
var head; // the head of the list (_:b1 in above example) | ||
var headPos; // set to subject or object when head is set | ||
var graph = tailQuad.graph; // make sure list is in exactly one graph | ||
// Traverse the list from tail to end | ||
var current = tailQuad.subject; | ||
while (current && !malformed) { | ||
var objectQuads = this.getQuads(null, null, current, null); | ||
var subjectQuads = this.getQuads(current, null, null, null); | ||
var i, | ||
quad, | ||
first = null, | ||
rest = null, | ||
parent = null; // Find the first and rest of this list node | ||
for (i = 0; i < subjectQuads.length && !malformed; i++) { | ||
quad = subjectQuads[i]; | ||
if (!quad.graph.equals(graph)) malformed = onError(current, 'not confined to single graph');else if (head) malformed = onError(current, 'has non-list arcs out'); // one rdf:first | ||
else if (quad.predicate.value === _IRIs.default.rdf.first) { | ||
if (first) malformed = onError(current, 'has multiple rdf:first arcs');else toRemove.push(first = quad); | ||
} // one rdf:rest | ||
else if (quad.predicate.value === _IRIs.default.rdf.rest) { | ||
if (rest) malformed = onError(current, 'has multiple rdf:rest arcs');else toRemove.push(rest = quad); | ||
} // alien triple | ||
else if (objectQuads.length) malformed = onError(current, 'can\'t be subject and object');else { | ||
head = quad; // e.g. { (1 2 3) :p :o } | ||
headPos = 'subject'; | ||
} | ||
} // { :s :p (1 2) } arrives here with no head | ||
// { (1 2) :p :o } arrives here with head set to the list. | ||
for (i = 0; i < objectQuads.length && !malformed; ++i) { | ||
quad = objectQuads[i]; | ||
if (head) malformed = onError(current, 'can\'t have coreferences'); // one rdf:rest | ||
else if (quad.predicate.value === _IRIs.default.rdf.rest) { | ||
if (parent) malformed = onError(current, 'has incoming rdf:rest arcs');else parent = quad; | ||
} else { | ||
head = quad; // e.g. { :s :p (1 2) } | ||
headPos = 'object'; | ||
} | ||
} // Store the list item and continue with parent | ||
if (!first) malformed = onError(current, 'has no list head');else items.unshift(first.object); | ||
current = parent && parent.subject; | ||
} // Don't remove any quads if the list is malformed | ||
if (malformed) remove = false; // Store the list under the value of its head | ||
else if (head) lists[head[headPos].value] = items; | ||
}); // Remove list quads if requested | ||
if (remove) this.removeQuads(toRemove); | ||
return lists; | ||
} | ||
@@ -694,0 +770,0 @@ |
@@ -50,3 +50,4 @@ "use strict"; | ||
if (outputStream && typeof outputStream.write !== 'function') options = outputStream, outputStream = null; | ||
options = options || {}; // If no output stream given, send the output as string through the end callback | ||
options = options || {}; | ||
this._lists = options.lists; // If no output stream given, send the output as string through the end callback | ||
@@ -141,4 +142,9 @@ if (!outputStream) { | ||
// A blank node or list is represented as-is | ||
if (entity.termType !== 'NamedNode') return 'id' in entity ? entity.id : '_:' + entity.value; // Escape special characters | ||
if (entity.termType !== 'NamedNode') { | ||
// If it is a list head, pretty-print it | ||
if (this._lists && entity.value in this._lists) entity = this.list(this._lists[entity.value]); | ||
return 'id' in entity ? entity.id : '_:' + entity.value; | ||
} // Escape special characters | ||
var iri = entity.value; | ||
@@ -198,3 +204,2 @@ if (escape.test(iri)) iri = iri.replace(escapeAll, characterReplacer); // Try to represent the IRI as prefixed name | ||
addPrefixes(prefixes, done) { | ||
// Add all useful prefixes | ||
var prefixIRIs = this._prefixIRIs, | ||
@@ -204,19 +209,16 @@ hasPrefixes = false; | ||
for (var prefix in prefixes) { | ||
// Verify whether the prefix can be used and does not exist yet | ||
var iri = prefixes[prefix]; | ||
if (typeof iri !== 'string') iri = iri.value; | ||
hasPrefixes = true; // Finish a possible pending quad | ||
if (/[#\/]$/.test(iri) && prefixIRIs[iri] !== (prefix += ':')) { | ||
hasPrefixes = true; | ||
prefixIRIs[iri] = prefix; // Finish a possible pending quad | ||
if (this._subject !== null) { | ||
this._write(this._inDefaultGraph ? '.\n' : '\n}\n'); | ||
if (this._subject !== null) { | ||
this._write(this._inDefaultGraph ? '.\n' : '\n}\n'); | ||
this._subject = null, this._graph = ''; | ||
} // Store and write the prefix | ||
this._subject = null, this._graph = ''; | ||
} // Write prefix | ||
prefixIRIs[iri] = prefix += ':'; | ||
this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); | ||
} | ||
this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); | ||
} // Recreate the prefix matcher | ||
@@ -223,0 +225,0 @@ |
{ | ||
"name": "n3", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.", | ||
@@ -5,0 +5,0 @@ "author": "Ruben Verborgh <ruben.verborgh@gmail.com>", |
// **N3Store** objects store N3 quads by graph in memory. | ||
import N3DataFactory from './N3DataFactory'; | ||
import { Readable } from 'stream'; | ||
import namespaces from './IRIs'; | ||
@@ -379,12 +380,8 @@ const { toId, fromId } = N3DataFactory.internal; | ||
match(subject, predicate, object, graph) { | ||
var self = this; | ||
var stream = new Readable({ objectMode: true }); | ||
// Initialize stream once it is being read | ||
stream._read = function () { | ||
stream._read = function () {}; | ||
var quads = self.getQuads(subject, predicate, object, graph); | ||
for (var quad of quads) { | ||
stream._read = () => { | ||
for (var quad of this.getQuads(subject, predicate, object, graph)) | ||
stream.push(quad); | ||
} | ||
stream.push(null); | ||
@@ -697,2 +694,100 @@ }; | ||
} | ||
// ### `extractLists` finds and removes all list triples | ||
// and returns the items per list. | ||
extractLists({ remove = false, ignoreErrors = false } = {}) { | ||
var lists = {}; // has scalar keys so could be a simple Object | ||
var onError = ignoreErrors ? (() => true) : | ||
((node, message) => { throw new Error(`${node.value} ${message}`); }); | ||
// Traverse each list from its tail | ||
var tails = this.getQuads(null, namespaces.rdf.rest, namespaces.rdf.nil, null); | ||
var toRemove = remove ? [...tails] : []; | ||
tails.forEach(tailQuad => { | ||
var items = []; // the members found as objects of rdf:first quads | ||
var malformed = false; // signals whether the current list is malformed | ||
var head; // the head of the list (_:b1 in above example) | ||
var headPos; // set to subject or object when head is set | ||
var graph = tailQuad.graph; // make sure list is in exactly one graph | ||
// Traverse the list from tail to end | ||
var current = tailQuad.subject; | ||
while (current && !malformed) { | ||
var objectQuads = this.getQuads(null, null, current, null); | ||
var subjectQuads = this.getQuads(current, null, null, null); | ||
var i, quad, first = null, rest = null, parent = null; | ||
// Find the first and rest of this list node | ||
for (i = 0; i < subjectQuads.length && !malformed; i++) { | ||
quad = subjectQuads[i]; | ||
if (!quad.graph.equals(graph)) | ||
malformed = onError(current, 'not confined to single graph'); | ||
else if (head) | ||
malformed = onError(current, 'has non-list arcs out'); | ||
// one rdf:first | ||
else if (quad.predicate.value === namespaces.rdf.first) { | ||
if (first) | ||
malformed = onError(current, 'has multiple rdf:first arcs'); | ||
else | ||
toRemove.push(first = quad); | ||
} | ||
// one rdf:rest | ||
else if (quad.predicate.value === namespaces.rdf.rest) { | ||
if (rest) | ||
malformed = onError(current, 'has multiple rdf:rest arcs'); | ||
else | ||
toRemove.push(rest = quad); | ||
} | ||
// alien triple | ||
else if (objectQuads.length) | ||
malformed = onError(current, 'can\'t be subject and object'); | ||
else { | ||
head = quad; // e.g. { (1 2 3) :p :o } | ||
headPos = 'subject'; | ||
} | ||
} | ||
// { :s :p (1 2) } arrives here with no head | ||
// { (1 2) :p :o } arrives here with head set to the list. | ||
for (i = 0; i < objectQuads.length && !malformed; ++i) { | ||
quad = objectQuads[i]; | ||
if (head) | ||
malformed = onError(current, 'can\'t have coreferences'); | ||
// one rdf:rest | ||
else if (quad.predicate.value === namespaces.rdf.rest) { | ||
if (parent) | ||
malformed = onError(current, 'has incoming rdf:rest arcs'); | ||
else | ||
parent = quad; | ||
} | ||
else { | ||
head = quad; // e.g. { :s :p (1 2) } | ||
headPos = 'object'; | ||
} | ||
} | ||
// Store the list item and continue with parent | ||
if (!first) | ||
malformed = onError(current, 'has no list head'); | ||
else | ||
items.unshift(first.object); | ||
current = parent && parent.subject; | ||
} | ||
// Don't remove any quads if the list is malformed | ||
if (malformed) | ||
remove = false; | ||
// Store the list under the value of its head | ||
else if (head) | ||
lists[head[headPos].value] = items; | ||
}); | ||
// Remove list quads if requested | ||
if (remove) | ||
this.removeQuads(toRemove); | ||
return lists; | ||
} | ||
} | ||
@@ -699,0 +794,0 @@ |
@@ -36,2 +36,3 @@ // **N3Writer** writes N3 documents. | ||
options = options || {}; | ||
this._lists = options.lists; | ||
@@ -133,4 +134,8 @@ // If no output stream given, send the output as string through the end callback | ||
// A blank node or list is represented as-is | ||
if (entity.termType !== 'NamedNode') | ||
if (entity.termType !== 'NamedNode') { | ||
// If it is a list head, pretty-print it | ||
if (this._lists && (entity.value in this._lists)) | ||
entity = this.list(this._lists[entity.value]); | ||
return 'id' in entity ? entity.id : '_:' + entity.value; | ||
} | ||
// Escape special characters | ||
@@ -204,20 +209,16 @@ var iri = entity.value; | ||
addPrefixes(prefixes, done) { | ||
// Add all useful prefixes | ||
var prefixIRIs = this._prefixIRIs, hasPrefixes = false; | ||
for (var prefix in prefixes) { | ||
// Verify whether the prefix can be used and does not exist yet | ||
var iri = prefixes[prefix]; | ||
if (typeof iri !== 'string') | ||
iri = iri.value; | ||
if (/[#\/]$/.test(iri) && prefixIRIs[iri] !== (prefix += ':')) { | ||
hasPrefixes = true; | ||
prefixIRIs[iri] = prefix; | ||
// Finish a possible pending quad | ||
if (this._subject !== null) { | ||
this._write(this._inDefaultGraph ? '.\n' : '\n}\n'); | ||
this._subject = null, this._graph = ''; | ||
} | ||
// Write prefix | ||
this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); | ||
hasPrefixes = true; | ||
// Finish a possible pending quad | ||
if (this._subject !== null) { | ||
this._write(this._inDefaultGraph ? '.\n' : '\n}\n'); | ||
this._subject = null, this._graph = ''; | ||
} | ||
// Store and write the prefix | ||
prefixIRIs[iri] = (prefix += ':'); | ||
this._write('@prefix ' + prefix + ' <' + iri + '>.\n'); | ||
} | ||
@@ -224,0 +225,0 @@ // Recreate the prefix matcher |
245796
5289