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.
141 lines
4.3 KiB
141 lines
4.3 KiB
import { defaultGraph } from "@rdfjs/data-model";
|
|
import type { Quad } from "@rdfjs/types";
|
|
import type { ObjectNode } from "@ldo/rdf-utils";
|
|
import {
|
|
TransactionDataset,
|
|
createTransactionDatasetFactory,
|
|
} from "@ldo/subscribable-dataset";
|
|
import { createDatasetFactory } from "@ldo/dataset";
|
|
import type { ProxyContext } from "../ProxyContext";
|
|
import { addObjectToDataset } from "../util/addObjectToDataset";
|
|
import {
|
|
getNodeFromRawObject,
|
|
getNodeFromRawValue,
|
|
} from "../util/getNodeFromRaw";
|
|
import { nodeToString } from "../util/NodeSet";
|
|
import type { ObjectJsonRepresentation } from "../util/nodeToJsonldRepresentation";
|
|
import type { RawObject, RawValue } from "../util/RawObject";
|
|
import type { ArrayProxyTarget } from "./createArrayHandler";
|
|
|
|
export function checkArrayModification(
|
|
target: ArrayProxyTarget,
|
|
objectsToAdd: RawValue[],
|
|
proxyContext: ProxyContext,
|
|
) {
|
|
if (target[2]) {
|
|
for (const objectToAdd of objectsToAdd) {
|
|
// Undefined is fine no matter what
|
|
if (objectToAdd === undefined) {
|
|
return;
|
|
}
|
|
if (typeof objectToAdd !== "object") {
|
|
throw new Error(
|
|
`Cannot add a literal "${objectToAdd}"(${typeof objectToAdd}) to a subject-oriented collection.`,
|
|
);
|
|
}
|
|
// Create a test dataset to see if the inputted data is valid
|
|
const testDataset = new TransactionDataset(
|
|
proxyContext.dataset,
|
|
createDatasetFactory(),
|
|
createTransactionDatasetFactory(),
|
|
);
|
|
addObjectToDataset(
|
|
objectToAdd as RawObject,
|
|
false,
|
|
proxyContext.duplicate({
|
|
writeGraphs: [defaultGraph()],
|
|
}),
|
|
);
|
|
const isValidAddition =
|
|
testDataset.match(
|
|
getNodeFromRawObject(objectToAdd, proxyContext.contextUtil),
|
|
target[0][1],
|
|
target[0][2],
|
|
).size !== 0;
|
|
if (!isValidAddition) {
|
|
throw new Error(
|
|
`Cannot add value to collection. This must contain a quad that matches (${nodeToString(
|
|
target[0][0],
|
|
)}, ${nodeToString(target[0][1])}, ${nodeToString(
|
|
target[0][2],
|
|
)}, ${nodeToString(target[0][3])})`,
|
|
);
|
|
}
|
|
}
|
|
} else if (!target[0][0] || !target[0][1]) {
|
|
throw new Error(
|
|
"A collection that does not specify a match for both a subject or predicate cannot be modified directly.",
|
|
);
|
|
}
|
|
}
|
|
|
|
export function modifyArray<ReturnType>(
|
|
config: {
|
|
target: ArrayProxyTarget;
|
|
key: string;
|
|
toAdd?: RawValue[];
|
|
quadsToDelete?: (quads: Quad[]) => Quad[];
|
|
modifyCoreArray: (
|
|
coreArray: ArrayProxyTarget[1],
|
|
addedValues: ArrayProxyTarget[1],
|
|
) => ReturnType;
|
|
},
|
|
proxyContext: ProxyContext,
|
|
): ReturnType {
|
|
const { target, toAdd, quadsToDelete, modifyCoreArray, key } = config;
|
|
const { dataset, contextUtil } = proxyContext;
|
|
checkArrayModification(target, toAdd || [], proxyContext);
|
|
|
|
// Remove appropriate Quads
|
|
if (quadsToDelete) {
|
|
const quadArr = dataset.match(...target[0]).toArray();
|
|
const deleteQuadArr = quadsToDelete(quadArr);
|
|
// Filter out overlapping items
|
|
deleteQuadArr.forEach((delQuad) => {
|
|
if (target[2]) {
|
|
dataset.deleteMatches(delQuad.subject, undefined, undefined);
|
|
} else {
|
|
dataset.delete(delQuad);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Add new items to the dataset
|
|
const added = toAdd
|
|
?.map((item) => {
|
|
return typeof item === "object"
|
|
? addObjectToDataset(item, false, proxyContext)
|
|
: item;
|
|
})
|
|
.filter(
|
|
(val) => val != undefined,
|
|
) as NonNullable<ObjectJsonRepresentation>[];
|
|
if (!target[2] && target[0][0] && target[0][1] && added) {
|
|
addObjectToDataset(
|
|
{
|
|
"@id": target[0][0],
|
|
[contextUtil.iriToKey(
|
|
target[0][1].value,
|
|
proxyContext.getRdfType(target[0][0]),
|
|
)]: added,
|
|
} as RawObject,
|
|
false,
|
|
proxyContext,
|
|
);
|
|
}
|
|
const addedNodes = added
|
|
? (added
|
|
.map((addedValue) => {
|
|
return getNodeFromRawValue(
|
|
key,
|
|
addedValue,
|
|
target[0][0] ? proxyContext.getRdfType(target[0][0]) : [],
|
|
proxyContext,
|
|
);
|
|
})
|
|
.filter((val) => val != undefined) as ObjectNode[])
|
|
: [];
|
|
|
|
// Allow the base array to be modified
|
|
return modifyCoreArray(target[1], addedNodes);
|
|
}
|
|
|