UNPKG

@comake/skl-js-engine

Version:

Standard Knowledge Language Javascript Engine

305 lines 15.9 kB
"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