You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

118 lines
3.6 KiB

import type { GraphNode, QuadMatch, SubjectNode } from "@ldo/rdf-utils";
import type { BlankNode, Dataset, NamedNode } from "@rdfjs/types";
import { createSubjectHandler } from "./subjectProxy/createSubjectHandler";
import type { SubjectProxy } from "./subjectProxy/SubjectProxy";
import type { SetProxy } from "./setProxy/SetProxy";
import type { ContextUtil } from "./ContextUtil";
import type { LanguageOrdering } from "./language/languageTypes";
import { namedNode } from "@rdfjs/data-model";
import type { RawValue } from "./util/RawObject";
import { createNewSetProxy } from "./setProxy/createNewSetProxy";
export interface ProxyContextOptions {
dataset: Dataset;
contextUtil: ContextUtil;
writeGraphs: GraphNode[];
languageOrdering: LanguageOrdering;
state?: Record<string, unknown>;
}
const rdfType = namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
/**
* This file keeps track of the target objects used in the proxies.
* The reason is so that JSON.stringify does not recurse inifinitely
* when it encounters a circular object.
*/
export class ProxyContext {
private subjectMap: Map<string, SubjectProxy> = new Map();
private setMap: Map<string, SetProxy<NonNullable<RawValue>>> = new Map();
readonly dataset: Dataset;
readonly contextUtil: ContextUtil;
readonly writeGraphs: GraphNode[];
readonly languageOrdering: LanguageOrdering;
public state: Record<string, unknown>;
constructor(options: ProxyContextOptions) {
this.dataset = options.dataset;
this.contextUtil = options.contextUtil;
this.writeGraphs = options.writeGraphs;
this.languageOrdering = options.languageOrdering;
this.state = options.state || {};
}
public createSubjectProxy(node: NamedNode | BlankNode): SubjectProxy {
if (!this.subjectMap.has(node.value)) {
const proxy = this.createNewSubjectProxy(node);
this.subjectMap.set(node.value, proxy);
}
return this.subjectMap.get(node.value) as SubjectProxy;
}
protected createNewSubjectProxy(node: NamedNode | BlankNode): SubjectProxy {
return new Proxy(
{ "@id": node },
createSubjectHandler(this),
) as unknown as SubjectProxy;
}
private getSetKey(...quadMatch: QuadMatch) {
return `${quadMatch[0]?.value || "undefined"}|${
quadMatch[1]?.value || "undefined"
}|${quadMatch[2]?.value || "undefined"}|${
quadMatch[3]?.value || "undefined"
}`;
}
public createSetProxy(
quadMatch: QuadMatch,
isSubjectOriented?: boolean,
isLangStringSet?: boolean,
): SetProxy {
const key = this.getSetKey(...quadMatch);
if (!this.setMap.has(key)) {
const proxy = this.createNewSetProxy(
quadMatch,
isSubjectOriented,
isLangStringSet,
);
this.setMap.set(key, proxy);
}
return this.setMap.get(key)!;
}
protected createNewSetProxy(
quadMatch: QuadMatch,
isSubjectOriented?: boolean,
isLangStringSet?: boolean,
) {
return createNewSetProxy(
quadMatch,
isSubjectOriented ?? false,
this,
isLangStringSet,
);
}
public duplicate(alternativeOptions: Partial<ProxyContextOptions>) {
const fullOptions: ProxyContextOptions = {
...{
dataset: this.dataset,
contextUtil: this.contextUtil,
writeGraphs: this.writeGraphs,
languageOrdering: this.languageOrdering,
},
...alternativeOptions,
};
return new ProxyContext(fullOptions);
}
public getRdfType(subjectNode: SubjectNode): NamedNode[] {
return this.dataset
.match(subjectNode, rdfType)
.toArray()
.map((quad) => quad.object)
.filter((object): object is NamedNode => object.termType === "NamedNode");
}
}