n3 1.15.0 → 1.16.2

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/lib/N3Parser.js CHANGED
@@ -83,11 +83,11 @@ class N3Parser {
83
83
  const n3Mode = this._n3Mode;
84
84
 
85
85
  this._contextStack.push({
86
- subject: subject,
87
- predicate: predicate,
88
- object: object,
89
- graph: graph,
90
- type: type,
86
+ type,
87
+ subject,
88
+ predicate,
89
+ object,
90
+ graph,
91
91
  inverse: n3Mode ? this._inversePredicate : false,
92
92
  blankPrefix: n3Mode ? this._prefixes._ : '',
93
93
  quantified: n3Mode ? this._quantified : null
@@ -107,16 +107,18 @@ class N3Parser {
107
107
  // when leaving a scope (list, blank node, formula)
108
108
 
109
109
 
110
- _restoreContext() {
111
- const context = this._contextStack.pop(),
112
- n3Mode = this._n3Mode;
110
+ _restoreContext(type, token) {
111
+ // Obtain the previous context
112
+ const context = this._contextStack.pop();
113
+
114
+ if (!context || context.type !== type) return this._error(`Unexpected ${token.type}`, token); // Restore the quad of the previous context
113
115
 
114
116
  this._subject = context.subject;
115
117
  this._predicate = context.predicate;
116
118
  this._object = context.object;
117
- this._graph = context.graph; // The settings below only apply to N3 streams
119
+ this._graph = context.graph; // Restore N3 context settings
118
120
 
119
- if (n3Mode) {
121
+ if (this._n3Mode) {
120
122
  this._inversePredicate = context.inverse;
121
123
  this._prefixes._ = context.blankPrefix;
122
124
  this._quantified = context.quantified;
@@ -406,7 +408,7 @@ class N3Parser {
406
408
 
407
409
  const empty = this._predicate === null;
408
410
 
409
- this._restoreContext(); // If the blank node was the object, restore previous context and read punctuation
411
+ this._restoreContext('blank', token); // If the blank node was the object, restore previous context and read punctuation
410
412
 
411
413
 
412
414
  if (this._object !== null) return this._getContextEndReader(); // If the blank node was the predicate, continue reading the object
@@ -460,7 +462,7 @@ class N3Parser {
460
462
 
461
463
  case ')':
462
464
  // Closing the list; restore the parent context
463
- this._restoreContext(); // If this list is contained within a parent list, return the membership quad here.
465
+ this._restoreContext('list', token); // If this list is contained within a parent list, return the membership quad here.
464
466
  // This will be `<parent list element> rdf:first <this list>.`.
465
467
 
466
468
 
@@ -606,7 +608,7 @@ class N3Parser {
606
608
 
607
609
  if (this._subject !== null) this._emit(this._subject, this._predicate, this._object, this._graph); // Restore the parent context containing this formula
608
610
 
609
- this._restoreContext(); // If the formula was the subject, continue reading the predicate.
611
+ this._restoreContext('formula', token); // If the formula was the subject, continue reading the predicate.
610
612
  // If the formula was the object, read punctuation.
611
613
 
612
614
 
@@ -830,7 +832,7 @@ class N3Parser {
830
832
  // The list item is the remaining subejct after reading the path
831
833
  const item = this._subject; // Switch back to the context of the list
832
834
 
833
- this._restoreContext(); // Output the list item
835
+ this._restoreContext('item', token); // Output the list item
834
836
 
835
837
 
836
838
  this._emit(this._subject, this.RDF_FIRST, item, this._graph);
@@ -890,7 +892,7 @@ class N3Parser {
890
892
 
891
893
  const quad = this._quad(this._subject, this._predicate, this._object, this._graph || this.DEFAULTGRAPH);
892
894
 
893
- this._restoreContext(); // If the triple was the subject, continue by reading the predicate.
895
+ this._restoreContext('<<', token); // If the triple was the subject, continue by reading the predicate.
894
896
 
895
897
 
896
898
  if (this._subject === null) {
package/lib/N3Store.js CHANGED
@@ -92,54 +92,41 @@ class N3Store {
92
92
  // `name0`, `name1`, and `name2` are the names of the keys at each level,
93
93
  // used when reconstructing the resulting quad
94
94
  // (for instance: _subject_, _predicate_, and _object_).
95
- // Finally, `graph` will be the graph of the created quads.
96
- // If `callback` is given, each result is passed through it
97
- // and iteration halts when it returns truthy for any quad.
98
- // If instead `array` is given, each result is added to the array.
95
+ // Finally, `graphId` will be the graph of the created quads.
99
96
 
100
97
 
101
- _findInIndex(index0, key0, key1, key2, name0, name1, name2, graph, callback, array) {
102
- let tmp, index1, index2; // Depending on the number of variables, keys or reverse index are faster
103
-
104
- const varCount = !key0 + !key1 + !key2,
105
- entityKeys = varCount > 1 ? Object.keys(this._ids) : this._entities; // If a key is specified, use only that part of index 0.
98
+ *_findInIndex(index0, key0, key1, key2, name0, name1, name2, graphId) {
99
+ let tmp, index1, index2;
100
+ const entityKeys = this._entities;
101
+ const graph = (0, _N3DataFactory.termFromId)(graphId, this._factory);
102
+ const parts = {
103
+ subject: null,
104
+ predicate: null,
105
+ object: null
106
+ }; // If a key is specified, use only that part of index 0.
106
107
 
107
108
  if (key0) (tmp = index0, index0 = {})[key0] = tmp[key0];
108
109
 
109
110
  for (const value0 in index0) {
110
- const entity0 = entityKeys[value0];
111
-
112
111
  if (index1 = index0[value0]) {
113
- // If a key is specified, use only that part of index 1.
112
+ parts[name0] = (0, _N3DataFactory.termFromId)(entityKeys[value0], this._factory); // If a key is specified, use only that part of index 1.
113
+
114
114
  if (key1) (tmp = index1, index1 = {})[key1] = tmp[key1];
115
115
 
116
116
  for (const value1 in index1) {
117
- const entity1 = entityKeys[value1];
118
-
119
117
  if (index2 = index1[value1]) {
120
- // If a key is specified, use only that part of index 2, if it exists.
118
+ parts[name1] = (0, _N3DataFactory.termFromId)(entityKeys[value1], this._factory); // If a key is specified, use only that part of index 2, if it exists.
119
+
121
120
  const values = key2 ? key2 in index2 ? [key2] : [] : Object.keys(index2); // Create quads for all items found in index 2.
122
121
 
123
122
  for (let l = 0; l < values.length; l++) {
124
- const parts = {
125
- subject: null,
126
- predicate: null,
127
- object: null
128
- };
129
- parts[name0] = (0, _N3DataFactory.termFromId)(entity0, this._factory);
130
- parts[name1] = (0, _N3DataFactory.termFromId)(entity1, this._factory);
131
123
  parts[name2] = (0, _N3DataFactory.termFromId)(entityKeys[values[l]], this._factory);
132
-
133
- const quad = this._factory.quad(parts.subject, parts.predicate, parts.object, (0, _N3DataFactory.termFromId)(graph, this._factory));
134
-
135
- if (array) array.push(quad);else if (callback(quad)) return true;
124
+ yield this._factory.quad(parts.subject, parts.predicate, parts.object, graph);
136
125
  }
137
126
  }
138
127
  }
139
128
  }
140
129
  }
141
-
142
- return array;
143
130
  } // ### `_loop` executes the callback on all keys of index 0
144
131
 
145
132
 
@@ -288,13 +275,17 @@ class N3Store {
288
275
  delete(quad) {
289
276
  this.removeQuad(quad);
290
277
  return this;
291
- } // ### `has` determines whether a dataset includes a certain quad.
292
- // Returns true or false as appropriate.
278
+ } // ### `has` determines whether a dataset includes a certain quad or quad pattern.
293
279
 
294
280
 
295
- has(quad) {
296
- const quads = this.getQuads(quad.subject, quad.predicate, quad.object, quad.graph);
297
- return quads.length !== 0;
281
+ has(subjectOrQuad, predicate, object, graph) {
282
+ if (subjectOrQuad && subjectOrQuad.subject) ({
283
+ subject: subjectOrQuad,
284
+ predicate,
285
+ object,
286
+ graph
287
+ } = subjectOrQuad);
288
+ return !this.readQuads(subjectOrQuad, predicate, object, graph).next().done;
298
289
  } // ### `import` adds a stream of quads to the store
299
290
 
300
291
 
@@ -356,7 +347,7 @@ class N3Store {
356
347
  });
357
348
 
358
349
  stream._read = () => {
359
- for (const quad of this.getQuads(subject, predicate, object, graph)) stream.push(quad);
350
+ for (const quad of this.readQuads(subject, predicate, object, graph)) stream.push(quad);
360
351
 
361
352
  stream.push(null);
362
353
  };
@@ -372,19 +363,24 @@ class N3Store {
372
363
 
373
364
 
374
365
  getQuads(subject, predicate, object, graph) {
366
+ return [...this.readQuads(subject, predicate, object, graph)];
367
+ } // ### `readQuads` returns an generator of quads matching a pattern.
368
+ // Setting any field to `undefined` or `null` indicates a wildcard.
369
+
370
+
371
+ *readQuads(subject, predicate, object, graph) {
375
372
  // Convert terms to internal string representation
376
373
  subject = subject && (0, _N3DataFactory.termToId)(subject);
377
374
  predicate = predicate && (0, _N3DataFactory.termToId)(predicate);
378
375
  object = object && (0, _N3DataFactory.termToId)(object);
379
376
  graph = graph && (0, _N3DataFactory.termToId)(graph);
380
377
 
381
- const quads = [],
382
- graphs = this._getGraphs(graph),
378
+ const graphs = this._getGraphs(graph),
383
379
  ids = this._ids;
384
380
 
385
381
  let content, subjectId, predicateId, objectId; // Translate IRIs to internal index keys.
386
382
 
387
- if (isString(subject) && !(subjectId = ids[subject]) || isString(predicate) && !(predicateId = ids[predicate]) || isString(object) && !(objectId = ids[object])) return quads;
383
+ if (isString(subject) && !(subjectId = ids[subject]) || isString(predicate) && !(predicateId = ids[predicate]) || isString(object) && !(objectId = ids[object])) return;
388
384
 
389
385
  for (const graphId in graphs) {
390
386
  // Only if the specified graph contains triples, there can be results
@@ -392,16 +388,14 @@ class N3Store {
392
388
  // Choose the optimal index, based on what fields are present
393
389
  if (subjectId) {
394
390
  if (objectId) // If subject and object are given, the object index will be the fastest
395
- this._findInIndex(content.objects, objectId, subjectId, predicateId, 'object', 'subject', 'predicate', graphId, null, quads);else // If only subject and possibly predicate are given, the subject index will be the fastest
396
- this._findInIndex(content.subjects, subjectId, predicateId, null, 'subject', 'predicate', 'object', graphId, null, quads);
391
+ yield* this._findInIndex(content.objects, objectId, subjectId, predicateId, 'object', 'subject', 'predicate', graphId);else // If only subject and possibly predicate are given, the subject index will be the fastest
392
+ yield* this._findInIndex(content.subjects, subjectId, predicateId, null, 'subject', 'predicate', 'object', graphId);
397
393
  } else if (predicateId) // If only predicate and possibly object are given, the predicate index will be the fastest
398
- this._findInIndex(content.predicates, predicateId, objectId, null, 'predicate', 'object', 'subject', graphId, null, quads);else if (objectId) // If only object is given, the object index will be the fastest
399
- this._findInIndex(content.objects, objectId, null, null, 'object', 'subject', 'predicate', graphId, null, quads);else // If nothing is given, iterate subjects and predicates first
400
- this._findInIndex(content.subjects, null, null, null, 'subject', 'predicate', 'object', graphId, null, quads);
394
+ yield* this._findInIndex(content.predicates, predicateId, objectId, null, 'predicate', 'object', 'subject', graphId);else if (objectId) // If only object is given, the object index will be the fastest
395
+ yield* this._findInIndex(content.objects, objectId, null, null, 'object', 'subject', 'predicate', graphId);else // If nothing is given, iterate subjects and predicates first
396
+ yield* this._findInIndex(content.subjects, null, null, null, 'subject', 'predicate', 'object', graphId);
401
397
  }
402
398
  }
403
-
404
- return quads;
405
399
  } // ### `match` returns a new dataset that is comprised of all quads in the current instance matching the given arguments.
406
400
  // The logic described in Quad Matching is applied for each quad in this dataset to check if it should be included in the output dataset.
407
401
  // Note: This method always returns a new DatasetCore, even if that dataset contains no quads.
@@ -480,45 +474,7 @@ class N3Store {
480
474
 
481
475
 
482
476
  some(callback, subject, predicate, object, graph) {
483
- // Convert terms to internal string representation
484
- subject = subject && (0, _N3DataFactory.termToId)(subject);
485
- predicate = predicate && (0, _N3DataFactory.termToId)(predicate);
486
- object = object && (0, _N3DataFactory.termToId)(object);
487
- graph = graph && (0, _N3DataFactory.termToId)(graph);
488
-
489
- const graphs = this._getGraphs(graph),
490
- ids = this._ids;
491
-
492
- let content, subjectId, predicateId, objectId; // Translate IRIs to internal index keys.
493
-
494
- if (isString(subject) && !(subjectId = ids[subject]) || isString(predicate) && !(predicateId = ids[predicate]) || isString(object) && !(objectId = ids[object])) return false;
495
-
496
- for (const graphId in graphs) {
497
- // Only if the specified graph contains triples, there can be results
498
- if (content = graphs[graphId]) {
499
- // Choose the optimal index, based on what fields are present
500
- if (subjectId) {
501
- if (objectId) {
502
- // If subject and object are given, the object index will be the fastest
503
- if (this._findInIndex(content.objects, objectId, subjectId, predicateId, 'object', 'subject', 'predicate', graphId, callback, null)) return true;
504
- } else // If only subject and possibly predicate are given, the subject index will be the fastest
505
- if (this._findInIndex(content.subjects, subjectId, predicateId, null, 'subject', 'predicate', 'object', graphId, callback, null)) return true;
506
- } else if (predicateId) {
507
- // If only predicate and possibly object are given, the predicate index will be the fastest
508
- if (this._findInIndex(content.predicates, predicateId, objectId, null, 'predicate', 'object', 'subject', graphId, callback, null)) {
509
- return true;
510
- }
511
- } else if (objectId) {
512
- // If only object is given, the object index will be the fastest
513
- if (this._findInIndex(content.objects, objectId, null, null, 'object', 'subject', 'predicate', graphId, callback, null)) {
514
- return true;
515
- }
516
- } else // If nothing is given, iterate subjects and predicates first
517
- if (this._findInIndex(content.subjects, null, null, null, 'subject', 'predicate', 'object', graphId, callback, null)) {
518
- return true;
519
- }
520
- }
521
- }
477
+ for (const quad of this.readQuads(subject, predicate, object, graph)) if (callback(quad)) return true;
522
478
 
523
479
  return false;
524
480
  } // ### `getSubjects` returns all subjects that match the pattern.
@@ -772,7 +728,7 @@ class N3Store {
772
728
 
773
729
 
774
730
  *[Symbol.iterator]() {
775
- yield* this.getQuads();
731
+ yield* this.readQuads();
776
732
  }
777
733
 
778
734
  } // Determines whether the argument is a string
@@ -811,10 +767,11 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
811
767
  predicate,
812
768
  subject
813
769
  } = this;
814
- const quads = n3Store.getQuads(subject, predicate, object, graph);
815
- this._filtered = new N3Store(quads, {
770
+ const newStore = this._filtered = new N3Store({
816
771
  factory: n3Store._factory
817
772
  });
773
+
774
+ for (const quad of n3Store.readQuads(subject, predicate, object, graph)) newStore.addQuad(quad);
818
775
  }
819
776
 
820
777
  return this._filtered;
@@ -825,7 +782,7 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
825
782
  }
826
783
 
827
784
  _read() {
828
- for (const quad of this.filtered.getQuads()) this.push(quad);
785
+ for (const quad of this) this.push(quad);
829
786
 
830
787
  this.push(null);
831
788
  }
@@ -847,7 +804,7 @@ class DatasetCoreAndReadableStream extends _readableStream.Readable {
847
804
  }
848
805
 
849
806
  *[Symbol.iterator]() {
850
- yield* this.filtered.getQuads();
807
+ yield* this._filtered || this.n3Store.readQuads(this.subject, this.predicate, this.object, this.graph);
851
808
  }
852
809
 
853
810
  }
package/lib/N3Util.js CHANGED
@@ -50,7 +50,7 @@ function inDefaultGraph(quad) {
50
50
 
51
51
  function prefix(iri, factory) {
52
52
  return prefixes({
53
- '': iri
53
+ '': iri.value || iri
54
54
  }, factory)('');
55
55
  } // Creates a function that allows registering and expanding prefixes
56
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n3",
3
- "version": "1.15.0",
3
+ "version": "1.16.2",
4
4
  "description": "Lightning fast, asynchronous, streaming Turtle / N3 / RDF library.",
5
5
  "author": "Ruben Verborgh <ruben.verborgh@gmail.com>",
6
6
  "keywords": [
package/src/N3Parser.js CHANGED
@@ -74,8 +74,8 @@ export default class N3Parser {
74
74
  _saveContext(type, graph, subject, predicate, object) {
75
75
  const n3Mode = this._n3Mode;
76
76
  this._contextStack.push({
77
- subject: subject, predicate: predicate, object: object,
78
- graph: graph, type: type,
77
+ type,
78
+ subject, predicate, object, graph,
79
79
  inverse: n3Mode ? this._inversePredicate : false,
80
80
  blankPrefix: n3Mode ? this._prefixes._ : '',
81
81
  quantified: n3Mode ? this._quantified : null,
@@ -94,14 +94,20 @@ export default class N3Parser {
94
94
 
95
95
  // ### `_restoreContext` restores the parent context
96
96
  // when leaving a scope (list, blank node, formula)
97
- _restoreContext() {
98
- const context = this._contextStack.pop(), n3Mode = this._n3Mode;
97
+ _restoreContext(type, token) {
98
+ // Obtain the previous context
99
+ const context = this._contextStack.pop();
100
+ if (!context || context.type !== type)
101
+ return this._error(`Unexpected ${token.type}`, token);
102
+
103
+ // Restore the quad of the previous context
99
104
  this._subject = context.subject;
100
105
  this._predicate = context.predicate;
101
106
  this._object = context.object;
102
107
  this._graph = context.graph;
103
- // The settings below only apply to N3 streams
104
- if (n3Mode) {
108
+
109
+ // Restore N3 context settings
110
+ if (this._n3Mode) {
105
111
  this._inversePredicate = context.inverse;
106
112
  this._prefixes._ = context.blankPrefix;
107
113
  this._quantified = context.quantified;
@@ -374,7 +380,7 @@ export default class N3Parser {
374
380
 
375
381
  // Restore the parent context containing this blank node
376
382
  const empty = this._predicate === null;
377
- this._restoreContext();
383
+ this._restoreContext('blank', token);
378
384
  // If the blank node was the object, restore previous context and read punctuation
379
385
  if (this._object !== null)
380
386
  return this._getContextEndReader();
@@ -425,7 +431,7 @@ export default class N3Parser {
425
431
  break;
426
432
  case ')':
427
433
  // Closing the list; restore the parent context
428
- this._restoreContext();
434
+ this._restoreContext('list', token);
429
435
  // If this list is contained within a parent list, return the membership quad here.
430
436
  // This will be `<parent list element> rdf:first <this list>.`.
431
437
  if (stack.length !== 0 && stack[stack.length - 1].type === 'list')
@@ -576,7 +582,7 @@ export default class N3Parser {
576
582
  this._emit(this._subject, this._predicate, this._object, this._graph);
577
583
 
578
584
  // Restore the parent context containing this formula
579
- this._restoreContext();
585
+ this._restoreContext('formula', token);
580
586
  // If the formula was the subject, continue reading the predicate.
581
587
  // If the formula was the object, read punctuation.
582
588
  return this._object === null ? this._readPredicate : this._getContextEndReader();
@@ -785,7 +791,7 @@ export default class N3Parser {
785
791
  // The list item is the remaining subejct after reading the path
786
792
  const item = this._subject;
787
793
  // Switch back to the context of the list
788
- this._restoreContext();
794
+ this._restoreContext('item', token);
789
795
  // Output the list item
790
796
  this._emit(this._subject, this.RDF_FIRST, item, this._graph);
791
797
  }
@@ -847,7 +853,7 @@ export default class N3Parser {
847
853
  // Read the quad and restore the previous context
848
854
  const quad = this._quad(this._subject, this._predicate, this._object,
849
855
  this._graph || this.DEFAULTGRAPH);
850
- this._restoreContext();
856
+ this._restoreContext('<<', token);
851
857
  // If the triple was the subject, continue by reading the predicate.
852
858
  if (this._subject === null) {
853
859
  this._subject = quad;