lincd-jsonld
Version:
Utilities to parse and write JSON-LD for the LINCD library
183 lines • 9.19 kB
JavaScript
;
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