tripledoc
Version:
Library to read, create and update documents on a Solid Pod
848 lines (834 loc) • 34.9 kB
text/typescript
import { Literal, BlankNode, Quad } from 'rdf-js';
import { DataFactory } from './n3dataset';
import {
Reference,
isLiteral,
LiteralTypes,
isReference,
isStringLiteral,
isIntegerLiteral,
isDecimalLiteral,
DateTimeLiteral,
isDateTimeLiteral,
IntegerLiteral,
DecimalLiteral,
StringLiteral,
isBlankNode,
generateLocaleTypeGuard,
LocaleStringLiteral,
} from './index';
import { findObjectsInDataset } from './getEntities';
import { BareTripleDocument, isSavedToPod } from './document';
import { initialiseDataset } from './n3dataset';
/**
* Represents a single Subject in a [[TripleDocument]].
*
* Used to read and modify properties of a single Subject in a [[TripleDocument]], using the `get*`,
* `set*`, `add*` and `remove*` methods for the relevant data types. Note that those changes will
* not be persisted until you call [[TripleDocument.save]].
*/
export interface TripleSubject {
/**
* @returns The [[TripleDocument]] that contains this Subject.
*/
getDocument: () => BareTripleDocument;
/**
* @deprecated
* @ignore This is mostly a convenience function to make it easy to work with n3 and tripledoc
* simultaneously. If you rely on this, it's probably best to either file an issue
* describing what you want to do that Tripledoc can't do directly, or to just use n3
* directly.
* @returns The Triples pertaining to this Subject that are stored on the user's Pod. Note that
* this does not return Triples that have not been saved yet - see
* [[getPendingTriples]] for those.
*/
getTriples: () => Quad[];
/**
* Find a literal string value for `predicate` on this Subject.
*
* This retrieves _one_ string literal, or `null` if none is found. If you want to find _all_
* string literals for a predicate, see [[getAllStrings]].
*
* @param getString.predicate Which property of this Subject you want the value of.
* @returns The first literal string value satisfying `predicate`, if any, and `null` otherwise.
*/
getString: (predicate: Reference) => string | null;
/**
* Find a literal string value in a given locale for `predicate` on this Subject.
*
* This retrieves _one_ string literal, or `null` if none (in the given locale) is found. If you
* want to find _all_ string literals in a locale for a predicate, see [[getAllLocaleStrings]].
*
* @param getLocaleString.predicate Which property of this Subject you want the value of.
* @param getLocaleString.locale Which locale the string should be in, e.g. 'nl-NL'.
* @returns The first literal string value satisfying `predicate` in the given locale, if any, and `null` otherwise.
*/
getLocaleString: (predicate: Reference, locale: string) => string | null;
/**
* Find a literal integer value for `predicate` on this Subject.
*
* This retrieves _one_ integer literal, or `null` if none is found. If you want to find _all_
* integer literals for a predicate, see [[getAllIntegers]].
*
* @param getInteger.predicate Which property of this Subject you want the value of.
* @returns The first literal integer value satisfying `predicate`, if any, and `null` otherwise.
*/
getInteger: (predicate: Reference) => number | null;
/**
* Find a literal decimal value for `predicate` on this Subject.
*
* This retrieves _one_ decimal literal, or `null` if none is found. If you want to find _all_
* decimal literals for a predicate, see [[getAllDecimals]].
*
* @param getDecimal.predicate Which property of this Subject you want the value of.
* @returns The first literal decimal value satisfying `predicate`, if any, and `null` otherwise.
*/
getDecimal: (predicate: Reference) => number | null;
/**
* Find a literal date+time value for `predicate` on this Subject.
*
* This retrieves _one_ date+time literal, or `null` if none is found. If you want to find _all_
* date+time literals for a predicate, see [[getAllDateTimes]].
*
* @param getDateTime.predicate Which property of this Subject you want the value of.
* @returns The first literal Date value satisfying `predicate`, if any, and `null` otherwise.
*/
getDateTime: (predicate: Reference) => Date | null;
/**
* @param getLiteral.predicate Which property of this Subject you want the value of.
* @returns The first literal value satisfying `predicate`, if any, and `null` otherwise.
* @deprecated This method has been superseded by the type-specific methods [[getString]],
* [[getInteger]], [[getDecimal]] and [[getDateTime]].
*/
getLiteral: (predicate: Reference) => LiteralTypes | null;
/**
* @param getAllStrings.predicate Which property of this Subject you want the values of.
* @returns All literal string values satisfying `predicate`.
*/
getAllStrings: (predicate: Reference) => string[];
/**
* @param getAllLocaleStrings.predicate Which property of this Subject you want the values of.
* @param getAllLocaleStrings.locale Which locale the values should be in, e.g. 'nl-NL', or `undefined` to get all locale strings.
* @returns All literal string values satisfying `predicate` in the given locale, or all locale strings if no locale was specified.
*/
getAllLocaleStrings: (predicate: Reference, locale?: string) => GetAllLocaleStringsReturnType<typeof locale>;
/**
* @param getAllIntegers.predicate Which property of this Subject you want the values of.
* @returns All literal integer values satisfying `predicate`.
*/
getAllIntegers: (predicate: Reference) => number[];
/**
* @param getAllDecimals.predicate Which property of this Subject you want the values of.
* @returns All literal decimal values satisfying `predicate`.
*/
getAllDecimals: (predicate: Reference) => number[];
/**
* @param getAllDateTimes.predicate Which property of this Subject you want the values of.
* @returns All literal DateTime values satisfying `predicate`.
*/
getAllDateTimes: (predicate: Reference) => Date[];
/**
* @param getAllLiterals.predicate Which property of this Subject you want the values of.
* @returns All literal values satisfying `predicate`.
* @deprecated This method has been superseded by the type-specific methods [[getAllStrings]],
* [[getAllIntegers]], [[getAllDecimals]] and [[getAllDates]].
*/
getAllLiterals: (predicate: Reference) => LiteralTypes[];
/**
* Find a local Subject (i.e. without its own URL) referenced by this Subject with `predicate`.
*
* This retrieves _one_ [[TripleSubject]], or `null` if none is found. If you want to find _all_
* local Subjects for a predicate, see [[getAllLocalSubjects]].
*
* @param getRef.predicate Which property of this Subject you want the value of.
* @returns The first referenced local Subject satisfying `predicate`, if any, and `null` otherwise.
* @ignore Experimental API; could change in minor or patch releases.
*/
getLocalSubject: (predicate: Reference) => TripleSubject | null;
/**
* Find local Subject (i.e. without their own URLs) referenced by this Subject with `predicate`.
*
* @param getRef.predicate Which property of this Subject you want the values of.
* @returns All referenced local Subjects satisfying `predicate`.
* @ignore Experimental API; could change in minor or patch releases.
*/
getAllLocalSubjects: (predicate: Reference) => Array<TripleSubject>;
/**
* Find a reference attached to this Subject with `predicate`.
*
* This retrieves _one_ reference, or `null` if none is found. If you want to find _all_
* references for a predicate, see [[getAllRefs]].
*
* @param getRef.predicate Which property of this Subject you want the value of.
* @returns The first referenced IRI satisfying `predicate`, if any, and `null` otherwise.
*/
getRef: (predicate: Reference) => Reference | null;
/**
* @ignore Deprecated method.
* @deprecated Replaced by [[getRef]].
*/
getNodeRef: (predicate: Reference) => Reference | null;
/**
* @returns The type of this Subject, if known.
*/
getType: () => Reference | null;
/**
* @param getAllRefs.predicate Which property of this Subject you want the values of.
* @returns All references satisfying `predicate`.
*/
getAllRefs: (predicate: Reference) => Array<Reference>;
/**
* @ignore Deprecated method.
* @deprecated Replaced by [[getAllRefs]].
*/
getAllNodeRefs: (predicate: Reference) => Array<Reference>;
/**
* Set a property of this Subject to a Literal string value.
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addString.predicate The property you want to add another value of.
* @param addString.object The Literal string value you want to add.
*/
addString: (predicate: Reference, object: string) => void;
/**
* Set a property of this Subject to a Literal localised string value.
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addLocaleString.predicate The property you want to add another value of.
* @param addLocaleString.object The Literal string value you want to add.
* @param addLocaleString.locale The locale the given string is in.
*/
addLocaleString: (predicate: Reference, object: string, locale: string) => void;
/**
* Set a property of this Subject to a Literal integer value.
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addInteger.predicate The property you want to add another value of.
* @param addInteger.object The Literal integer value you want to add.
*/
addInteger: (predicate: Reference, object: number) => void;
/**
* Set a property of this Subject to a Literal decimal value.
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addDecimal.predicate The property you want to add another value of.
* @param addDecimal.object The Literal decimal value you want to add.
*/
addDecimal: (predicate: Reference, object: number) => void;
/**
* Set a property of this Subject to a Literal DateTime value.
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addDateTime.predicate The property you want to add another value of.
* @param addDateTime.object The Literal DateTime value you want to add.
*/
addDateTime: (predicate: Reference, object: Date) => void;
/**
* Set a property of this Subject to a Literal value (i.e. not a URL).
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addLiteral.predicate The property you want to add another value of.
* @param addLiteral.object The Literal value you want to add, the type of which is one of [[LiteralTypes]].
* @deprecated This method has been superseded by the type-specific methods [[addString]],
* [[addInteger]], [[addDecimal]] and [[addDateTime]].
*/
addLiteral: (predicate: Reference, object: LiteralTypes) => void;
/**
* Set a property of this Subject to a [[Reference]].
*
* Note that this value is not saved to the user's Pod until you save the containing Document.
*
* @param addRef.predicate The property you want to add another value of.
* @param addRef.object The IRI you want to add a reference to.
*/
addRef: (predicate: Reference, object: Reference) => void;
/**
* @ignore Deprecated method.
* @deprecated Replaced by [[addRef]].
*/
addNodeRef: (predicate: Reference, object: Reference) => void;
/**
* Remove a Literal string value for a property of this Subject.
*
* Note that this value is not removed from the user's Pod until you save the containing Document.
*
* @param removeString.predicate The property you want to remove a value of.
* @param removeString.object The Literal string value you want to remove.
*/
removeString: (predicate: Reference, object: string) => void;
/**
* Remove a Literal localised string value for a property of this Subject.
*
* Note that this value is not removed from the user's Pod until you save the containing Document.
*
* @param removeLocaleString.predicate The property you want to remove a value of.
* @param removeLocaleString.object The Literal string value you want to remove.
* @param removeLocaleString.locale The locale of the string to remove.
*/
removeLocaleString: (predicate: Reference, object: string, locale: string) => void;
/**
* Remove a Literal integer value for a property of this Subject.
*
* Note that this value is not removed from the user's Pod until you save the containing Document.
*
* @param removeInteger.predicate The property you want to remove a value of.
* @param removeInteger.object The Literal integer value you want to remove.
*/
removeInteger: (predicate: Reference, object: number) => void;
/**
* Remove a Literal decimal value for a property of this Subject.
*
* Note that this value is not removed from the user's Pod until you save the containing Document.
*
* @param removeDecimal.predicate The property you want to remove a value of.
* @param removeDecimal.object The Literal decimal value you want to remove.
*/
removeDecimal: (predicate: Reference, object: number) => void;
/**
* Remove a Literal DateTime value for a property of this Subject.
*
* Note that this value is not removed from the user's Pod until you save the containing Document.
*
* @param removeDateTime.predicate The property you want to remove a value of.
* @param removeDateTime.object The Literal DateTime value you want to remove.
*/
removeDateTime: (predicate: Reference, object: Date) => void;
/**
* Remove a Literal value for a property of this Subject.
*
* Note that this value is not removed from the user's Pod until you save the containing Document.
*
* @param removeLiteral.predicate The property you want to remove a value of.
* @param removeLiteral.object The Literal value you want to remove, the type of which is one of [[LiteralTypes]].
* @deprecated This method has been superseded by the type-specific methods [[removeString]],
* [[removeInteger]], [[removeDecimal]] and [[removeDateTime]].
*/
removeLiteral: (predicate: Reference, object: LiteralTypes) => void;
/**
* Remove a [[Reference]] value for a property of this Subject.
*
* Note that this pointer is not removed from the user's Pod until you save the containing Document.
*
* @param removeRef.predicate The property you want to remove a reference for.
* @param removeRef.object The reference you want to remove.
*/
removeRef: (predicate: Reference, object: Reference) => void;
/**
* @ignore Deprecated.
* @deprecated Replaced by [[removeRef]].
*/
removeNodeRef: (predicate: Reference, object: Reference) => void;
/**
* Remove all values for a property of this Subject.
*
* Note that these values are not removed from the user's Pod until you save the containing
* Document.
*
* @param removeAll.predicate The property you want to remove the values of.
*/
removeAll: (predicate: Reference) => void;
/**
* Set a property of this Subject to a string Literal value, clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setString.predicate The property you want to set the value of.
* @param setString.object The string Literal value you want to set.
*/
setString: (predicate: Reference, object: string) => void;
/**
* Set a property of this Subject to a localised string Literal value, clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setLocaleString.predicate The property you want to set the value of.
* @param setLocaleString.object The string Literal value you want to set.
* @param setLocaleString.locale The locale of the given string.
*/
setLocaleString: (predicate: Reference, object: string, locale: string) => void;
/**
* Set a property of this Subject to an integer Literal value, clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setInteger.predicate The property you want to set the value of.
* @param setInteger.object The integer Literal value you want to set.
*/
setInteger: (predicate: Reference, object: number) => void;
/**
* Set a property of this Subject to a decimal Literal value, clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setDecimal.predicate The property you want to set the value of.
* @param setDecimal.object The decimal Literal value you want to set.
*/
setDecimal: (predicate: Reference, object: number) => void;
/**
* Set a property of this Subject to a DateTime Literal value, clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setDateTime.predicate The property you want to set the value of.
* @param setDateTime.object The DateTime Literal value you want to set.
*/
setDateTime: (predicate: Reference, object: Date) => void;
/**
* Set a property of this Subject to a Literal value, clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setLiteral.predicate The property you want to set the value of.
* @param setLiteral.object The Literal value you want to set, the type of which is one of [[LiteralTypes]].
* @deprecated This method has been superseded by the type-specific methods [[setString]],
* [[setInteger]], [[setDecimal]] and [[setDateTime]].
*/
setLiteral: (predicate: Reference, object: LiteralTypes) => void;
/**
* Set a property of this Subject to a [[Reference]], clearing all existing values.
*
* Note that this change is not saved to the user's Pod until you save the containing Document.
*
* @param setRef.predicate The property you want to set the value of.
* @param setRef.object The reference you want to add.
*/
setRef: (predicate: Reference, object: Reference) => void;
/**
* @ignore Deprecated.
* @deprecated Replaced by [[setRef]].
*/
setNodeRef: (predicate: Reference, object: Reference) => void;
/**
* Unset all values for all Predicates of this Subject.
*
* @internal Currently an internal API for use by [[TripleDocument]].
*/
clear: () => void;
/**
* @internal Pending Triples are only provided so the Document can access them in order to save
* them - this is not part of the public API and can thus break in a minor release.
* @returns A tuple with the first element being a list of Triples that should be deleted from
* the store, and the second element a list of Triples that should be added to it.
*/
getPendingTriples: () => [Quad[], Quad[]];
/**
* Get the IRI of the [[Reference]] representing this specific Subject.
*
* @returns The IRI of this specific Subject.
*/
asRef: () => Reference;
/**
* @ignore Deprecated.
* @deprecated Replaced by [[asRef]].
*/
asNodeRef: () => Reference;
};
type StringWithLocale = { locale: string; value: string };
type GetAllLocaleStringsReturnType<X extends string | undefined> = X extends string ? string [] : Array<StringWithLocale>;
/**
* @internal Only to be called by the Document containing this subject; not a public API.
* @param document The Document this Subject is defined in.
* @param subjectRef The URL that identifies this subject.
*/
export function initialiseSubject(document: BareTripleDocument, subjectRef: Reference| BlankNode): TripleSubject {
const subjectNode = isBlankNode(subjectRef) ? subjectRef : DataFactory.namedNode(subjectRef);
const triples = (isSavedToPod(document))
? document.getStore().match(subjectNode, null, null, null).toArray()
: [];
const dataset = initialiseDataset();
dataset.addAll(triples);
let pendingAdditions: Quad[] = [];
let pendingDeletions: Quad[] = [];
const get = (predicateNode: Reference) => findObjectsInDataset(dataset, subjectRef, predicateNode);
const getString = (predicateNode: Reference) => {
const objects = get(predicateNode);
const firstStringLiteral = objects.find(isStringLiteral);
if (typeof firstStringLiteral === 'undefined') {
return null;
}
return firstStringLiteral.value;
};
const getLocaleString = (predicateNode: Reference, locale: string) => {
const objects = get(predicateNode);
const firstStringLiteral = objects.find(generateLocaleTypeGuard(locale));
if (typeof firstStringLiteral === 'undefined') {
return null;
}
return firstStringLiteral.value;
};
const getInteger = (predicateRef: Reference) => {
const objects = get(predicateRef);
const firstIntegerLiteral = objects.find(isIntegerLiteral);
if (typeof firstIntegerLiteral === 'undefined') {
return null;
}
return fromIntegerLiteral(firstIntegerLiteral);
};
const getDecimal = (predicateRef: Reference) => {
const objects = get(predicateRef);
const firstDecimalLiteral = objects.find(isDecimalLiteral);
if (typeof firstDecimalLiteral === 'undefined') {
return null;
}
return fromDecimalLiteral(firstDecimalLiteral);
};
const getDateTime = (predicateRef: Reference) => {
const objects = get(predicateRef);
const firstDateTimeLiteral = objects.find(isDateTimeLiteral);
if (typeof firstDateTimeLiteral === 'undefined') {
return null;
}
return fromDateTimeLiteral(firstDateTimeLiteral);
};
const getLiteral = (predicateRef: Reference) => {
const objects = get(predicateRef);
const firstLiteral = objects.find(isLiteral);
if (typeof firstLiteral === 'undefined') {
return null;
}
return fromLiteral(firstLiteral);
};
const getAllStrings = (predicateRef: Reference) => {
const objects = get(predicateRef);
const literals = objects.filter(isStringLiteral);
return literals.map(fromStringLiteral);
};
const getAllLocaleStrings = (predicateRef: Reference, locale?: string) => {
const objects = get(predicateRef);
if(locale) {
const literals = objects.filter(generateLocaleTypeGuard(locale));
return literals.map(fromStringLiteral);
}
const literals = objects.filter(hasLocale);
return literals.map(fromLocaleStringLiteral);
};
const getAllIntegers = (predicateRef: Reference) => {
const objects = get(predicateRef);
const literals = objects.filter(isIntegerLiteral);
return literals.map(fromIntegerLiteral);
};
const getAllDecimals = (predicateRef: Reference) => {
const objects = get(predicateRef);
const literals = objects.filter(isDecimalLiteral);
return literals.map(fromDecimalLiteral);
};
const getAllDateTimes = (predicateRef: Reference) => {
const objects = get(predicateRef);
const literals = objects.filter(isDateTimeLiteral);
return literals.map(fromDateTimeLiteral);
};
const getAllLiterals = (predicateRef: Reference) => {
const objects = get(predicateRef);
const literals = objects.filter(isLiteral);
return literals.map(fromLiteral);
};
const getLocalSubject = (predicateRef: Reference) => {
const objects = get(predicateRef);
const firstRef = objects.find(isBlankNode);
if (typeof firstRef === 'undefined') {
return null;
}
return initialiseSubject(document, firstRef);
};
const getAllLocalSubjects = (predicateRef: Reference) => {
const objects = get(predicateRef);
const nodeRefs = objects.filter(isBlankNode);
return nodeRefs.map((localSubject: BlankNode) => initialiseSubject(document, localSubject));
};
const getRef = (predicateRef: Reference) => {
const objects = get(predicateRef);
const firstRef = objects.find(isReference);
if (typeof firstRef === 'undefined') {
return null;
}
return firstRef;
};
const getAllRefs = (predicateRef: Reference) => {
const objects = get(predicateRef);
const nodeRefs = objects.filter(isReference);
return nodeRefs;
};
const getType = () => {
return getRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#type');
}
const addLiteral = (predicateRef: Reference, literal: LiteralTypes) => {
pendingAdditions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
asLiteral(literal),
));
};
const addString = (predicateRef: Reference, literal: string) => {
if (typeof literal !== 'string') {
throw new Error('The given value is not a string.');
}
return addLiteral(predicateRef, literal);
};
const addLocaleString = (predicateRef: Reference, literal: string, locale: string) => {
if (typeof literal !== 'string') {
throw new Error('The given value is not a string.');
}
pendingAdditions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
DataFactory.literal(literal, locale),
));
};
const addInteger = (predicateRef: Reference, literal: number) => {
if (typeof literal !== 'number' || !Number.isInteger(literal)) {
throw new Error('The given value is not an integer.');
}
return addLiteral(predicateRef, literal);
};
const addDecimal = (predicateRef: Reference, literal: number) => {
if (typeof literal !== 'number') {
throw new Error('The given value is not a decimal.');
}
pendingAdditions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#decimal')),
));
};
const addDateTime = (predicateRef: Reference, literal: Date) => {
if (literal instanceof Date === false) {
throw new Error('The given value is not a DateTime.');
}
return addLiteral(predicateRef, literal);
};
const addRef = (predicateRef: Reference, nodeRef: Reference) => {
pendingAdditions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
DataFactory.namedNode(nodeRef),
));
};
const removeRef = (predicateRef: Reference, nodeRef: Reference) => {
pendingDeletions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
DataFactory.namedNode(nodeRef),
));
};
const removeLiteral = (predicateRef: Reference, literal: LiteralTypes) => {
pendingDeletions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
asLiteral(literal),
));
};
const removeString = (predicateRef: Reference, literal: string) => {
if (typeof literal !== 'string') {
throw new Error('The given value is not a string.');
}
return removeLiteral(predicateRef, literal);
};
const removeLocaleString = (predicateRef: Reference, literal: string, locale: string) => {
if (typeof literal !== 'string') {
throw new Error('The given value is not a string.');
}
pendingDeletions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
DataFactory.literal(literal, locale),
));
};
const removeInteger = (predicateRef: Reference, literal: number) => {
if (typeof literal !== 'number' || !Number.isInteger(literal)) {
throw new Error('The given value is not an integer.');
}
return removeLiteral(predicateRef, literal);
};
const removeDecimal = (predicateRef: Reference, literal: number) => {
if (typeof literal !== 'number') {
throw new Error('The given value is not a decimal.');
}
// We cannot re-use `removeLiteral` here because it will parse `42.0` as an integer:
pendingDeletions.push(DataFactory.triple(
subjectNode,
DataFactory.namedNode(predicateRef),
DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#decimal')),
));
};
const removeDateTime = (predicateRef: Reference, literal: Date) => {
if (literal instanceof Date === false) {
throw new Error('The given value is not a DateTime.');
}
return removeLiteral(predicateRef, literal);
};
const removeAll = (predicateRef: Reference) => {
pendingDeletions.push(...dataset.match(
subjectNode, DataFactory.namedNode(predicateRef), null, null,
).toArray());
};
const clear = () => {
pendingDeletions.push(...getTriples());
};
const setRef = (predicateRef: Reference, nodeRef: Reference) => {
removeAll(predicateRef);
addRef(predicateRef, nodeRef);
};
const setLiteral = (predicateRef: Reference, literal: LiteralTypes) => {
removeAll(predicateRef);
addLiteral(predicateRef, literal);
};
const setString = (predicateRef: Reference, literal: string) => {
removeAll(predicateRef);
addString(predicateRef, literal);
};
const setLocaleString = (predicateRef: Reference, literal: string, locale: string) => {
removeAll(predicateRef);
addLocaleString(predicateRef, literal, locale);
};
const setInteger = (predicateRef: Reference, literal: number) => {
removeAll(predicateRef);
addInteger(predicateRef, literal);
};
const setDecimal = (predicateRef: Reference, literal: number) => {
removeAll(predicateRef);
addDecimal(predicateRef, literal);
};
const setDateTime = (predicateRef: Reference, literal: Date) => {
removeAll(predicateRef);
addDateTime(predicateRef, literal);
};
const getTriples = () => dataset.match(
subjectNode,
null,
null,
null,
).toArray();
const asRef = () => isBlankNode(subjectRef) ? subjectRef.value : subjectRef;
const subject: TripleSubject = {
getDocument: () => document,
getTriples: getTriples,
getString: getString,
getLocaleString: getLocaleString,
getInteger: getInteger,
getDecimal: getDecimal,
getDateTime: getDateTime,
getLiteral: getLiteral,
getAllStrings: getAllStrings,
getAllLocaleStrings: getAllLocaleStrings,
getAllIntegers: getAllIntegers,
getAllDecimals: getAllDecimals,
getAllDateTimes: getAllDateTimes,
getAllLiterals: getAllLiterals,
getLocalSubject: getLocalSubject,
getAllLocalSubjects: getAllLocalSubjects,
getRef: getRef,
getAllRefs: getAllRefs,
getType: getType,
addString: addString,
addLocaleString: addLocaleString,
addInteger: addInteger,
addDecimal: addDecimal,
addDateTime: addDateTime,
addRef: addRef,
removeAll: removeAll,
removeString: removeString,
removeLocaleString: removeLocaleString,
removeInteger: removeInteger,
removeDecimal: removeDecimal,
removeDateTime: removeDateTime,
removeRef: removeRef,
setRef: setRef,
setString: setString,
setLocaleString: setLocaleString,
setInteger: setInteger,
setDecimal: setDecimal,
setDateTime: setDateTime,
clear: clear,
getPendingTriples: () => [pendingDeletions, pendingAdditions],
asRef: asRef,
// Deprecated aliases, included for backwards compatibility:
getNodeRef: getRef,
getAllNodeRefs: getAllRefs,
addNodeRef: addRef,
addLiteral: addLiteral,
removeNodeRef: removeRef,
removeLiteral: removeLiteral,
setNodeRef: setRef,
setLiteral: setLiteral,
asNodeRef: asRef,
};
return subject;
}
function fromDateTimeLiteral(literal: DateTimeLiteral): Date {
// See https://github.com/linkeddata/rdflib.js/blob/d84af88f367b8b5f617c753d8241c5a2035458e8/src/literal.js#L87
const utcFullYear = parseInt(literal.value.substring(0, 4), 10);
const utcMonth = parseInt(literal.value.substring(5, 7), 10) - 1;
const utcDate = parseInt(literal.value.substring(8, 10), 10);
const utcHours = parseInt(literal.value.substring(11, 13), 10);
const utcMinutes = parseInt(literal.value.substring(14, 16), 10);
const utcSeconds = parseInt(literal.value.substring(17, literal.value.indexOf('Z')), 10);
const date = new Date(0);
date.setUTCFullYear(utcFullYear);
date.setUTCMonth(utcMonth);
date.setUTCDate(utcDate);
date.setUTCHours(utcHours);
date.setUTCMinutes(utcMinutes);
date.setUTCSeconds(utcSeconds);
return date;
}
function fromIntegerLiteral(literal: IntegerLiteral): number {
return parseInt(literal.value, 10);
}
function fromDecimalLiteral(literal: DecimalLiteral): number {
return parseFloat(literal.value);
}
function fromStringLiteral(literal: StringLiteral | LocaleStringLiteral<string>): string {
return literal.value;
}
function hasLocale(value: string | BlankNode | Literal): value is Literal {
if(isLiteral(value)) {
return value.language.length > 0;
}
return false;
}
function fromLocaleStringLiteral(value: Literal): StringWithLocale {
return {
locale: value.language,
value: value.value
}
}
function fromLiteral(literal: Literal): LiteralTypes {
if (isDateTimeLiteral(literal)) {
return fromDateTimeLiteral(literal);
}
if (isIntegerLiteral(literal)) {
return fromIntegerLiteral(literal);
}
if (isDecimalLiteral(literal)) {
return fromDecimalLiteral(literal);
}
return literal.value;
}
function asLiteral(literal: LiteralTypes): Literal {
if (literal instanceof Date) {
// To align with rdflib, we ignore miliseconds:
// https://github.com/linkeddata/rdflib.js/blob/d84af88f367b8b5f617c753d8241c5a2035458e8/src/literal.js#L74
const roundedDate = new Date(
Date.UTC(
literal.getUTCFullYear(), literal.getUTCMonth(), literal.getUTCDate(),
literal.getUTCHours(), literal.getUTCMinutes(), literal.getUTCSeconds(), 0,
),
);
// Truncate the `.000Z` at the end (i.e. the miliseconds), to plain `Z`:
const rdflibStyleString = roundedDate.toISOString().replace(/\.000Z$/, 'Z');
return DataFactory.literal(rdflibStyleString, DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#dateTime'));
}
if (typeof literal === 'number' && Number.isInteger(literal)) {
return DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#integer'))
}
if (typeof literal === 'number' && !Number.isInteger(literal)) {
return DataFactory.literal(literal.toString(), DataFactory.namedNode('http://www.w3.org/2001/XMLSchema#decimal'))
}
return DataFactory.literal(literal.toString());
}