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/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 default class N3Store {
9
- constructor(quads, options) {
10
- // The number of quads is initially zero
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._entities = Object.create(null); // inverse of `_ids`
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, factory) {
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, factory);
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, this._factory);
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], this._factory);
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], this._factory);
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]], this._factory);
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
- if (!isString(graph))
219
- return this._graphs;
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 = termToId(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 = termToId(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
- stream._read = () => {
361
- for (const quad of this.readQuads(subject, predicate, object, graph))
362
- stream.push(quad);
363
- stream.push(null);
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
- let name, index;
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
- for (const quad of this)
816
- this.push(quad);
817
- this.push(null);
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* quad
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,