n3 1.17.4 → 1.17.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/browser/n3.min.js +1 -1
- package/lib/N3DataFactory.js +1 -1
- package/lib/N3Lexer.js +1 -1
- package/lib/N3Parser.js +6 -6
- package/lib/N3Store.js +107 -75
- package/lib/N3StreamParser.js +1 -1
- package/lib/N3StreamWriter.js +1 -1
- package/lib/N3Util.js +1 -1
- package/lib/N3Writer.js +3 -3
- package/lib/index.js +9 -3
- package/package.json +1 -1
- package/src/N3Parser.js +5 -5
- package/src/N3Store.js +92 -81
- package/src/N3Writer.js +1 -1
- package/src/index.js +2 -1
package/src/N3Store.js
CHANGED
|
@@ -4,33 +4,25 @@ import { default as N3DataFactory, termToId, termFromId } from './N3DataFactory'
|
|
|
4
4
|
import namespaces from './IRIs';
|
|
5
5
|
import { isDefaultGraph } from './N3Util';
|
|
6
6
|
|
|
7
|
+
const ITERATOR = Symbol('iter');
|
|
8
|
+
|
|
7
9
|
// ## Constructor
|
|
8
|
-
export
|
|
9
|
-
constructor(
|
|
10
|
-
|
|
11
|
-
this._size = 0;
|
|
12
|
-
// `_graphs` contains subject, predicate, and object indexes per graph
|
|
13
|
-
this._graphs = Object.create(null);
|
|
10
|
+
export class N3EntityIndex {
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this._id = 1;
|
|
14
13
|
// `_ids` maps entities such as `http://xmlns.com/foaf/0.1/name` to numbers,
|
|
15
14
|
// saving memory by using only numbers as keys in `_graphs`
|
|
16
|
-
this._id = 0;
|
|
17
15
|
this._ids = Object.create(null);
|
|
18
|
-
this.
|
|
16
|
+
this._ids[''] = 1;
|
|
17
|
+
// inverse of `_ids`
|
|
18
|
+
this._entities = Object.create(null);
|
|
19
|
+
this._entities[1] = '';
|
|
19
20
|
// `_blankNodeIndex` is the index of the last automatically named blank node
|
|
20
21
|
this._blankNodeIndex = 0;
|
|
21
|
-
|
|
22
|
-
// Shift parameters if `quads` is not given
|
|
23
|
-
if (!options && quads && !quads[0])
|
|
24
|
-
options = quads, quads = null;
|
|
25
|
-
options = options || {};
|
|
26
22
|
this._factory = options.factory || N3DataFactory;
|
|
27
|
-
|
|
28
|
-
// Add quads if passed
|
|
29
|
-
if (quads)
|
|
30
|
-
this.addQuads(quads);
|
|
31
23
|
}
|
|
32
24
|
|
|
33
|
-
_termFromId(id
|
|
25
|
+
_termFromId(id) {
|
|
34
26
|
if (id[0] === '.') {
|
|
35
27
|
const entities = this._entities;
|
|
36
28
|
const terms = id.split('.');
|
|
@@ -42,7 +34,7 @@ export default class N3Store {
|
|
|
42
34
|
);
|
|
43
35
|
return q;
|
|
44
36
|
}
|
|
45
|
-
return termFromId(id,
|
|
37
|
+
return termFromId(id, this._factory);
|
|
46
38
|
}
|
|
47
39
|
|
|
48
40
|
_termToNumericId(term) {
|
|
@@ -69,6 +61,50 @@ export default class N3Store {
|
|
|
69
61
|
return this._ids[str] || (this._ids[this._entities[++this._id] = str] = this._id);
|
|
70
62
|
}
|
|
71
63
|
|
|
64
|
+
createBlankNode(suggestedName) {
|
|
65
|
+
let name, index;
|
|
66
|
+
// Generate a name based on the suggested name
|
|
67
|
+
if (suggestedName) {
|
|
68
|
+
name = suggestedName = `_:${suggestedName}`, index = 1;
|
|
69
|
+
while (this._ids[name])
|
|
70
|
+
name = suggestedName + index++;
|
|
71
|
+
}
|
|
72
|
+
// Generate a generic blank node name
|
|
73
|
+
else {
|
|
74
|
+
do { name = `_:b${this._blankNodeIndex++}`; }
|
|
75
|
+
while (this._ids[name]);
|
|
76
|
+
}
|
|
77
|
+
// Add the blank node to the entities, avoiding the generation of duplicates
|
|
78
|
+
this._ids[name] = ++this._id;
|
|
79
|
+
this._entities[this._id] = name;
|
|
80
|
+
return this._factory.blankNode(name.substr(2));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ## Constructor
|
|
85
|
+
export default class N3Store {
|
|
86
|
+
constructor(quads, options) {
|
|
87
|
+
// The number of quads is initially zero
|
|
88
|
+
this._size = 0;
|
|
89
|
+
// `_graphs` contains subject, predicate, and object indexes per graph
|
|
90
|
+
this._graphs = Object.create(null);
|
|
91
|
+
|
|
92
|
+
// Shift parameters if `quads` is not given
|
|
93
|
+
if (!options && quads && !quads[0])
|
|
94
|
+
options = quads, quads = null;
|
|
95
|
+
options = options || {};
|
|
96
|
+
this._factory = options.factory || N3DataFactory;
|
|
97
|
+
this._entityIndex = options.entityIndex || new N3EntityIndex({ factory: this._factory });
|
|
98
|
+
this._entities = this._entityIndex._entities;
|
|
99
|
+
this._termFromId = this._entityIndex._termFromId.bind(this._entityIndex);
|
|
100
|
+
this._termToNumericId = this._entityIndex._termToNumericId.bind(this._entityIndex);
|
|
101
|
+
this._termToNewNumericId = this._entityIndex._termToNewNumericId.bind(this._entityIndex);
|
|
102
|
+
|
|
103
|
+
// Add quads if passed
|
|
104
|
+
if (quads)
|
|
105
|
+
this.addQuads(quads);
|
|
106
|
+
}
|
|
107
|
+
|
|
72
108
|
// ## Public properties
|
|
73
109
|
|
|
74
110
|
// ### `size` returns the number of quads in the store
|
|
@@ -127,24 +163,24 @@ export default class N3Store {
|
|
|
127
163
|
*_findInIndex(index0, key0, key1, key2, name0, name1, name2, graphId) {
|
|
128
164
|
let tmp, index1, index2;
|
|
129
165
|
const entityKeys = this._entities;
|
|
130
|
-
const graph = this._termFromId(graphId
|
|
166
|
+
const graph = this._termFromId(entityKeys[graphId]);
|
|
131
167
|
const parts = { subject: null, predicate: null, object: null };
|
|
132
168
|
|
|
133
169
|
// If a key is specified, use only that part of index 0.
|
|
134
170
|
if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0];
|
|
135
171
|
for (const value0 in index0) {
|
|
136
172
|
if (index1 = index0[value0]) {
|
|
137
|
-
parts[name0] = this._termFromId(entityKeys[value0]
|
|
173
|
+
parts[name0] = this._termFromId(entityKeys[value0]);
|
|
138
174
|
// If a key is specified, use only that part of index 1.
|
|
139
175
|
if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1];
|
|
140
176
|
for (const value1 in index1) {
|
|
141
177
|
if (index2 = index1[value1]) {
|
|
142
|
-
parts[name1] = this._termFromId(entityKeys[value1]
|
|
178
|
+
parts[name1] = this._termFromId(entityKeys[value1]);
|
|
143
179
|
// If a key is specified, use only that part of index 2, if it exists.
|
|
144
180
|
const values = key2 ? (key2 in index2 ? [key2] : []) : Object.keys(index2);
|
|
145
181
|
// Create quads for all items found in index 2.
|
|
146
182
|
for (let l = 0; l < values.length; l++) {
|
|
147
|
-
parts[name2] = this._termFromId(entityKeys[values[l]]
|
|
183
|
+
parts[name2] = this._termFromId(entityKeys[values[l]]);
|
|
148
184
|
yield this._factory.quad(parts.subject, parts.predicate, parts.object, graph);
|
|
149
185
|
}
|
|
150
186
|
}
|
|
@@ -215,11 +251,8 @@ export default class N3Store {
|
|
|
215
251
|
// ### `_getGraphs` returns an array with the given graph,
|
|
216
252
|
// or all graphs if the argument is null or undefined.
|
|
217
253
|
_getGraphs(graph) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
const graphs = {};
|
|
221
|
-
graphs[graph] = this._graphs[graph];
|
|
222
|
-
return graphs;
|
|
254
|
+
graph = graph === '' ? 1 : (graph && (this._termToNumericId(graph) || -1));
|
|
255
|
+
return typeof graph !== 'number' ? this._graphs : { [graph]: this._graphs[graph] };
|
|
223
256
|
}
|
|
224
257
|
|
|
225
258
|
// ### `_uniqueEntities` returns a function that accepts an entity ID
|
|
@@ -253,7 +286,7 @@ export default class N3Store {
|
|
|
253
286
|
predicate = subject.predicate, subject = subject.subject;
|
|
254
287
|
|
|
255
288
|
// Convert terms to internal string representation
|
|
256
|
-
graph =
|
|
289
|
+
graph = graph ? this._termToNewNumericId(graph) : 1;
|
|
257
290
|
|
|
258
291
|
// Find the graph that will contain the triple
|
|
259
292
|
let graphItem = this._graphs[graph];
|
|
@@ -313,9 +346,8 @@ export default class N3Store {
|
|
|
313
346
|
if (!predicate)
|
|
314
347
|
graph = subject.graph, object = subject.object,
|
|
315
348
|
predicate = subject.predicate, subject = subject.subject;
|
|
316
|
-
|
|
317
349
|
// Convert terms to internal string representation
|
|
318
|
-
graph =
|
|
350
|
+
graph = graph ? this._termToNumericId(graph) : 1;
|
|
319
351
|
|
|
320
352
|
// Find internal identifiers for all components
|
|
321
353
|
// and verify the quad exists.
|
|
@@ -357,10 +389,16 @@ export default class N3Store {
|
|
|
357
389
|
removeMatches(subject, predicate, object, graph) {
|
|
358
390
|
const stream = new Readable({ objectMode: true });
|
|
359
391
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
392
|
+
const iterable = this.readQuads(subject, predicate, object, graph);
|
|
393
|
+
stream._read = size => {
|
|
394
|
+
while (size-- > 0) {
|
|
395
|
+
const { done, value } = iterable.next();
|
|
396
|
+
if (done) {
|
|
397
|
+
stream.push(null);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
stream.push(value);
|
|
401
|
+
}
|
|
364
402
|
};
|
|
365
403
|
|
|
366
404
|
return this.remove(stream);
|
|
@@ -380,9 +418,6 @@ export default class N3Store {
|
|
|
380
418
|
// ### `readQuads` returns an generator of quads matching a pattern.
|
|
381
419
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
382
420
|
*readQuads(subject, predicate, object, graph) {
|
|
383
|
-
// Convert terms to internal string representation
|
|
384
|
-
graph = graph && termToId(graph);
|
|
385
|
-
|
|
386
421
|
const graphs = this._getGraphs(graph);
|
|
387
422
|
let content, subjectId, predicateId, objectId;
|
|
388
423
|
|
|
@@ -429,15 +464,12 @@ export default class N3Store {
|
|
|
429
464
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
430
465
|
// For backwards compatibility, the object return also implements the Readable stream interface.
|
|
431
466
|
match(subject, predicate, object, graph) {
|
|
432
|
-
return new DatasetCoreAndReadableStream(this, subject, predicate, object, graph);
|
|
467
|
+
return new DatasetCoreAndReadableStream(this, subject, predicate, object, graph, { entityIndex: this._entityIndex });
|
|
433
468
|
}
|
|
434
469
|
|
|
435
470
|
// ### `countQuads` returns the number of quads matching a pattern.
|
|
436
471
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
437
472
|
countQuads(subject, predicate, object, graph) {
|
|
438
|
-
// Convert terms to internal string representation
|
|
439
|
-
graph = graph && termToId(graph);
|
|
440
|
-
|
|
441
473
|
const graphs = this._getGraphs(graph);
|
|
442
474
|
let count = 0, content, subjectId, predicateId, objectId;
|
|
443
475
|
|
|
@@ -514,9 +546,6 @@ export default class N3Store {
|
|
|
514
546
|
// ### `forSubjects` executes the callback on all subjects that match the pattern.
|
|
515
547
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
516
548
|
forSubjects(callback, predicate, object, graph) {
|
|
517
|
-
// Convert terms to internal string representation
|
|
518
|
-
graph = graph && termToId(graph);
|
|
519
|
-
|
|
520
549
|
const graphs = this._getGraphs(graph);
|
|
521
550
|
let content, predicateId, objectId;
|
|
522
551
|
callback = this._uniqueEntities(callback);
|
|
@@ -559,9 +588,6 @@ export default class N3Store {
|
|
|
559
588
|
// ### `forPredicates` executes the callback on all predicates that match the pattern.
|
|
560
589
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
561
590
|
forPredicates(callback, subject, object, graph) {
|
|
562
|
-
// Convert terms to internal string representation
|
|
563
|
-
graph = graph && termToId(graph);
|
|
564
|
-
|
|
565
591
|
const graphs = this._getGraphs(graph);
|
|
566
592
|
let content, subjectId, objectId;
|
|
567
593
|
callback = this._uniqueEntities(callback);
|
|
@@ -604,9 +630,6 @@ export default class N3Store {
|
|
|
604
630
|
// ### `forObjects` executes the callback on all objects that match the pattern.
|
|
605
631
|
// Setting any field to `undefined` or `null` indicates a wildcard.
|
|
606
632
|
forObjects(callback, subject, predicate, graph) {
|
|
607
|
-
// Convert terms to internal string representation
|
|
608
|
-
graph = graph && termToId(graph);
|
|
609
|
-
|
|
610
633
|
const graphs = this._getGraphs(graph);
|
|
611
634
|
let content, subjectId, predicateId;
|
|
612
635
|
callback = this._uniqueEntities(callback);
|
|
@@ -653,28 +676,13 @@ export default class N3Store {
|
|
|
653
676
|
this.some(quad => {
|
|
654
677
|
callback(quad.graph);
|
|
655
678
|
return true; // Halt iteration of some()
|
|
656
|
-
}, subject, predicate, object, graph);
|
|
679
|
+
}, subject, predicate, object, this._termFromId(this._entities[graph]));
|
|
657
680
|
}
|
|
658
681
|
}
|
|
659
682
|
|
|
660
683
|
// ### `createBlankNode` creates a new blank node, returning its name
|
|
661
684
|
createBlankNode(suggestedName) {
|
|
662
|
-
|
|
663
|
-
// Generate a name based on the suggested name
|
|
664
|
-
if (suggestedName) {
|
|
665
|
-
name = suggestedName = `_:${suggestedName}`, index = 1;
|
|
666
|
-
while (this._ids[name])
|
|
667
|
-
name = suggestedName + index++;
|
|
668
|
-
}
|
|
669
|
-
// Generate a generic blank node name
|
|
670
|
-
else {
|
|
671
|
-
do { name = `_:b${this._blankNodeIndex++}`; }
|
|
672
|
-
while (this._ids[name]);
|
|
673
|
-
}
|
|
674
|
-
// Add the blank node to the entities, avoiding the generation of duplicates
|
|
675
|
-
this._ids[name] = ++this._id;
|
|
676
|
-
this._entities[this._id] = name;
|
|
677
|
-
return this._factory.blankNode(name.substr(2));
|
|
685
|
+
return this._entityIndex.createBlankNode(suggestedName);
|
|
678
686
|
}
|
|
679
687
|
|
|
680
688
|
// ### `extractLists` finds and removes all list triples
|
|
@@ -783,24 +791,19 @@ export default class N3Store {
|
|
|
783
791
|
}
|
|
784
792
|
}
|
|
785
793
|
|
|
786
|
-
// Determines whether the argument is a string
|
|
787
|
-
function isString(s) {
|
|
788
|
-
return typeof s === 'string' || s instanceof String;
|
|
789
|
-
}
|
|
790
|
-
|
|
791
794
|
/**
|
|
792
795
|
* A class that implements both DatasetCore and Readable.
|
|
793
796
|
*/
|
|
794
797
|
class DatasetCoreAndReadableStream extends Readable {
|
|
795
|
-
constructor(n3Store, subject, predicate, object, graph) {
|
|
798
|
+
constructor(n3Store, subject, predicate, object, graph, options) {
|
|
796
799
|
super({ objectMode: true });
|
|
797
|
-
Object.assign(this, { n3Store, subject, predicate, object, graph });
|
|
800
|
+
Object.assign(this, { n3Store, subject, predicate, object, graph, options });
|
|
798
801
|
}
|
|
799
802
|
|
|
800
803
|
get filtered() {
|
|
801
804
|
if (!this._filtered) {
|
|
802
805
|
const { n3Store, graph, object, predicate, subject } = this;
|
|
803
|
-
const newStore = this._filtered = new N3Store({ factory: n3Store._factory });
|
|
806
|
+
const newStore = this._filtered = new N3Store({ factory: n3Store._factory, entityIndex: this.options.entityIndex });
|
|
804
807
|
for (const quad of n3Store.readQuads(subject, predicate, object, graph))
|
|
805
808
|
newStore.addQuad(quad);
|
|
806
809
|
}
|
|
@@ -811,10 +814,18 @@ class DatasetCoreAndReadableStream extends Readable {
|
|
|
811
814
|
return this.filtered.size;
|
|
812
815
|
}
|
|
813
816
|
|
|
814
|
-
_read() {
|
|
815
|
-
|
|
816
|
-
this.
|
|
817
|
-
this
|
|
817
|
+
_read(size) {
|
|
818
|
+
if (size > 0 && !this[ITERATOR])
|
|
819
|
+
this[ITERATOR] = this[Symbol.iterator]();
|
|
820
|
+
const iterable = this[ITERATOR];
|
|
821
|
+
while (size-- > 0) {
|
|
822
|
+
const { done, value } = iterable.next();
|
|
823
|
+
if (done) {
|
|
824
|
+
this.push(null);
|
|
825
|
+
return;
|
|
826
|
+
}
|
|
827
|
+
this.push(value);
|
|
828
|
+
}
|
|
818
829
|
}
|
|
819
830
|
|
|
820
831
|
add(quad) {
|
|
@@ -830,7 +841,7 @@ class DatasetCoreAndReadableStream extends Readable {
|
|
|
830
841
|
}
|
|
831
842
|
|
|
832
843
|
match(subject, predicate, object, graph) {
|
|
833
|
-
return new DatasetCoreAndReadableStream(this.filtered, subject, predicate, object, graph);
|
|
844
|
+
return new DatasetCoreAndReadableStream(this.filtered, subject, predicate, object, graph, this.options);
|
|
834
845
|
}
|
|
835
846
|
|
|
836
847
|
*[Symbol.iterator]() {
|
package/src/N3Writer.js
CHANGED
|
@@ -225,7 +225,7 @@ export default class N3Writer {
|
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
|
|
228
|
-
// ### `_encodeQuad` encodes an RDF
|
|
228
|
+
// ### `_encodeQuad` encodes an RDF-star quad
|
|
229
229
|
_encodeQuad({ subject, predicate, object, graph }) {
|
|
230
230
|
return `<<${
|
|
231
231
|
this._encodeSubject(subject)} ${
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Lexer from './N3Lexer';
|
|
2
2
|
import Parser from './N3Parser';
|
|
3
3
|
import Writer from './N3Writer';
|
|
4
|
-
import Store from './N3Store';
|
|
4
|
+
import Store, { N3EntityIndex as EntityIndex } from './N3Store';
|
|
5
5
|
import StreamParser from './N3StreamParser';
|
|
6
6
|
import StreamWriter from './N3StreamWriter';
|
|
7
7
|
import * as Util from './N3Util';
|
|
@@ -28,6 +28,7 @@ export {
|
|
|
28
28
|
Parser,
|
|
29
29
|
Writer,
|
|
30
30
|
Store,
|
|
31
|
+
EntityIndex,
|
|
31
32
|
StreamParser,
|
|
32
33
|
StreamWriter,
|
|
33
34
|
Util,
|