@comake/skl-js-engine
Version:
Standard Knowledge Language Javascript Engine
305 lines • 15.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SparqlUpdateBuilder = void 0;
const rmlmapper_js_1 = require("@comake/rmlmapper-js");
const data_model_1 = __importDefault(require("@rdfjs/data-model"));
const constants_1 = require("../../../constants");
const SparqlUtil_1 = require("../../../util/SparqlUtil");
const TripleUtil_1 = require("../../../util/TripleUtil");
const Util_1 = require("../../../util/Util");
const VariableGenerator_1 = require("./VariableGenerator");
class SparqlUpdateBuilder {
constructor(args) {
this.variableGenerator = new VariableGenerator_1.VariableGenerator();
this.setTimestamps = args?.setTimestamps ?? false;
}
buildPartialUpdate(idOrIds, attributes) {
const ids = (0, Util_1.ensureArray)(idOrIds);
const updates = this.idsAndAttributesToGraphDeletionsAndInsertions(ids, attributes);
return (0, SparqlUtil_1.createSparqlUpdate)(updates);
}
buildUpdate(entityOrEntities) {
const entities = (0, Util_1.ensureArray)(entityOrEntities);
const { clear, insertions, timestampInsertions } = this.entitiesToGraphDeletionsAndInsertions(entities);
const insertUpdate = {
updateType: 'insert',
insert: insertions
};
const updates = [...clear, insertUpdate];
if (timestampInsertions.length > 0) {
updates.push({
updateType: 'insertdelete',
delete: [],
insert: timestampInsertions,
where: [SparqlUtil_1.bindNow]
});
}
return (0, SparqlUtil_1.createSparqlUpdate)(updates);
}
buildDeleteById(idOrIds) {
const ids = (0, Util_1.ensureArray)(idOrIds);
const drops = this.idsToGraphDropUpdates(ids);
return (0, SparqlUtil_1.createSparqlUpdate)(drops);
}
buildDelete(entityOrEntities) {
const entities = (0, Util_1.ensureArray)(entityOrEntities);
const drops = this.entitiesToGraphDropUpdates(entities);
return (0, SparqlUtil_1.createSparqlUpdate)(drops);
}
buildDeleteAll() {
return (0, SparqlUtil_1.createSparqlUpdate)([SparqlUtil_1.dropAll]);
}
idsAndAttributesToGraphDeletionsAndInsertions(ids, attributes) {
return ids.flatMap((id) => {
const subject = data_model_1.default.namedNode(id);
const { attributesToUpdate, attributesToDelete } = this.partitionAttributes(attributes);
const { triples: deletionTriples, deletions: deletionDeletions } = this.partialEntityToDeletionTriples(attributesToUpdate, subject);
const { triples: insertionTriples, insertions: insertionInsertions } = this.partialEntityToTriples(subject, attributesToUpdate);
const { triples: deleteOnlyTriples } = this.partialEntityToDeletionTriples(attributesToDelete, subject);
const updates = [];
if (deletionTriples.length > 0) {
updates.push({
updateType: 'insertdelete',
delete: [(0, SparqlUtil_1.createSparqlGraphQuads)(subject, deletionTriples)],
insert: [],
where: deletionTriples.map((triple) => (0, SparqlUtil_1.createSparqlOptional)([(0, SparqlUtil_1.createSparqlBasicGraphPattern)([triple])])),
using: {
default: [subject]
}
});
}
for (const deletion of deletionDeletions) {
updates.push({
updateType: 'insertdelete',
delete: [deletion],
insert: [],
where: [
...deletion.triples.map((triple) => (0, SparqlUtil_1.createSparqlOptional)([(0, SparqlUtil_1.createSparqlBasicGraphPattern)([triple])]))
],
using: {
default: [deletion.name]
}
});
}
if (insertionTriples.length > 0) {
updates.push({
updateType: 'insert',
insert: [(0, SparqlUtil_1.createSparqlGraphQuads)(subject, insertionTriples), ...insertionInsertions]
});
}
if (deleteOnlyTriples.length > 0) {
updates.push({
updateType: 'insertdelete',
delete: [(0, SparqlUtil_1.createSparqlGraphQuads)(subject, deleteOnlyTriples)],
insert: [],
where: deleteOnlyTriples.map((triple) => (0, SparqlUtil_1.createSparqlOptional)([(0, SparqlUtil_1.createSparqlBasicGraphPattern)([triple])])),
using: {
default: [subject]
}
});
}
const hasAnyChanges = deletionTriples.length > 0 || insertionTriples.length > 0 || deleteOnlyTriples.length > 0;
if (this.setTimestamps && hasAnyChanges) {
const modifiedVariable = data_model_1.default.variable(this.variableGenerator.getNext());
const modifiedDeletionTriple = { subject, predicate: SparqlUtil_1.modified, object: modifiedVariable };
const modifiedInsertionTriple = { subject, predicate: SparqlUtil_1.modified, object: SparqlUtil_1.now };
updates.push({
updateType: 'insertdelete',
delete: [(0, SparqlUtil_1.createSparqlGraphQuads)(subject, [modifiedDeletionTriple])],
insert: [(0, SparqlUtil_1.createSparqlGraphQuads)(subject, [modifiedInsertionTriple])],
where: [(0, SparqlUtil_1.createSparqlOptional)([(0, SparqlUtil_1.createSparqlBasicGraphPattern)([modifiedDeletionTriple])]), SparqlUtil_1.bindNow],
using: {
default: [subject]
}
});
}
return updates;
});
}
partitionAttributes(attributes) {
const attributesToUpdate = {};
const attributesToDelete = {};
Object.entries(attributes).forEach(([key, value]) => {
if (key === '@id') {
return;
}
if (value === null) {
attributesToDelete[key] = value;
}
else if (value !== undefined) {
attributesToUpdate[key] = value;
}
});
return { attributesToUpdate, attributesToDelete };
}
entitiesToGraphDeletionsAndInsertions(entities) {
return entities.reduce((obj, entity) => {
const entityGraphName = data_model_1.default.namedNode(entity['@id']);
const { entityTriples, timestampTriples, insertions } = this.entityToTriples(entity, entityGraphName);
obj.clear.push((0, SparqlUtil_1.createSparqlClearUpdate)(entityGraphName));
obj.insertions.push((0, SparqlUtil_1.createSparqlGraphQuads)(entityGraphName, entityTriples), ...insertions);
if (timestampTriples.length > 0) {
obj.timestampInsertions.push((0, SparqlUtil_1.createSparqlGraphQuads)(entityGraphName, timestampTriples));
}
return obj;
}, { clear: [], insertions: [], timestampInsertions: [] });
}
idsToGraphDropUpdates(ids) {
return ids.map((id) => {
const entityGraphName = data_model_1.default.namedNode(id);
return (0, SparqlUtil_1.createSparqlDropUpdate)(entityGraphName);
});
}
entitiesToGraphDropUpdates(entities) {
return entities.map((entity) => {
const entityGraphName = data_model_1.default.namedNode(entity['@id']);
return (0, SparqlUtil_1.createSparqlDropUpdate)(entityGraphName);
});
}
partialEntityToDeletionTriples(entity, subject) {
return Object.entries(entity).reduce((acc, [key, value]) => {
if (key !== '@id') {
let deletions = [];
if (value && typeof value === 'object' && '@id' in value && typeof value['@id'] === 'string' && '@type' in value) {
const { triples: nestedTriples, deletions: nestedDeletions } = this.partialEntityToDeletionTriples(value, data_model_1.default.namedNode(value['@id']));
deletions = [...deletions, (0, SparqlUtil_1.createSparqlGraphQuads)(data_model_1.default.namedNode(value['@id']), nestedTriples), ...nestedDeletions];
}
return {
triples: [
...acc.triples,
this.buildTriplesWithSubjectPredicateAndVariableValue(subject, key === '@type' ? SparqlUtil_1.rdfTypeNamedNode : data_model_1.default.namedNode(key), this.variableGenerator.getNext())
],
deletions: [...acc.deletions, ...deletions]
};
}
return acc;
}, { triples: [], deletions: [] });
}
partialEntityToTriples(subject, entity) {
return Object.entries(entity).reduce((acc, [key, value]) => {
const values = (0, Util_1.ensureArray)(value);
if (key !== '@id') {
let predicateTriples;
if (key === '@type') {
predicateTriples = { triples: this.buildTriplesWithSubjectPredicateAndIriValue(subject, SparqlUtil_1.rdfTypeNamedNode, values), insertions: [] };
}
else {
predicateTriples = this.buildTriplesForSubjectPredicateAndValues(subject, key, values);
}
return { triples: [...acc.triples, ...predicateTriples.triples], insertions: [...acc.insertions, ...predicateTriples.insertions] };
}
return acc;
}, { triples: [], insertions: [] });
}
entityToTriples(entity, subject) {
const entityTriples = Object.entries(entity).reduce((acc, [key, value]) => {
const values = (0, Util_1.ensureArray)(value);
if (key !== '@id') {
if (key === '@type') {
const predicateTriples = this.buildTriplesWithSubjectPredicateAndIriValue(subject, SparqlUtil_1.rdfTypeNamedNode, values);
return { triples: [...acc.triples, ...predicateTriples], insertions: acc.insertions };
}
if (!(this.setTimestamps && key === constants_1.EngineConstants.prop.dateModified)) {
const predicateTriples = this.buildTriplesForSubjectPredicateAndValues(subject, key, values);
return { triples: [...acc.triples, ...predicateTriples.triples], insertions: [...acc.insertions, ...predicateTriples.insertions] };
}
}
return acc;
}, { triples: [], insertions: [] });
const timestampTriples = [];
if (this.setTimestamps && subject.termType === 'NamedNode') {
if (!(constants_1.EngineConstants.prop.dateCreated in entity)) {
timestampTriples.push({ subject, predicate: SparqlUtil_1.created, object: SparqlUtil_1.now });
}
timestampTriples.push({ subject, predicate: SparqlUtil_1.modified, object: SparqlUtil_1.now });
}
return {
entityTriples: entityTriples.triples,
insertions: entityTriples.insertions,
timestampTriples
};
}
buildTriplesForSubjectPredicateAndValues(subject, predicate, values) {
const predicateTerm = data_model_1.default.namedNode(predicate);
// Return values.flatMap((value: any): { triples: Triple[]; insertions: GraphQuads[] } =>
// this.buildTriplesWithSubjectPredicateAndValue(subject, predicateTerm, value));
return values.reduce((acc, value) => {
const { triples, insertions } = this.buildTriplesWithSubjectPredicateAndValue(subject, predicateTerm, value);
return { triples: [...acc.triples, ...triples], insertions: [...acc.insertions, ...insertions] };
}, { triples: [], insertions: [] });
}
buildTriplesWithSubjectPredicateAndIriValue(subject, predicate, values) {
return values.map((valueItem) => ({
subject,
predicate,
object: data_model_1.default.namedNode(valueItem)
}));
}
buildTriplesWithSubjectPredicateAndVariableValue(subject, predicate, value) {
return {
subject,
predicate,
object: data_model_1.default.variable(value)
};
}
buildTriplesWithSubjectPredicateAndValue(subject, predicate, value) {
const isObject = typeof value === 'object';
if (isObject) {
if ('@list' in value) {
return { triples: this.buildTriplesForList(subject, predicate, value['@list']), insertions: [] };
}
if ('@value' in value) {
return { triples: [{ subject, predicate, object: this.jsonLdValueObjectToLiteral(value) }], insertions: [] };
}
const isReferenceObject = '@id' in value;
const isBlankNodeReferenceObject = !isReferenceObject || value['@id'].startsWith('_:');
if (isBlankNodeReferenceObject) {
return { triples: this.buildTriplesForBlankNode(subject, predicate, value), insertions: [] };
}
if (isReferenceObject) {
const triples = [
{ subject, predicate, object: data_model_1.default.namedNode(value['@id']) }
];
if (value['@type']) {
const { entityTriples, insertions } = this.entityToTriples(value, data_model_1.default.namedNode(value['@id']));
return { triples, insertions: [...insertions, (0, SparqlUtil_1.createSparqlGraphQuads)(data_model_1.default.namedNode(value['@id']), entityTriples)] };
}
return { triples, insertions: [] };
}
}
return { triples: [{ subject, predicate, object: (0, TripleUtil_1.valueToLiteral)(value) }], insertions: [] };
}
jsonLdValueObjectToLiteral(value) {
if (typeof value['@value'] === 'object') {
return data_model_1.default.literal(JSON.stringify(value['@value']), rmlmapper_js_1.RDF.JSON);
}
if (value['@language']) {
return data_model_1.default.literal(value['@value'], value['@language']);
}
if (value['@type']) {
return data_model_1.default.literal(value['@value'].toString(), value['@type']);
}
return (0, TripleUtil_1.valueToLiteral)(value['@value']);
}
buildTriplesForList(subject, predicate, value) {
const blankNode = data_model_1.default.blankNode(this.variableGenerator.getNext());
const rest = value.length > 1
? this.buildTriplesForList(blankNode, SparqlUtil_1.restPredicate, value.slice(1))
: [{ subject: blankNode, predicate: SparqlUtil_1.restPredicate, object: SparqlUtil_1.nilPredicate }];
return [
{ subject, predicate, object: blankNode },
...this.buildTriplesWithSubjectPredicateAndValue(blankNode, SparqlUtil_1.firstPredicate, value[0]).triples,
...rest
];
}
buildTriplesForBlankNode(subject, predicate, value) {
const blankNode = data_model_1.default.blankNode(this.variableGenerator.getNext());
const { entityTriples } = this.entityToTriples(value, blankNode);
return [{ subject, predicate, object: blankNode }, ...entityTriples];
}
}
exports.SparqlUpdateBuilder = SparqlUpdateBuilder;
//# sourceMappingURL=SparqlUpdateBuilder.js.map