diff --git a/light9/web/patch.test.ts b/light9/web/patch.test.ts --- a/light9/web/patch.test.ts +++ b/light9/web/patch.test.ts @@ -1,2 +1,45 @@ import { assert, describe, expect, it } from "vitest"; +import { Quad, NamedNode } from "n3"; +import { Patch, QuadPattern } from "./patch"; +import * as N3 from "n3"; + +const node1 = new NamedNode("http://example.com/node1"); +const node2 = new NamedNode("http://example.com/node2"); +const node3 = new NamedNode("http://example.com/node3"); + +function QP( + subject: N3.Quad_Subject | null, // + predicate: N3.Quad_Predicate | null, + object: N3.Quad_Object | null, + graph: N3.Quad_Graph | null +): QuadPattern { + return { subject, predicate, object, graph }; +} + +describe("Patch.matches", () => { + it("matches any quads against an open pattern", () => { + const quad1 = new Quad(node1, node2, node3); + const quad2 = new Quad(node1, node2, node3); + const quad3 = new Quad(node1, node2, node3); + + const pattern = QP(null, null, null, null); + + const p = new Patch([quad1, quad2], [quad3]); + + assert.isTrue(p.matches(pattern)); + }); + it("doesn't match when the patch is empty", () => { + const p = new Patch([], []); + assert.isFalse(p.matches(QP(null, null, null, null))); + }); + it("compares terms correctly", () => { + assert.isTrue(new Patch([new Quad(node1, node2, node3)], []).matches(QP(node1, null, null, null))); + assert.isFalse(new Patch([new Quad(node1, node2, node3)], []).matches(QP(node2, null, null, null))); + }); + it("matches on just one set term", () => { + assert.isTrue(new Patch([new Quad(node1, node2, node3)], []).matches(QP(node1, null, null, null))); + assert.isTrue(new Patch([new Quad(node1, node2, node3)], []).matches(QP(null, node2, null, null))); + assert.isTrue(new Patch([new Quad(node1, node2, node3)], []).matches(QP(null, null, node3, null))); + }); +}); diff --git a/light9/web/patch.ts b/light9/web/patch.ts --- a/light9/web/patch.ts +++ b/light9/web/patch.ts @@ -2,6 +2,15 @@ import * as async from "async"; import debug from "debug"; import * as N3 from "n3"; import { NamedNode, Parser, Quad, Writer } from "n3"; +import { isEqualWith } from "lodash"; + +export interface QuadPattern { + subject: N3.Quad_Subject | null; + predicate: N3.Quad_Predicate | null; + object: N3.Quad_Object | null; // literals allowed? needs review. probably 'yes'. + graph: N3.Quad_Graph | null; +} + const log = debug("patch"); export class Patch { @@ -31,6 +40,18 @@ export class Patch { ); } + matches(pat: QuadPattern): boolean { + const allQuads = this.dels.concat(this.adds); + return allQuads.some((quad) => { + return ( + (pat.subject === null || pat.subject.equals(quad.subject)) && // + (pat.predicate === null || pat.predicate.equals(quad.predicate)) && // + (pat.object === null || pat.object.equals(quad.object)) && // + (pat.graph === null || pat.graph.equals(quad.graph)) + ); + }); + } + isEmpty() { return !this.dels.length && !this.adds.length; }