UNPKG

lincd-jsonld

Version:

Utilities to parse and write JSON-LD for the LINCD library

183 lines 9.19 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.JSONLD = exports.jsonld_parser = void 0; /** * @license MPL-v2.0 * @package lincd-jsonld * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ const jsonld_1 = __importDefault(require("jsonld")); const { promises: jsonld } = jsonld_1.default; // import * as jsonld from "jsonld/dist/node6/jsonld"; const models_1 = require("lincd/models"); const NodeFactory_js_1 = require("./NodeFactory.js"); const NodeURIMappings_1 = require("lincd/collections/NodeURIMappings"); const QuadSet_1 = require("lincd/collections/QuadSet"); const CoreSet_1 = require("lincd/collections/CoreSet"); const package_js_1 = require("../package.js"); const CoreMap_1 = require("lincd/collections/CoreMap"); exports.jsonld_parser = jsonld; (0, package_js_1.linkedUtil)(exports.jsonld_parser); let JSONLD = class JSONLD { static parseString(json, setExplicit = true, nodemap, targetGraph) { return this.parse(JSON.parse(json), setExplicit, nodemap, targetGraph); } /** * Parses the result of a promise. * Handy shortcut * @param p */ static parsePromise(p) { return p.then((result) => this.parse(result)); } static parsePromises(...p) { return Promise.all(p) .then((importedDatas) => { return Promise.all(importedDatas.map((importedData) => this.parse(importedData))); }) .then((parseResults) => { let combined = { graphs: new CoreSet_1.CoreSet(), quads: new QuadSet_1.QuadSet(), nodemap: new NodeURIMappings_1.NodeURIMappings(), }; parseResults.forEach((parseResult) => { var _a, _b, _c; (_a = parseResult.graphs) === null || _a === void 0 ? void 0 : _a.forEach((g) => combined.graphs.add(g)); (_b = parseResult.quads) === null || _b === void 0 ? void 0 : _b.forEach((q) => combined.quads.add(q)); (_c = parseResult.nodemap) === null || _c === void 0 ? void 0 : _c.forEach((value, key) => combined.nodemap.set(key, value)); }); return combined; }); } static parse(jsonObject, setExplicit = true, // setSubjectsLoaded: boolean = false, nodemap = new NodeURIMappings_1.NodeURIMappings(), targetGraph, overwriteData = false) { if (!nodemap) { nodemap = new NodeURIMappings_1.NodeURIMappings(); } return this.parseToNQuads(jsonObject) .then((nquads) => { let result = this.nquadsToGraphs(nquads, setExplicit, nodemap, targetGraph, overwriteData); //NOTE: leave this commented out here for now //we may need it once we start working more with blank nodes again // if (nodemap && nodemap.getBlankNodes().size > 0) { //the jsonld.js library replaces all the blanknode labels in the JSONLD with new blank node labels. //however we sometimes want to match the ids in the jsonld to other things send over to the server //so when a blank node map is given we need to 'fix' the nquad string output // console.warn( // 'Blank nodes in this JSONLD data will not match previous blank nodes. (Blank node label fix was turned off)', // ); // nquads = this.fixQuadBlanknodeLabels(jsonObject, nquads, nodemap); // } return result; }) .catch((err) => { console.warn('Error converting nquads to graphs: ' + err.stack); return null; }); } static parseToNQuads(jsonObject) { return jsonld .toRDF(jsonObject, { format: 'application/nquads' }) .catch((e) => { console.warn('Error parsing JSONLD: ' + e.stack); }); } static fixQuadBlanknodeLabels(jsonObject, nquads, nodemap) { //the jsonld.js library replaces all the blanknode labels in the JSONLD with new blank node labels. //it luckily does this in order of occurrence in the document. So first bnode in the doc {"@id":"_:123"} will become _:b0, next one _:b1 //so here we first find all the blank node labels used in the jsonObject by recursing the object var labels = []; var recursiveLabelGrabber = (obj) => { for (var key in obj) { var val = obj[key]; //and if "@id" is found as key and the value is a blank node if (key == '@id' && val.substr(0, 2) == '_:') { //we save it to the labels labels.push(val); } if (Array.isArray(val)) { val.forEach((subValue) => { recursiveLabelGrabber(subValue); }); } else if (typeof val == 'object') { recursiveLabelGrabber(val); } } }; recursiveLabelGrabber(jsonObject); //then we replace the _:bx occurences in the nquads string with these original labels so that they will maych with things in our own bnode map labels.forEach((label, key) => { nquads = nquads.replace(new RegExp('_:b' + key, 'g'), label); }); return nquads; } static nquadsToGraphs(nquads, setExplicit = true, nodemap = new NodeURIMappings_1.NodeURIMappings(), targetGraph, overwriteData = false) { var graphs = new CoreSet_1.CoreSet(); var quads = new QuadSet_1.QuadSet(); var clearedProps = overwriteData ? new CoreMap_1.CoreMap() : null; nquads.split('\n').forEach((line) => { if (line != '') { //Self-made regex, adjusted from multiple partially working results, including: https://gist.github.com/rogargon/0c79561a978df34a6d59 //NOTE added a ' character for graphDB data with ' in the URL let [s, p, o, g] = line .trim() .match(/[^\s"]+|("(?:[^"\\]|\\.)*")(@[a-z]{1,3}|\^\^[a-zA-Z]+\:[a-zA-Z0-9_-]+|\^\^\<https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=']{2,512}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)\>)?/g); let subject = NodeFactory_js_1.NodeFactory.uriResourceFromSPARQL(s, nodemap); let predicate = NodeFactory_js_1.NodeFactory.uriResourceFromSPARQL(p, nodemap); let object = NodeFactory_js_1.NodeFactory.resourceFromSPARQL(o, nodemap); let graph; //if a target graph is given, we always use that, regardless of whether there was any graph present in the data //else if a graph was in the data, use that, or fall back to default graph if (targetGraph) { graph = targetGraph; } else if (g != '.') { graph = NodeFactory_js_1.NodeFactory.graphFromSPARQL(g, nodemap); } else { graph = models_1.defaultGraph; } //sometimes we want to update the graph with new data coming in from JSONLD //so if overwrite data is true, we clear old data for any subj/pred combination we find if (overwriteData && (!clearedProps.has(subject) || !clearedProps.get(subject).has(predicate))) { //remove without triggering storage events subject.getQuads(predicate).removeAll(false); if (!clearedProps.has(subject)) { clearedProps.set(subject, new CoreSet_1.CoreSet()); } clearedProps.get(subject).add(predicate); } let quad = models_1.Quad.getOrCreate(subject, predicate, object, graph); graphs.add(quad.graph); quads.add(quad); if (setExplicit && quad.implicit) quad.implicit = false; } }); return { graphs, quads, nodemap }; } }; exports.JSONLD = JSONLD; exports.JSONLD = JSONLD = __decorate([ package_js_1.linkedUtil ], JSONLD); //# sourceMappingURL=JSONLD.js.map