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.
177 lines
5.8 KiB
177 lines
5.8 KiB
import { quad } from "@rdfjs/data-model";
|
|
import type { NamedNode } from "@rdfjs/types";
|
|
import type { ObjectNode, QuadMatch, SubjectNode } from "@ldo/rdf-utils";
|
|
import type { ObjectJsonRepresentation } from "../util/nodeToJsonldRepresentation";
|
|
import { nodeToJsonldRepresentation } from "../util/nodeToJsonldRepresentation";
|
|
import type { ArrayMethodBuildersType } from "./arrayMethods";
|
|
import { arrayMethodsBuilders, methodNames } from "./arrayMethods";
|
|
import {
|
|
_getNodeAtIndex,
|
|
_getUnderlyingArrayTarget,
|
|
_getUnderlyingDataset,
|
|
_getUnderlyingMatch,
|
|
_isSubjectOriented,
|
|
_proxyContext,
|
|
} from "../types";
|
|
import { modifyArray } from "./modifyArray";
|
|
import type { ProxyContext } from "../ProxyContext";
|
|
import { NodeSet } from "../util/NodeSet";
|
|
import { filterQuadsByLanguageOrdering } from "../language/languageUtils";
|
|
|
|
export type ArrayProxyTarget = [
|
|
quadMatch: QuadMatch,
|
|
curArray: ObjectNode[],
|
|
isSubjectOriented?: boolean,
|
|
isLangStringArray?: boolean,
|
|
];
|
|
|
|
function updateArrayOrder(
|
|
target: ArrayProxyTarget,
|
|
proxyContext: ProxyContext,
|
|
): void {
|
|
let quads = proxyContext.dataset.match(...target[0]);
|
|
if (target[3]) {
|
|
// Is lang string array
|
|
quads = filterQuadsByLanguageOrdering(quads, proxyContext.languageOrdering);
|
|
}
|
|
const datasetObjects = new NodeSet();
|
|
quads.toArray().forEach((quad) => {
|
|
// If this this a subject-oriented document
|
|
if (target[2]) {
|
|
datasetObjects.add(quad.subject as SubjectNode);
|
|
} else {
|
|
datasetObjects.add(quad.object as ObjectNode);
|
|
}
|
|
});
|
|
const processedObjects: ObjectNode[] = [];
|
|
target[1].forEach((arrItem) => {
|
|
if (datasetObjects.has(arrItem)) {
|
|
processedObjects.push(arrItem);
|
|
datasetObjects.delete(arrItem);
|
|
}
|
|
});
|
|
datasetObjects.toArray().forEach((datasetObject) => {
|
|
processedObjects.push(datasetObject);
|
|
});
|
|
target[1] = processedObjects;
|
|
}
|
|
|
|
function getProcessedArray(
|
|
target: ArrayProxyTarget,
|
|
proxyContext: ProxyContext,
|
|
): ObjectJsonRepresentation[] {
|
|
return target[1].map((node) => {
|
|
return nodeToJsonldRepresentation(node, proxyContext);
|
|
});
|
|
}
|
|
|
|
export function createArrayHandler(
|
|
proxyContext: ProxyContext,
|
|
): ProxyHandler<ArrayProxyTarget> {
|
|
return {
|
|
get(target, key, ...rest) {
|
|
switch (key) {
|
|
case _getUnderlyingDataset:
|
|
return proxyContext.dataset;
|
|
case _getUnderlyingMatch:
|
|
return target[0];
|
|
case _isSubjectOriented:
|
|
return target[2];
|
|
case _getUnderlyingArrayTarget:
|
|
return target;
|
|
case _proxyContext:
|
|
return proxyContext;
|
|
case _getNodeAtIndex:
|
|
return (index: number): ObjectNode | undefined => {
|
|
updateArrayOrder(target, proxyContext);
|
|
return target[1][index];
|
|
};
|
|
}
|
|
|
|
// TODO: Because of this, every get operation is O(n). Consider changing
|
|
// this
|
|
updateArrayOrder(target, proxyContext);
|
|
const processedArray = getProcessedArray(target, proxyContext);
|
|
if (methodNames.has(key as keyof ArrayMethodBuildersType)) {
|
|
return arrayMethodsBuilders[key as keyof ArrayMethodBuildersType](
|
|
target,
|
|
key as string,
|
|
proxyContext,
|
|
);
|
|
}
|
|
return Reflect.get(processedArray, key, ...rest);
|
|
},
|
|
getOwnPropertyDescriptor(target, key, ...rest) {
|
|
updateArrayOrder(target, proxyContext);
|
|
const processedArray = getProcessedArray(target, proxyContext);
|
|
return Reflect.getOwnPropertyDescriptor(processedArray, key, ...rest);
|
|
},
|
|
ownKeys(target, ...rest) {
|
|
updateArrayOrder(target, proxyContext);
|
|
const processedArray = getProcessedArray(target, proxyContext);
|
|
return Reflect.ownKeys(processedArray, ...rest);
|
|
},
|
|
getPrototypeOf(target, ...rest) {
|
|
updateArrayOrder(target, proxyContext);
|
|
const processedObjects = getProcessedArray(target, proxyContext);
|
|
return Reflect.getPrototypeOf(processedObjects, ...rest);
|
|
},
|
|
has(target, ...rest) {
|
|
updateArrayOrder(target, proxyContext);
|
|
const processedObjects = getProcessedArray(target, proxyContext);
|
|
return Reflect.has(processedObjects, ...rest);
|
|
},
|
|
set(target, key, value, ...rest) {
|
|
if (key === _proxyContext) {
|
|
proxyContext = value;
|
|
return true;
|
|
}
|
|
updateArrayOrder(target, proxyContext);
|
|
if (typeof key !== "symbol" && !isNaN(parseInt(key as string))) {
|
|
const index = parseInt(key);
|
|
return modifyArray(
|
|
{
|
|
target,
|
|
key,
|
|
toAdd: [value],
|
|
quadsToDelete(allQuads) {
|
|
return allQuads[index] ? [allQuads[index]] : [];
|
|
},
|
|
modifyCoreArray(coreArray, addedValues) {
|
|
coreArray[index] = addedValues[0];
|
|
return true;
|
|
},
|
|
},
|
|
proxyContext,
|
|
);
|
|
}
|
|
return Reflect.set(target[1], key, ...rest);
|
|
},
|
|
deleteProperty(target, key) {
|
|
const { dataset } = proxyContext;
|
|
if (typeof key !== "symbol" && !isNaN(parseInt(key as string))) {
|
|
const objectQuad = dataset.match(...target[0]).toArray()[parseInt(key)];
|
|
if (!objectQuad) {
|
|
return true;
|
|
}
|
|
const term = target[2] ? objectQuad.subject : objectQuad.object;
|
|
if (term.termType === "Literal") {
|
|
const subject = target[0][0] as NamedNode;
|
|
const predicate = target[0][1] as NamedNode;
|
|
if (subject && predicate) {
|
|
dataset.delete(quad(subject, predicate, term));
|
|
}
|
|
return true;
|
|
} else if (
|
|
term.termType === "NamedNode" ||
|
|
term.termType === "BlankNode"
|
|
) {
|
|
dataset.deleteMatches(term, undefined, undefined);
|
|
dataset.deleteMatches(undefined, undefined, term);
|
|
return true;
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
};
|
|
}
|
|
|