n3 1.25.2 → 2.0.0-beta.1

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/N3Parser.js CHANGED
@@ -27,16 +27,12 @@ export default class N3Parser {
27
27
  this._readPredicateOrNamedGraph = this._readPredicate;
28
28
  // Support triples in other graphs
29
29
  this._supportsQuads = !(isTurtle || isTriG || isNTriples || isN3);
30
- // Whether the log:isImpliedBy predicate is supported
31
- this._isImpliedBy = options.isImpliedBy;
32
- // Support nesting of triples
33
- this._supportsRDFStar = format === '' || /star|\*$/.test(format);
34
30
  // Disable relative IRIs in N-Triples or N-Quads mode
35
31
  if (isLineMode)
36
32
  this._resolveRelativeIRI = iri => { return null; };
37
33
  this._blankNodePrefix = typeof options.blankNodePrefix !== 'string' ? '' :
38
34
  options.blankNodePrefix.replace(/^(?!_:)/, '_:');
39
- this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3, isImpliedBy: this._isImpliedBy });
35
+ this._lexer = options.lexer || new N3Lexer({ lineMode: isLineMode, n3: isN3 });
40
36
  // Disable explicit quantifiers by default
41
37
  this._explicitQuantifiers = !!options.explicitQuantifiers;
42
38
  }
