UNPKG

rdf-dataset-fragmenter

Version:
109 lines 6.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.QuadTransformerRemapResourceIdentifier = void 0; const rdf_data_factory_1 = require("rdf-data-factory"); const relative_to_absolute_iri_1 = require("relative-to-absolute-iri"); const ResourceIdentifier_1 = require("./identifier/ResourceIdentifier"); const DF = new rdf_data_factory_1.DataFactory(); /** * A quad transformer that matches all resources of the given type, * and rewrites its (subject) IRI (across all triples) so that it becomes part of the targeted resource. * * For example, a transformer matching on type `Post` for identifier predicate `hasId` and target predicate `hasCreator` * will modify all post IRIs to become a hash-based IRI inside the object IRI of `hasCreator`. * Concretely, `<ex:post1> a <Post>. <ex:post1> <hasId> '1'. <ex:post1> <hasCreator> <urn:person1>` * will become * `<urn:person1#Post1> a <Post>. <urn:person1#Post1> <hasId> '1'. <urn:person1#post1> <hasCreator> <urn:person1>`. * * WARNING: This transformer assumes that all the applicable resources * have `rdf:type` occurring as first triple with the resource IRI as subject. */ class QuadTransformerRemapResourceIdentifier { /** * @param newIdentifierSeparator Separator string to use inbetween the target IRI and the identifier value * when minting a new resource IRI. This may also be a relative IRI. * @param typeRegex The RDF type that should be used to capture resources. * @param identifierPredicateRegex Predicate regex that contains a resource identifier. * @param targetPredicateRegex Predicate regex that contains an IRI onto which the resource identifier should be * remapped. * @param identifierValueModifier An optional value modifier that will be applied on matched identifier values. * @param keepSubjectFragment If the fragment of the original subject should be inherited onto the new identifier IRI. */ constructor(newIdentifierSeparator, typeRegex, identifierPredicateRegex, targetPredicateRegex, identifierValueModifier, keepSubjectFragment) { this.newIdentifierSeparator = newIdentifierSeparator; this.identifierPredicate = new RegExp(identifierPredicateRegex, 'u'); this.resourceIdentifier = new ResourceIdentifier_1.ResourceIdentifier(typeRegex, targetPredicateRegex); this.identifierValueModifier = identifierValueModifier; this.keepSubjectFragment = Boolean(keepSubjectFragment); } transform(quad, allowedComponent) { // If a subject or object in the quad has been remapped (resource has been fully defined before) // Only do this is no components in the quad are being buffered, // otherwise we might lose remapping of quads that are remapped at multiple positions const isBuffered = this.resourceIdentifier.isQuadBuffered(quad, allowedComponent); if (!isBuffered) { const [modified, mappedQuad] = this.mapQuad(quad, allowedComponent); if (modified) { return [mappedQuad]; } } // Add buffer entry on applicable resource type if ((!allowedComponent || allowedComponent === 'subject') && this.resourceIdentifier.tryInitializingBuffer(quad)) { // We will emit the quad later return []; } // If this resource is buffered if (isBuffered) { const resource = this.resourceIdentifier.getBufferResource(quad); // Try to set the id if (this.identifierPredicate.test(quad.predicate.value)) { if (resource.id) { throw new Error(`Illegal overwrite of identifier value on resource '${quad.subject.value}'`); } resource.id = quad.object; // Modify the value if needed if (this.identifierValueModifier) { resource.id = this.identifierValueModifier.apply(resource.id); } } // Try to set the target this.resourceIdentifier.tryStoringTarget(resource, quad); // Check if resource is complete if (resource.id && resource.target) { // Determine new resource IRI let resourceIri = DF.namedNode((0, relative_to_absolute_iri_1.resolve)(this.newIdentifierSeparator + resource.id.value, resource.target.value)); // Inherit fragment if needed if (this.keepSubjectFragment) { const fragmentPos = quad.subject.value.indexOf('#'); if (fragmentPos >= 0) { const fragment = quad.subject.value.slice(fragmentPos); resourceIri = DF.namedNode(resourceIri.value + fragment); } } // Clear the buffer, and set rewriting rule this.resourceIdentifier.applyMapping(quad, resourceIri); // Flush buffered quads return resource.quads.map(subQuad => this.mapQuad(subQuad, allowedComponent)[1]); } // Don't emit anything if our buffer is incomplete return []; } return [quad]; } mapQuad(quad, allowedComponent) { const modified = this.resourceIdentifier.forEachMappedResource(quad, (mapping, component) => { if (component === 'subject' && (!allowedComponent || allowedComponent === 'subject')) { quad = DF.quad(mapping, quad.predicate, quad.object, quad.graph); } else if (!allowedComponent || allowedComponent === 'object') { quad = DF.quad(quad.subject, quad.predicate, mapping, quad.graph); } }); return [modified, quad]; } end() { this.resourceIdentifier.onEnd(); } } exports.QuadTransformerRemapResourceIdentifier = QuadTransformerRemapResourceIdentifier; //# sourceMappingURL=QuadTransformerRemapResourceIdentifier.js.map