Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/quad-patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rdfjs/types": minor
---

Add `QuadPattern` and `TermPattern` types and an optional `QuadPatternDatasetCore` interface whose `match` accepts patterns for the components of quad terms (triple terms)
17 changes: 17 additions & 0 deletions data-model.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,23 @@ export interface Quad extends BaseQuad {
equals<T extends Term = Term>(other: T | null | undefined): this is T;
}

/**
* A pattern that matches quad terms (triple terms) by their components.
*
* The entries are patterns for the subject, predicate, object and graph of the quad term, in that order.
* A missing, `null` or `undefined` entry matches any component, a term matches components it equals,
* and a nested `QuadPattern` matches nested quad terms in the same way.
*
* For example, `[s, null, null]` matches every quad term with subject `s`.
*/
export type QuadPattern = readonly [subject?: TermPattern, predicate?: TermPattern, object?: TermPattern, graph?: TermPattern];

/**
* A pattern for one position of a quad: a term to match exactly, a `QuadPattern` to match quad terms by their
* components, or `null` or `undefined` to match any term.
*/
export type TermPattern = Term | QuadPattern | null | undefined;

/**
* A factory for instantiating RDF terms and quads.
*/
Expand Down
24 changes: 23 additions & 1 deletion dataset.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* Dataset Interfaces */
/* https://rdf.js.org/dataset-spec/ */

import { Quad, BaseQuad, Term } from './data-model.js';
import { Quad, BaseQuad, Term, TermPattern } from './data-model.js';
import { Stream } from './stream.js';

export interface DatasetCore<OutQuad extends BaseQuad = Quad, InQuad extends BaseQuad = OutQuad> {
Expand Down Expand Up @@ -202,3 +202,25 @@ export interface DatasetFactory<OutQuad extends BaseQuad = Quad, InQuad extends
*/
dataset(quads?: Dataset<InQuad>|InQuad[]): D;
}

/**
* A `DatasetCore` whose `match` method also accepts `QuadPattern`s, to match quads by the components of the quad terms
* (triple terms) they contain.
*
* This interface is optional and extends `DatasetCore` without changing it,
* so datasets that do not implement it keep matching quad terms exactly.
*/
export interface QuadPatternDatasetCore<OutQuad extends BaseQuad = Quad, InQuad extends BaseQuad = OutQuad> extends DatasetCore<OutQuad, InQuad> {
/**
* Returns a new dataset that is comprised of all quads in the current instance matching the given arguments.
*
* Arguments that are terms or `null`/`undefined` are matched as in `DatasetCore.match`.
* A `QuadPattern` argument matches quad terms whose components match its entries.
*
* @param subject The optional exact subject, or pattern of a quad term subject, to match.
* @param predicate The optional exact predicate to match.
* @param object The optional exact object, or pattern of a quad term object, to match.
* @param graph The optional exact graph, or pattern of a quad term graph, to match.
*/
match(subject?: TermPattern, predicate?: Term | null, object?: TermPattern, graph?: TermPattern): QuadPatternDatasetCore<OutQuad, InQuad>;
}
27 changes: 26 additions & 1 deletion rdf-js-tests.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { BlankNode, DataFactory, Dataset, DatasetCore, DatasetCoreFactory, DatasetFactory, DefaultGraph, Literal,
NamedNode, Quad, BaseQuad, Sink, Source, Store, Stream, Term, Variable, Quad_Graph, Quad_Subject } from "./index.js";
NamedNode, Quad, BaseQuad, Sink, Source, Store, Stream, Term, Variable, Quad_Graph, Quad_Subject,
QuadPattern, QuadPatternDatasetCore, TermPattern } from "./index.js";
import { EventEmitter } from "events";

function test_terms() {
Expand All @@ -19,7 +20,7 @@

const namedNodeConstant: NamedNode<'http://example.org'> = <any> {};
const constantIri: 'http://example.org' = namedNodeConstant.value;
// @ts-expect-error

Check warning on line 23 in rdf-js-tests.ts

View workflow job for this annotation

GitHub Actions / build (20)

Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer

Check warning on line 23 in rdf-js-tests.ts

View workflow job for this annotation

GitHub Actions / build (18)

Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer

Check warning on line 23 in rdf-js-tests.ts

View workflow job for this annotation

GitHub Actions / build (lts/*)

Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer
const otherConstantIri: 'http://not-example.org' = namedNodeConstant.value;
// @ts-expect-error
const otherNamedNodeConstant: NamedNode<'http://not-example.org'> = namedNodeConstant;
Expand Down Expand Up @@ -543,3 +544,27 @@
const datasetFilter: Dataset = datasetExt.filter();
const datasetDifference: Dataset = datasetExt.difference();
}

function testQuadPatterns() {
const term: Term = <any> {};
const namedNode: NamedNode = <any> {};

const any: QuadPattern = [];
const subjectOnly: QuadPattern = [term];
const full: QuadPattern = [term, null, undefined, term];
const nested: QuadPattern = [[namedNode, null, null], namedNode, null];
const termPatterns: TermPattern[] = [term, null, undefined, nested];
// @ts-expect-error A quad pattern has at most four positions
const tooLong: QuadPattern = [term, term, term, term, term];

const dataset: QuadPatternDatasetCore = <any> {};
const match1: QuadPatternDatasetCore = dataset.match(null, namedNode, [namedNode, null, null]);
const match2: QuadPatternDatasetCore = dataset.match(nested, null, null, null);
const match3: DatasetCore = dataset.match(term, term, term, term);
// @ts-expect-error Predicates cannot be quad terms
dataset.match(null, [namedNode, null, null]);

// Existing DatasetCore implementations and callers are unaffected
const datasetCore: DatasetCore = dataset;
const coreMatch: DatasetCore = datasetCore.match(term, term, term, term);
}
Loading