@@ -135,6 +131,11 @@ export default class N3Parser {
135
131
  this._sparqlStyle = true;
136
132
  case '@base':
137
133
  return this._readBaseIRI;
134
+ // It could be a version declaration
135
+ case 'VERSION':
136
+ this._sparqlStyle = true;
137
+ case '@version':
138
+ return this._readVersion;
138
139
  // It could be a graph
139
140
  case '{':
140
141
  if (this._supportsNamedGraphs) {
@@ -199,6 +200,10 @@ export default class N3Parser {
199
200
  this._subject = this._factory.blankNode(), null, null);
200
201
  return this._readBlankNodeHead;
201
202
  case '(':
203
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
204
+ if (parent.type === '<<') {
205
+ return this._error('Unexpected list in reified triple', token);
206
+ }
202
207
  // Start a new list
203
208
  this._saveContext('list', this._graph, this.RDF_NIL, null, null);
204
209
  this._subject = null;
@@ -239,9 +244,13 @@ export default class N3Parser {
239
244
  this._subject = this._factory.literal(token.value, this._factory.namedNode(token.prefix));
240
245
 
241
246
  break;
247
+ case '<<(':
248
+ if (!this._n3Mode)
249
+ return this._error('Disallowed triple term as subject', token);
250
+ this._saveContext('<<(', this._graph, null, null, null);
251
+ this._graph = null;
252
+ return this._readSubject;
242
253
  case '<<':
243
- if (!this._supportsRDFStar)
244
- return this._error('Unexpected RDF-star syntax', token);
245
254
  this._saveContext('<<', this._graph, null, null, null);
246
255
  this._graph = null;
247
256
  return this._readSubject;
@@ -271,6 +280,7 @@ export default class N3Parser {
271
280
  case '.':
272
281
  case ']':
273
282
  case '}':
283
+ case '|}':
274
284
  // Expected predicate didn't come, must have been trailing semicolon
275
285
  if (this._predicate === null)
276
286
  return this._error(`Unexpected ${type}`, token);
@@ -317,6 +327,10 @@ export default class N3Parser {
317
327
  this._subject = this._factory.blankNode());
318
328
  return this._readBlankNodeHead;
319
329
  case '(':
330
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
331
+ if (parent.type === '<<') {
332
+ return this._error('Unexpected list in reified triple', token);
333
+ }
320
334
  // Start a new list
321
335
  this._saveContext('list', this._graph, this._subject, this._predicate, this.RDF_NIL);
322
336
  this._subject = null;
@@ -328,9 +342,11 @@ export default class N3Parser {
328
342
  this._saveContext('formula', this._graph, this._subject, this._predicate,
329
343
  this._graph = this._factory.blankNode());
330
344
  return this._readSubject;
345
+ case '<<(':
346
+ this._saveContext('<<(', this._graph, this._subject, this._predicate, null);
347
+ this._graph = null;
348
+ return this._readSubject;
331
349
  case '<<':
332
- if (!this._supportsRDFStar)
333
- return this._error('Unexpected RDF-star syntax', token);
334
350
  this._saveContext('<<', this._graph, this._subject, this._predicate, null);
335
351
  this._graph = null;
336
352
  return this._readSubject;
@@ -366,6 +382,10 @@ export default class N3Parser {
366
382
  return this._readBlankNodeTail(token);
367
383
  }
368
384
  else {
385
+ const stack = this._contextStack, parentParent = stack.length > 1 && stack[stack.length - 2];
386
+ if (parentParent.type === '<<') {
387
+ return this._error('Unexpected compound blank node expression in reified triple', token);
388
+ }
369
389
  this._predicate = null;
370
390
  return this._readPredicate(token);
371
391
  }
@@ -475,6 +495,11 @@ export default class N3Parser {
475
495
  this._saveContext('formula', this._graph, this._subject, this._predicate,
476
496
  this._graph = this._factory.blankNode());
477
497
  return this._readSubject;
498
+ case '<<':
499
+ this._saveContext('<<', this._graph, null, null, null);
500
+ this._graph = null;
501
+ next = this._readSubject;
502
+ break;
478
503
  default:
479
504
  if ((item = this._readEntity(token)) === undefined)
480
505
  return;
@@ -484,6 +509,10 @@ export default class N3Parser {
484
509
  if (list === null)
485
510
  this._subject = list = this._factory.blankNode();
486
511
 
512
+ // When reading a reified triple, store the list as subject in the stack, as this will be overridden when reading the triple.
513
+ if (token.type === '<<')
514
+ stack[stack.length - 1].subject = this._subject;
515
+
487
516
  // Is this the first element of the list?
488
517
  if (previousList === null) {
489
518
  // This list is either the subject or the object of its parent
@@ -524,9 +553,10 @@ export default class N3Parser {
524
553
  }
525
554
 
526
555
  // ### `_completeLiteral` completes a literal with an optional datatype or language
527
- _completeLiteral(token) {
556
+ _completeLiteral(token, component) {
528
557
  // Create a simple string literal by default
529
558
  let literal = this._factory.literal(this._literalValue);
559
+ let readCb;
530
560
 
531
561
  switch (token.type) {
532
562
  // Create a datatyped literal
@@ -534,43 +564,82 @@ export default class N3Parser {
534
564
  case 'typeIRI':
535
565
  const datatype = this._readEntity(token);
536
566
  if (datatype === undefined) return; // No datatype means an error occurred
567
+ if (datatype.value === namespaces.rdf.langString || datatype.value === namespaces.rdf.dirLangString) {
568
+ return this._error('Detected illegal (directional) languaged-tagged string with explicit datatype', token);
569
+ }
537
570
  literal = this._factory.literal(this._literalValue, datatype);
538
571
  token = null;
539
572
  break;
540
573
  // Create a language-tagged string
541
574
  case 'langcode':
575
+ if (token.value.length > 8)
576
+ return this._error('Detected language tag of length larger than 8', token);
542
577
  literal = this._factory.literal(this._literalValue, token.value);
578
+ this._literalLanguage = token.value;
543
579
  token = null;
580
+ readCb = this._readDirCode.bind(this, component);
544
581
  break;
545
582
  }
546
583
 
547
- return { token, literal };
584
+ return { token, literal, readCb };
585
+ }
586
+
587
+ _readDirCode(component, listItem, token) {
588
+ // Attempt to read a dircode
589
+ if (token.type === 'dircode') {
590
+ const term = this._factory.literal(this._literalValue, { language: this._literalLanguage, direction: token.value });
591
+ if (component === 'subject')
592
+ this._subject = term;
593
+ else
594
+ this._object = term;
595
+ this._literalLanguage = undefined;
596
+ token = null;
597
+ }
598
+
599
+ if (component === 'subject')
600
+ return token === null ? this._readPredicateOrNamedGraph : this._readPredicateOrNamedGraph(token);
601
+ return this._completeObjectLiteralPost(token, listItem);
548
602
  }
549
603
 
550
604
  // Completes a literal in subject position
551
605
  _completeSubjectLiteral(token) {
552
- this._subject = this._completeLiteral(token).literal;
606
+ const completed = this._completeLiteral(token, 'subject');
607
+ this._subject = completed.literal;
608
+
609
+ // Postpone completion if the literal is only partially completed (such as lang+dir).
610
+ if (completed.readCb)
611
+ return completed.readCb.bind(this, false);
612
+
553
613
  return this._readPredicateOrNamedGraph;
554
614
  }
555
615
 
556
616
  // Completes a literal in object position
557
617
  _completeObjectLiteral(token, listItem) {
558
- const completed = this._completeLiteral(token);
618
+ const completed = this._completeLiteral(token, 'object');
559
619
  if (!completed)
560
620
  return;
621
+
561
622
  this._object = completed.literal;
562
623
 
624
+ // Postpone completion if the literal is only partially completed (such as lang+dir).
625
+ if (completed.readCb)
626
+ return completed.readCb.bind(this, listItem);
627
+
628
+ return this._completeObjectLiteralPost(completed.token, listItem);
629
+ }
630
+
631
+ _completeObjectLiteralPost(token, listItem) {
563
632
  // If this literal was part of a list, write the item
564
633
  // (we could also check the context stack, but passing in a flag is faster)
565
634
  if (listItem)
566
635
  this._emit(this._subject, this.RDF_FIRST, this._object, this._graph);
567
636
  // If the token was consumed, continue with the rest of the input
568
- if (completed.token === null)
637
+ if (token === null)
569
638
  return this._getContextEndReader();
570
639
  // Otherwise, consume the token now
571
640
  else {
572
641
  this._readCallback = this._getContextEndReader();
573
- return this._readCallback(completed.token);
642
+ return this._readCallback(token);
574
643
  }
575
644
  }
576
645
 
@@ -592,7 +661,7 @@ export default class N3Parser {
592
661
 
593
662
  // ### `_readPunctuation` reads punctuation between quads or quad parts
594
663
  _readPunctuation(token) {
595
- let next, graph = this._graph;
664
+ let next, graph = this._graph, startingAnnotation = false;
596
665
  const subject = this._subject, inversePredicate = this._inversePredicate;
597
666
  switch (token.type) {
598
667
  // A closing brace ends a graph
@@ -605,6 +674,7 @@ export default class N3Parser {
605
674
  // A dot just ends the statement, without sharing anything with the next
606
675
  case '.':
607
676
  this._subject = null;
677
+ this._tripleTerm = null;
608
678
  next = this._contextStack.length ? this._readSubject : this._readInTopContext;
609
679
  if (inversePredicate) this._inversePredicate = false;
610
680
  break;
@@ -616,20 +686,24 @@ export default class N3Parser {
616
686
  case ',':
617
687
  next = this._readObject;
618
688
  break;
689
+ // ~ is allowed in the annotation syntax
690
+ case '~':
691
+ next = this._readReifierInAnnotation;
692
+ startingAnnotation = true;
693
+ break;
619
694
  // {| means that the current triple is annotated with predicate-object pairs.
620
695
  case '{|':
621
- if (!this._supportsRDFStar)
622
- return this._error('Unexpected RDF-star syntax', token);
623
- // Continue using the last triple as quoted triple subject for the predicate-object pairs.
624
- const predicate = this._predicate, object = this._object;
625
- this._subject = this._factory.quad(subject, predicate, object, this.DEFAULTGRAPH);
696
+ // Continue using the last triple as reified triple subject for the predicate-object pairs.
697
+ this._subject = this._readTripleTerm();
698
+ startingAnnotation = true;
626
699
  next = this._readPredicate;
627
700
  break;
628
- // |} means that the current quoted triple in annotation syntax is finalized.
701
+ // |} means that the current reified triple in annotation syntax is finalized.
629
702
  case '|}':
630
- if (this._subject.termType !== 'Quad')
631
- return this._error('Unexpected asserted triple closing', token);
703
+ if (!this._annotation)
704
+ return this._error('Unexpected annotation syntax closing', token);
632
705
  this._subject = null;
706
+ this._annotation = false;
633
707
  next = this._readPunctuation;
634
708
  break;
635
709
  default:
@@ -641,13 +715,16 @@ export default class N3Parser {
641
715
  return this._error(`Expected punctuation to follow "${this._object.id}"`, token);
642
716
  }
643
717
  // A quad has been completed now, so return it
644
- if (subject !== null) {
718
+ if (subject !== null && (!startingAnnotation || (startingAnnotation && !this._annotation))) {
645
719
  const predicate = this._predicate, object = this._object;
646
720
  if (!inversePredicate)
647
721
  this._emit(subject, predicate, object, graph);
648
722
  else
649
723
  this._emit(object, predicate, subject, graph);
650
724
  }
725
+ if (startingAnnotation) {
726
+ this._annotation = true;
727
+ }
651
728
  return next;
652
729
  }
653
730
 
@@ -705,6 +782,16 @@ export default class N3Parser {
705
782
  return this._readDeclarationPunctuation;
706
783
  }
707
784
 
785
+ // ### `_readVersion` reads version string declaration
786
+ _readVersion(token) {
787
+ if (token.type !== 'literal')
788
+ return this._error('Expected literal to follow version declaration', token);
789
+ if ((token.end - token.start) !== token.value.length + 2)
790
+ return this._error('Version declarations must use single quotes', token);
791
+ this._prefixCallback(token.value);
792
+ return this._readDeclarationPunctuation;
793
+ }
794
+
708
795
  // ### `_readNamedGraphLabel` reads the label of a named graph
709
796
  _readNamedGraphLabel(token) {
710
797
  switch (token.type) {
@@ -853,25 +940,15 @@ export default class N3Parser {
853
940
  return this._readPath;
854
941
  }
855
942
 
856
- // ### `_readRDFStarTailOrGraph` reads the graph of a nested RDF-star quad or the end of a nested RDF-star triple
857
- _readRDFStarTailOrGraph(token) {
858
- if (token.type !== '>>') {
859
- // An entity means this is a quad (only allowed if not already inside a graph)
860
- if (this._supportsQuads && this._graph === null && (this._graph = this._readEntity(token)) !== undefined)
861
- return this._readRDFStarTail;
862
- return this._error(`Expected >> to follow "${this._object.id}"`, token);
863
- }
864
- return this._readRDFStarTail(token);
865
- }
866
-
867
- // ### `_readRDFStarTail` reads the end of a nested RDF-star triple
868
- _readRDFStarTail(token) {
869
- if (token.type !== '>>')
870
- return this._error(`Expected >> but got ${token.type}`, token);
943
+ // ### `_readTripleTermTail` reads the end of a triple term
944
+ _readTripleTermTail(token) {
945
+ if (token.type !== ')>>')
946
+ return this._error(`Expected )>> but got ${token.type}`, token);
871
947
  // Read the quad and restore the previous context
872
948
  const quad = this._factory.quad(this._subject, this._predicate, this._object,
873
- this._graph || this.DEFAULTGRAPH);
874
- this._restoreContext('<<', token);
949
+ this._graph || this.DEFAULTGRAPH);
950
+ this._restoreContext('<<(', token);
951
+
875
952
  // If the triple was the subject, continue by reading the predicate.
876
953
  if (this._subject === null) {
877
954
  this._subject = quad;
@@ -884,6 +961,78 @@ export default class N3Parser {
884
961
  }
885
962
  }
886
963
 
964
+ // ### `_readReifiedTripleTailOrReifier` reads a reifier or the end of a nested reified triple
965
+ _readReifiedTripleTailOrReifier(token) {
966
+ if (token.type === '~') {
967
+ return this._readReifier;
968
+ }
969
+ return this._readReifiedTripleTail(token);
970
+ }
971
+
972
+ // ### `_readReifiedTripleTail` reads the end of a nested reified triple
973
+ _readReifiedTripleTail(token) {
974
+ if (token.type !== '>>')
975
+ return this._error(`Expected >> but got ${token.type}`, token);
976
+ // Read the triple term and restore the previous context
977
+ this._tripleTerm = null;
978
+ const reifier = this._readTripleTerm();
979
+ this._restoreContext('<<', token);
980
+
981
+ // // If we're in a list, continue processing that list
982
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
983
+ if (parent && parent.type === 'list') {
984
+ this._emit(this._subject, this.RDF_FIRST, reifier, this._graph);
985
+ return this._getContextEndReader();
986
+ }
987
+ // If the triple was the subject, continue by reading the predicate.
988
+ else if (this._subject === null) {
989
+ this._subject = reifier;
990
+ return this._readPredicateOrReifierTripleEnd;
991
+ }
992
+ // If the triple was the object, read context end.
993
+ else {
994
+ this._object = reifier;
995
+ return this._getContextEndReader();
996
+ }
997
+ }
998
+
999
+ _readPredicateOrReifierTripleEnd(token) {
1000
+ if (token.type === '.') {
1001
+ this._subject = null;
1002
+ return this._readPunctuation(token);
1003
+ }
1004
+ return this._readPredicate(token);
1005
+ }
1006
+
1007
+ // ### `_readReifier` reads the triple term identifier after a tilde when in a reifying triple.
1008
+ _readReifier(token) {
1009
+ this._reifier = this._readEntity(token);
1010
+ return this._readReifiedTripleTail;
1011
+ }
1012
+
1013
+ // ### `_readReifier` reads the optional triple term identifier after a tilde when in annotation syntax.
1014
+ _readReifierInAnnotation(token) {
1015
+ // If next token is a reifier, read it as such.
1016
+ if (token.type === 'IRI' || token.type === 'typeIRI' || token.type === 'type' || token.type === 'prefixed' || token.type === 'blank' || token.type === 'var') {
1017
+ this._reifier = this._readEntity(token);
1018
+ return this._readPunctuation;
1019
+ }
1020
+ // Otherwise, emit and assert triple term.
1021
+ this._readTripleTerm();
1022
+ this._subject = null;
1023
+ return this._readPunctuation(token);
1024
+ }
1025
+
1026
+ _readTripleTerm() {
1027
+ const stack = this._contextStack, parent = stack.length && stack[stack.length - 1];
1028
+ const parentGraph = parent ? parent.graph : undefined;
1029
+ const reifier = this._reifier || this._factory.blankNode();
1030
+ this._reifier = null;
1031
+ this._tripleTerm = this._tripleTerm || this._factory.quad(this._subject, this._predicate, this._object);
1032
+ this._emit(reifier, this.RDF_REIFIES, this._tripleTerm, parentGraph || this.DEFAULTGRAPH);
1033
+ return reifier;
1034
+ }
1035
+
887
1036
  // ### `_getContextEndReader` gets the next reader function at the end of a context
888
1037
  _getContextEndReader() {
889
1038
  const contextStack = this._contextStack;
@@ -897,8 +1046,10 @@ export default class N3Parser {
897
1046
  return this._readListItem;
898
1047
  case 'formula':
899
1048
  return this._readFormulaTail;
1049
+ case '<<(':
1050
+ return this._readTripleTermTail;
900
1051
  case '<<':
901
- return this._readRDFStarTailOrGraph;
1052
+ return this._readReifiedTripleTailOrReifier;
902
1053
  }
903
1054
  }
904
1055
 
@@ -1013,18 +1164,20 @@ export default class N3Parser {
1013
1164
  // ## Public methods
1014
1165
 
1015
1166
  // ### `parse` parses the N3 input and emits each parsed quad through the onQuad callback.
1016
- parse(input, quadCallback, prefixCallback) {
1167
+ parse(input, quadCallback, prefixCallback, versionCallback) {
1017
1168
  // The second parameter accepts an object { onQuad: ..., onPrefix: ..., onComment: ...}
1018
1169
  // As a second and third parameter it still accepts a separate quadCallback and prefixCallback for backward compatibility as well
1019
- let onQuad, onPrefix, onComment;
1020
- if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment)) {
1170
+ let onQuad, onPrefix, onComment, onVersion;
1171
+ if (quadCallback && (quadCallback.onQuad || quadCallback.onPrefix || quadCallback.onComment || quadCallback.onVersion)) {
1021
1172
  onQuad = quadCallback.onQuad;
1022
1173
  onPrefix = quadCallback.onPrefix;
1023
1174
  onComment = quadCallback.onComment;
1175
+ onVersion = quadCallback.onVersion;
1024
1176
  }
1025
1177
  else {
1026
1178
  onQuad = quadCallback;
1027
1179
  onPrefix = prefixCallback;
1180
+ onVersion = versionCallback;
1028
1181
  }
1029
1182
  // The read callback is the next function to be executed when a token arrives.
1030
1183
  // We start reading in the top context.
@@ -1034,6 +1187,7 @@ export default class N3Parser {
1034
1187
  this._prefixes._ = this._blankNodePrefix ? this._blankNodePrefix.substr(2)
1035
1188
  : `b${blankNodePrefix++}_`;
1036
1189
  this._prefixCallback = onPrefix || noop;
1190
+ this._versionCallback = onVersion || noop;
1037
1191
  this._inversePredicate = false;
1038
1192
  this._quantified = Object.create(null);
1039
1193
 
@@ -1089,16 +1243,16 @@ function initDataFactory(parser, factory) {
1089
1243
  parser.DEFAULTGRAPH = factory.defaultGraph();
1090
1244
 
1091
1245
  // Set common named nodes
1092
- parser.RDF_FIRST = factory.namedNode(namespaces.rdf.first);
1093
- parser.RDF_REST = factory.namedNode(namespaces.rdf.rest);
1094
- parser.RDF_NIL = factory.namedNode(namespaces.rdf.nil);
1095
- parser.N3_FORALL = factory.namedNode(namespaces.r.forAll);
1096
- parser.N3_FORSOME = factory.namedNode(namespaces.r.forSome);
1246
+ parser.RDF_FIRST = factory.namedNode(namespaces.rdf.first);
1247
+ parser.RDF_REST = factory.namedNode(namespaces.rdf.rest);
1248
+ parser.RDF_NIL = factory.namedNode(namespaces.rdf.nil);
1249
+ parser.RDF_REIFIES = factory.namedNode(namespaces.rdf.reifies);
1250
+ parser.N3_FORALL = factory.namedNode(namespaces.r.forAll);
1251
+ parser.N3_FORSOME = factory.namedNode(namespaces.r.forSome);
1097
1252
  parser.ABBREVIATIONS = {
1098
1253
  'a': factory.namedNode(namespaces.rdf.type),
1099
1254
  '=': factory.namedNode(namespaces.owl.sameAs),
1100
1255
  '>': factory.namedNode(namespaces.log.implies),
1101
- '<': factory.namedNode(namespaces.log.isImpliedBy),
1102
1256
  };
1103
1257
  parser.QUANTIFIERS_GRAPH = factory.namedNode('urn:n3:quantifiers');
1104
1258
  }
package/src/N3Store.js CHANGED
@@ -163,7 +163,7 @@ export default class N3Store {
163
163
  this._graphs = Object.create(null);
164
164
 
165
165
  // Shift parameters if `quads` is not given
166
- if (!options && quads && !quads[0] && !(typeof quads.match === 'function'))
166
+ if (!options && quads && !quads[0])
167
167
  options = quads, quads = null;
168
168
  options = options || {};
169
169
  this._factory = options.factory || N3DataFactory;
@@ -175,7 +175,7 @@ export default class N3Store {
175
175
 
176
176
  // Add quads if passed
177
177
  if (quads)
178
- this.addAll(quads);
178
+ this.addQuads(quads);
179
179
  }
180
180
 
181
181
  // ## Public properties
@@ -601,7 +601,7 @@ export default class N3Store {
601
601
  // Setting any field to `undefined` or `null` indicates a wildcard.
602
602
  some(callback, subject, predicate, object, graph) {
603
603
  for (const quad of this.readQuads(subject, predicate, object, graph))
604
- if (callback(quad, this))
604
+ if (callback(quad))
605
605
  return true;
606
606
  return false;
607
607
  }
@@ -1134,28 +1134,27 @@ class DatasetCoreAndReadableStream extends Readable {
1134
1134
 
1135
1135
  const graphs = n3Store._getGraphs(graph);
1136
1136
  for (const graphKey in graphs) {
1137
- let subjects, predicates, objects, content;
1138
- if (content = graphs[graphKey]) {
1139
- if (!subjectId && predicateId) {
1140
- if (predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId])) {
1141
- subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
1142
- objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
1143
- }
1144
- }
1145
- else if (objectId) {
1146
- if (objects = indexMatch(content.objects, [objectId, subjectId, predicateId])) {
1147
- subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId]);
1148
- predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
1149
- }
1137
+ let subjects, predicates, objects;
1138
+
1139
+ if (!subjectId && predicateId) {
1140
+ if (predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId])) {
1141
+ subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
1142
+ objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
1150
1143
  }
1151
- else if (subjects = indexMatch(content.subjects, [subjectId, predicateId, objectId])) {
1152
- predicates = indexMatch(content.predicates, [predicateId, objectId, subjectId]);
1153
- objects = indexMatch(content.objects, [objectId, subjectId, predicateId]);
1144
+ }
1145
+ else if (objectId) {
1146
+ if (objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId])) {
1147
+ subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId]);
1148
+ predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
1154
1149
  }
1155
-
1156
- if (subjects)
1157
- newStore._graphs[graphKey] = { subjects, predicates, objects };
1158
1150
  }
1151
+ else if (subjects = indexMatch(graphs[graphKey].subjects, [subjectId, predicateId, objectId])) {
1152
+ predicates = indexMatch(graphs[graphKey].predicates, [predicateId, objectId, subjectId]);
1153
+ objects = indexMatch(graphs[graphKey].objects, [objectId, subjectId, predicateId]);
1154
+ }
1155
+
1156
+ if (subjects)
1157
+ newStore._graphs[graphKey] = { subjects, predicates, objects };
1159
1158
  }
1160
1159
  newStore._size = null;
1161
1160
  }
package/src/N3Writer.js CHANGED
@@ -2,8 +2,6 @@
2
2
  import namespaces from './IRIs';
3
3
  import { default as N3DataFactory, Term } from './N3DataFactory';
4
4
  import { isDefaultGraph } from './N3Util';
5
- import BaseIRI from './BaseIRI';
6
- import { escapeRegex } from './Util';
7
5
 
8
6
  const DEFAULTGRAPH = N3DataFactory.defaultGraph();
9
7
 
@@ -60,7 +58,9 @@ export default class N3Writer {
60
58
  this._prefixIRIs = Object.create(null);
61
59
  options.prefixes && this.addPrefixes(options.prefixes);
62
60
  if (options.baseIRI) {
63
- this._baseIri = new BaseIRI(options.baseIRI);
61
+ this._baseMatcher = new RegExp(`^${escapeRegex(options.baseIRI)
62
+ }${options.baseIRI.endsWith('/') ? '' : '[#?]'}`);
63
+ this._baseLength = options.baseIRI.length;
64
64
  }
65
65
  }
66
66
  else {
@@ -153,9 +153,8 @@ export default class N3Writer {
153
153
  }
154
154
  let iri = entity.value;
155
155
  // Use relative IRIs if requested and possible
156
- if (this._baseIri) {
157
- iri = this._baseIri.toRelative(iri);
158
- }
156
+ if (this._baseMatcher && this._baseMatcher.test(iri))
157
+ iri = iri.substr(this._baseLength);
159
158
  // Escape special characters
160
159
  if (escape.test(iri))
161
160
  iri = iri.replace(escapeAll, characterReplacer);
@@ -173,8 +172,9 @@ export default class N3Writer {
173
172
  value = value.replace(escapeAll, characterReplacer);
174
173
 
175
174
  // Write a language-tagged literal
175
+ const direction = literal.direction ? `--${literal.direction}` : '';
176
176
  if (literal.language)
177
- return `"${value}"@${literal.language}`;
177
+ return `"${value}"@${literal.language}${direction}`;
178
178
 
179
179
  // Write dedicated literals per data type
180
180
  if (this._lineMode) {
@@ -395,3 +395,7 @@ function characterReplacer(character) {
395
395
  }
396
396
  return result;
397
397
  }
398
+
399
+ function escapeRegex(regex) {
400
+ return regex.replace(/[\]\/\(\)\*\+\?\.\\\$]/g, '\\$&');
401
+ }
package/src/index.js CHANGED
@@ -7,7 +7,6 @@ import Reasoner, { getRulesFromDataset } from './N3Reasoner';
7
7
  import StreamParser from './N3StreamParser';
8
8
  import StreamWriter from './N3StreamWriter';
9
9
  import * as Util from './N3Util';
10
- import BaseIRI from './BaseIRI';
11
10
 
12
11
  import {
13
12
  default as DataFactory,
@@ -37,7 +36,6 @@ export {
37
36
  StreamWriter,
38
37
  Util,
39
38
  Reasoner,
40
- BaseIRI,
41
39
 
42
40
  DataFactory,
43
41
 
@@ -67,7 +65,6 @@ export default {
67
65
  StreamWriter,
68
66
  Util,
69
67
  Reasoner,
70
- BaseIRI,
71
68
 
72
69
  DataFactory,
73
70