From bc0b64ef1198420c2821d98f9baaa5012d588dc0 Mon Sep 17 00:00:00 2001 From: tpluscode Date: Thu, 16 Jul 2020 09:54:55 +0200 Subject: [PATCH] feat: graph traversals --- lib/Clownface.js | 16 ++++++++++ lib/Context.js | 9 ++++-- test/Clownface/fromGraph.js | 59 +++++++++++++++++++++++++++++++++++++ test/Clownface/index.js | 1 + 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 test/Clownface/fromGraph.js diff --git a/lib/Clownface.js b/lib/Clownface.js index fd11e77..d6f3428 100644 --- a/lib/Clownface.js +++ b/lib/Clownface.js @@ -421,6 +421,22 @@ class Clownface { return this } + fromGraph (graph) { + if (typeof graph === 'undefined') { + throw new Error('graph parameter is required') + } + + const context = this._context.map(context => context.clone({ + graph: graph === null ? undefined : graph + })) + + return Clownface.fromContext(context) + } + + get defaultGraph () { + return rdf.defaultGraphInstance + } + _toTermArray (predicates, type, languageOrDatatype) { return toTermArray(predicates, type, languageOrDatatype, this.factory) } diff --git a/lib/Context.js b/lib/Context.js index 5db9e70..07ab298 100644 --- a/lib/Context.js +++ b/lib/Context.js @@ -12,8 +12,13 @@ class Context { this.term = term(value, undefined, undefined, factory) } - clone ({ dataset = this.dataset, graph = this.graph, value, factory = this.factory, namespace = this.namespace }) { - return new Context({ dataset, graph, value, factory, namespace }) + clone ({ dataset = this.dataset, graph, value, factory = this.factory, namespace = this.namespace }) { + let g = graph + if (typeof graph === 'undefined') { + g = undefined + } + + return new Context({ dataset, graph: g, value, factory, namespace }) } has (predicate, object) { diff --git a/test/Clownface/fromGraph.js b/test/Clownface/fromGraph.js new file mode 100644 index 0000000..b6b9fd8 --- /dev/null +++ b/test/Clownface/fromGraph.js @@ -0,0 +1,59 @@ +/* global describe, it */ + +const assert = require('assert') +const { rdfs } = require('@tpluscode/rdf-ns-builders') +const clownface = require('../..') +const rdf = require('../support/factory') +const ns = require('../support/namespace') + +describe('fromGraph', () => { + it('called with graph changes context to same term in named graph', () => { + const term = ns.ex.Foo + const dataset = rdf.dataset([ + rdf.quad(term, rdfs.label, rdf.literal('default graph')), + rdf.quad(term, rdfs.label, rdf.literal('named graph'), ns.ex.NamedGraph) + ]) + const pointer = clownface({ dataset, term }) + + const movedPointer = pointer.fromGraph(ns.ex.NamedGraph) + + assert.deepStrictEqual(movedPointer.out(rdfs.label).value, 'named graph') + }) + + it('called with null changes context to same term across all graphs', () => { + const term = ns.ex.Foo + const dataset = rdf.dataset([ + rdf.quad(term, rdfs.label, rdf.literal('default graph')), + rdf.quad(term, rdfs.label, rdf.literal('named graph'), ns.ex.NamedGraph) + ]) + const pointer = clownface({ dataset, term, graph: ns.ex.NamedGraph }) + + const movedPointer = pointer.fromGraph(null) + + assert.deepStrictEqual(movedPointer.out(rdfs.label).values.length, 2) + }) + + it('called with undefined should throw', () => { + const term = ns.ex.Foo + const dataset = rdf.dataset([ + rdf.quad(term, rdfs.label, rdf.literal('default graph')), + rdf.quad(term, rdfs.label, rdf.literal('named graph'), ns.ex.NamedGraph) + ]) + const pointer = clownface({ dataset, term }) + + assert.throws(() => pointer.fromGraph(undefined)) + }) + + it('called with default graph instance changes context to same term in default graph', () => { + const term = ns.ex.Foo + const dataset = rdf.dataset([ + rdf.quad(term, rdfs.label, rdf.literal('default graph')), + rdf.quad(term, rdfs.label, rdf.literal('named graph'), ns.ex.NamedGraph) + ]) + const pointer = clownface({ dataset, term }) + + const movedPointer = pointer.fromGraph(rdf.defaultGraphInstance) + + assert.deepStrictEqual(movedPointer.out(rdfs.label).value, 'default graph') + }) +}) diff --git a/test/Clownface/index.js b/test/Clownface/index.js index 3dff800..d8e7a32 100644 --- a/test/Clownface/index.js +++ b/test/Clownface/index.js @@ -28,4 +28,5 @@ describe('Clownface', () => { require('./deleteIn') require('./deleteOut') require('./deleteList') + require('./fromGraph') })