From a751dc267efc8d45bd5738915e9febbc9f1163f3 Mon Sep 17 00:00:00 2001 From: Laurens Rietveld Date: Tue, 24 Jan 2023 14:42:29 +0100 Subject: [PATCH 1/2] added graphs argument --- README.md | 6 +++++ src/N3Writer.js | 17 +++++++++--- test/N3Writer-test.js | 62 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index cf5e554d..88666a64 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,12 @@ To write N-Triples (or N-Quads) instead, pass a `format` argument upon creation const writer1 = new N3.Writer({ format: 'N-Triples' }); const writer2 = new N3.Writer({ format: 'application/trig' }); ``` +To exclude the graph name from the serialization, pass a `graphs` argument upon creation: +```JavaScript +const writer3 = new N3.Writer({ graphs: 'keep' }); // Keeps the graph names (default) +const writer4 = new N3.Writer({ graphs: 'ignore' }); // Ignores the graph name +const writer5 = new N3.Writer({ graphs: 'error' }); // Throws an error when writing a graph name +``` ### From quads to an RDF stream diff --git a/src/N3Writer.js b/src/N3Writer.js index abc3852f..b00c4b63 100644 --- a/src/N3Writer.js +++ b/src/N3Writer.js @@ -35,6 +35,7 @@ export default class N3Writer { options = outputStream, outputStream = null; options = options || {}; this._lists = options.lists; + this._graphs = options.graphs || 'keep'; // If no output stream given, send the output as string through the end callback if (!outputStream) { @@ -84,8 +85,11 @@ export default class N3Writer { // ### `_writeQuad` writes the quad to the output stream _writeQuad(subject, predicate, object, graph, done) { try { + if (this._graphs === 'error' && !DEFAULTGRAPH.equals(graph)) { + done(new Error('Encountered graph name, this is forbidden.')); + } // Write the graph's label if it has changed - if (!graph.equals(this._graph)) { + if (this._graphs === 'keep' && !graph.equals(this._graph)) { // Close the previous graph and start the new one this._write((this._subject === null ? '' : (this._inDefaultGraph ? '.\n' : '\n}\n')) + (DEFAULTGRAPH.equals(graph) ? '' : `${this._encodeIriOrBlank(graph)} {\n`)); @@ -117,15 +121,20 @@ export default class N3Writer { _writeQuadLine(subject, predicate, object, graph, done) { // Write the quad without prefixes delete this._prefixMatch; - this._write(this.quadToString(subject, predicate, object, graph), done); + this._write(this.quadToString(subject, predicate, object, graph, done), done); } // ### `quadToString` serializes a quad as a string - quadToString(subject, predicate, object, graph) { + quadToString(subject, predicate, object, graph, done) { + if (this._graphs === 'error' && !DEFAULTGRAPH.equals(graph)) { + const err = new Error('Encountered graph name, this is forbidden.'); + if (done) return done(err); + throw err; + } return `${this._encodeSubject(subject)} ${ this._encodeIriOrBlank(predicate)} ${ this._encodeObject(object) - }${graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; + }${this._graphs === 'keep' && graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; } // ### `quadsToString` serializes an array of quads as a string diff --git a/test/N3Writer-test.js b/test/N3Writer-test.js index 33660145..30d36513 100644 --- a/test/N3Writer-test.js +++ b/test/N3Writer-test.js @@ -31,6 +31,17 @@ describe('Writer', () => { const writer = new Writer(); writer.quadToString(new NamedNode('a'), new NamedNode('b'), new NamedNode('c'), new NamedNode('g')).should.equal(' .\n'); }); + it('should throw error when it\'s forbidden to pass graphname', done => { + const writer = new Writer({ graphs: 'error' }); + try { + writer.quadToString(new NamedNode('a'), new NamedNode('b'), new NamedNode('c'), new NamedNode('g')).should.equal(' .\n'); + } + catch (error) { + error.should.be.an.instanceof(Error); + error.should.have.property('message', 'Encountered graph name, this is forbidden.'); + done(); + } + }); it('should serialize an array of triples', () => { const writer = new Writer(); @@ -656,6 +667,57 @@ describe('Writer', () => { }); }); + it('ignores the graph name when needed in N-Quads mode', done => { + const writer = new Writer({ graphs: 'ignore', format: 'n-quads' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g'))); + writer.end((error, output) => { + output.should.equal(' .\n'); + done(error); + }); + }); + + it('throws an graph-found error needed in N-Quads mode', done => { + const writer = new Writer({ graphs: 'error', format: 'n-quads' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g')), error => { + error.should.be.an.instanceof(Error); + error.should.have.property('message', 'Encountered graph name, this is forbidden.'); + done(); + }); + }); + it('ignores the graph name when needed', done => { + const writer = new Writer({ graphs: 'ignore' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g'))); + writer.end((error, output) => { + output.should.equal(' .\n'); + done(error); + }); + }); + + it('throws an graph-found error needed', done => { + const writer = new Writer({ graphs: 'error' }); + writer.addQuad(new Quad( + new NamedNode('a:a'), + new NamedNode('b:b'), + new NamedNode('c:c'), + new NamedNode('g:g')), error => { + error.should.be.an.instanceof(Error); + error.should.have.property('message', 'Encountered graph name, this is forbidden.'); + done(); + }); + }); + it('should end when the end option is not set', done => { const outputStream = new QuickStream(), writer = new Writer(outputStream, {}); outputStream.should.have.property('ended', false); From a49385f328b5ee265349de0abed3ee3a4c309a4e Mon Sep 17 00:00:00 2001 From: Jesse Wright <63333554+jeswr@users.noreply.github.com> Date: Fri, 24 Mar 2023 21:11:23 +1100 Subject: [PATCH 2/2] chore: refactor for review https://github.com/rdfjs/N3.js/pull/319#discussion_r1147292454 --- README.md | 4 ++-- src/N3Writer.js | 20 +++++++++++--------- test/N3Writer-test.js | 6 +++--- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 88666a64..478a984d 100644 --- a/README.md +++ b/README.md @@ -201,8 +201,8 @@ const writer2 = new N3.Writer({ format: 'application/trig' }); ``` To exclude the graph name from the serialization, pass a `graphs` argument upon creation: ```JavaScript -const writer3 = new N3.Writer({ graphs: 'keep' }); // Keeps the graph names (default) -const writer4 = new N3.Writer({ graphs: 'ignore' }); // Ignores the graph name +const writer3 = new N3.Writer({ graphs: 'keep' }); // Keeps the graph names (default) +const writer4 = new N3.Writer({ graphs: 'drop' }); // Drops the graph name const writer5 = new N3.Writer({ graphs: 'error' }); // Throws an error when writing a graph name ``` diff --git a/src/N3Writer.js b/src/N3Writer.js index b00c4b63..6dccc1be 100644 --- a/src/N3Writer.js +++ b/src/N3Writer.js @@ -35,7 +35,9 @@ export default class N3Writer { options = outputStream, outputStream = null; options = options || {}; this._lists = options.lists; - this._graphs = options.graphs || 'keep'; + this._keepGraphs = !options.graphs || options.graphs === 'keep'; + this._errorOnGraphs = options.graphs === 'error'; + // If no output stream given, send the output as string through the end callback if (!outputStream) { @@ -85,11 +87,11 @@ export default class N3Writer { // ### `_writeQuad` writes the quad to the output stream _writeQuad(subject, predicate, object, graph, done) { try { - if (this._graphs === 'error' && !DEFAULTGRAPH.equals(graph)) { - done(new Error('Encountered graph name, this is forbidden.')); + if (this._errorOnGraphs && !DEFAULTGRAPH.equals(graph)) { + done(new Error('The chosen serialization settings do not support triples in a non-default graph.')); } // Write the graph's label if it has changed - if (this._graphs === 'keep' && !graph.equals(this._graph)) { + if (this._keepGraphs && !graph.equals(this._graph)) { // Close the previous graph and start the new one this._write((this._subject === null ? '' : (this._inDefaultGraph ? '.\n' : '\n}\n')) + (DEFAULTGRAPH.equals(graph) ? '' : `${this._encodeIriOrBlank(graph)} {\n`)); @@ -126,15 +128,15 @@ export default class N3Writer { // ### `quadToString` serializes a quad as a string quadToString(subject, predicate, object, graph, done) { - if (this._graphs === 'error' && !DEFAULTGRAPH.equals(graph)) { - const err = new Error('Encountered graph name, this is forbidden.'); - if (done) return done(err); - throw err; + if (this._errorOnGraphs && !DEFAULTGRAPH.equals(graph)) { + const error = new Error('The chosen serialization settings do not support triples in a non-default graph.'); + if (done) return done(error); + throw error; } return `${this._encodeSubject(subject)} ${ this._encodeIriOrBlank(predicate)} ${ this._encodeObject(object) - }${this._graphs === 'keep' && graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; + }${this._keepGraphs && graph && graph.value ? ` ${this._encodeIriOrBlank(graph)} .\n` : ' .\n'}`; } // ### `quadsToString` serializes an array of quads as a string diff --git a/test/N3Writer-test.js b/test/N3Writer-test.js index 30d36513..54f01a17 100644 --- a/test/N3Writer-test.js +++ b/test/N3Writer-test.js @@ -38,7 +38,7 @@ describe('Writer', () => { } catch (error) { error.should.be.an.instanceof(Error); - error.should.have.property('message', 'Encountered graph name, this is forbidden.'); + error.should.have.property('message', 'The chosen serialization settings do not support triples in a non-default graph.'); done(); } }); @@ -688,7 +688,7 @@ describe('Writer', () => { new NamedNode('c:c'), new NamedNode('g:g')), error => { error.should.be.an.instanceof(Error); - error.should.have.property('message', 'Encountered graph name, this is forbidden.'); + error.should.have.property('message', 'The chosen serialization settings do not support triples in a non-default graph.'); done(); }); }); @@ -713,7 +713,7 @@ describe('Writer', () => { new NamedNode('c:c'), new NamedNode('g:g')), error => { error.should.be.an.instanceof(Error); - error.should.have.property('message', 'Encountered graph name, this is forbidden.'); + error.should.have.property('message', 'The chosen serialization settings do not support triples in a non-default graph.'); done(); }); });