Introduce data field as the main property on which to get/set other properties #4
9 changed files with 115 additions and 99 deletions
22
README.md
22
README.md
|
|
@ -28,17 +28,17 @@ const fileUrl = 'https://concepts.datalad.org/s/things/v1.shacl.ttl';
|
||||||
// Listen for and act on the 'graphLoaded' event
|
// Listen for and act on the 'graphLoaded' event
|
||||||
shapesDS.addEventListener('graphLoaded', (event) => {
|
shapesDS.addEventListener('graphLoaded', (event) => {
|
||||||
console.log('Shapes graph fully loaded:', event.detail)
|
console.log('Shapes graph fully loaded:', event.detail)
|
||||||
console.log(shapesDS.propertyGroups)
|
console.log(shapesDS.data.propertyGroups)
|
||||||
console.log(shapesDS.nodeShapes)
|
console.log(shapesDS.data.nodeShapes)
|
||||||
console.log(shapesDS.nodeShapeNames)
|
console.log(shapesDS.data.nodeShapeNames)
|
||||||
console.log(shapesDS.nodeShapeNamesArray)
|
console.log(shapesDS.data.nodeShapeNamesArray)
|
||||||
console.log(shapesDS.nodeShapeIRIs)
|
console.log(shapesDS.data.nodeShapeIRIs)
|
||||||
console.log(shapesDS.prefixes)
|
console.log(shapesDS.data.prefixes)
|
||||||
console.log(shapesDS.serializedGraph)
|
console.log(shapesDS.data.serializedGraph)
|
||||||
console.log(shapesDS.graphLoaded)
|
console.log(shapesDS.data.graphLoaded)
|
||||||
console.log(shapesDS.prefixesLoaded)
|
console.log(shapesDS.data.prefixesLoaded)
|
||||||
console.log(shapesDS.graph)
|
console.log(shapesDS.data.graph)
|
||||||
console.log(shapesDS.graph.size)
|
console.log(shapesDS.data.graph.size)
|
||||||
});
|
});
|
||||||
// Load the RDF
|
// Load the RDF
|
||||||
shapesDS.loadRDF(fileUrl);
|
shapesDS.loadRDF(fileUrl);
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import { RDFS } from '../modules/namespaces';
|
||||||
|
|
||||||
export class ClassDataset extends RdfDataset {
|
export class ClassDataset extends RdfDataset {
|
||||||
|
|
||||||
constructor() {
|
constructor(data = {}) {
|
||||||
super()
|
super(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
onDataFn(quad) {
|
onDataFn(quad) {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { isEmptyObject, toIRI} from '../modules/utils';
|
||||||
|
|
||||||
export class FormBase {
|
export class FormBase {
|
||||||
|
|
||||||
constructor(id_iri = null) {
|
constructor(id_iri = null, content = {}) {
|
||||||
|
|
||||||
if (!id_iri) {
|
if (!id_iri) {
|
||||||
var msg = "id_iri is a required argument"
|
var msg = "id_iri is a required argument"
|
||||||
|
|
@ -16,7 +16,7 @@ export class FormBase {
|
||||||
throw new Error(msg)
|
throw new Error(msg)
|
||||||
}
|
}
|
||||||
this.ID_IRI = id_iri
|
this.ID_IRI = id_iri
|
||||||
this.content = {}
|
this.content = content
|
||||||
this.ignoredProperties = [
|
this.ignoredProperties = [
|
||||||
RDF.type.value,
|
RDF.type.value,
|
||||||
]
|
]
|
||||||
|
|
@ -230,7 +230,7 @@ export class FormBase {
|
||||||
var quadArray = RdfDS.getSubjectTriples(subject_term)
|
var quadArray = RdfDS.getSubjectTriples(subject_term)
|
||||||
var IdQuadExists = false
|
var IdQuadExists = false
|
||||||
quadArray.forEach((quad) => {
|
quadArray.forEach((quad) => {
|
||||||
var predicate_uri = toIRI(quad.predicate.value, RdfDS.prefixes)
|
var predicate_uri = toIRI(quad.predicate.value, RdfDS.data.prefixes)
|
||||||
if (predicate_uri === this.ID_IRI) {
|
if (predicate_uri === this.ID_IRI) {
|
||||||
IdQuadExists = true
|
IdQuadExists = true
|
||||||
}
|
}
|
||||||
|
|
@ -253,7 +253,7 @@ export class FormBase {
|
||||||
if (this.content[class_uri]) {
|
if (this.content[class_uri]) {
|
||||||
// If we are in edit mode, the first step is to delete existing quads from graphData
|
// If we are in edit mode, the first step is to delete existing quads from graphData
|
||||||
if (editMode) {
|
if (editMode) {
|
||||||
RdfDS.graph.deleteMatches(rdf.namedNode(node_uri), null, null, null)
|
RdfDS.data.graph.deleteMatches(rdf.namedNode(node_uri), null, null, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we generate the quads
|
// Then we generate the quads
|
||||||
|
|
@ -261,7 +261,7 @@ export class FormBase {
|
||||||
var quads = this.formNodeToQuads(class_uri, node_uri, shapesDS)
|
var quads = this.formNodeToQuads(class_uri, node_uri, shapesDS)
|
||||||
// and add them to the dataset
|
// and add them to the dataset
|
||||||
quads.forEach(quad => {
|
quads.forEach(quad => {
|
||||||
RdfDS.graph.add(quad)
|
RdfDS.addQuad(quad)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Some next steps depend on the type of the record's subject
|
// Some next steps depend on the type of the record's subject
|
||||||
|
|
@ -283,8 +283,8 @@ export class FormBase {
|
||||||
var objectQuads = RdfDS.getObjectTriples(rdf.namedNode(node_uri))
|
var objectQuads = RdfDS.getObjectTriples(rdf.namedNode(node_uri))
|
||||||
objectQuads.forEach((quad) => {
|
objectQuads.forEach((quad) => {
|
||||||
let new_quad = rdf.quad(quad.subject, quad.predicate, subject)
|
let new_quad = rdf.quad(quad.subject, quad.predicate, subject)
|
||||||
RdfDS.graph.delete(quad)
|
RdfDS.data.graph.delete(quad)
|
||||||
RdfDS.graph.add(new_quad)
|
RdfDS.data.graph.add(new_quad)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Change formdata node_uri to the actual id, if this was present:
|
// Change formdata node_uri to the actual id, if this was present:
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,35 @@ import formatsPretty from '@rdfjs/formats/pretty.js'
|
||||||
/**
|
/**
|
||||||
* A class wrapping an RDF dataset (quad-store) from the `rdf-ext` library.
|
* A class wrapping an RDF dataset (quad-store) from the `rdf-ext` library.
|
||||||
*/
|
*/
|
||||||
export class RdfDataset extends EventTarget {
|
export class RdfDataset {
|
||||||
/**
|
/**
|
||||||
* Create a wrapper object for an RDF dataset a.k.a. quad-store
|
* Create a wrapper object for an RDF dataset a.k.a. quad-store
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor(data = {}) {
|
||||||
super()
|
|
||||||
|
this.data = data;
|
||||||
this.rdfPretty = rdf.clone();
|
this.rdfPretty = rdf.clone();
|
||||||
this.rdfPretty.formats.import(formatsPretty);
|
this.rdfPretty.formats.import(formatsPretty);
|
||||||
this.prefixes = {};
|
|
||||||
this.serializedGraph = '';
|
this.data.prefixes = {};
|
||||||
this.graphLoaded = false;
|
this.data.serializedGraph = '';
|
||||||
this.prefixesLoaded = false;
|
this.data.graphLoaded = false;
|
||||||
this.graph = this.createDataset();
|
this.data.prefixesLoaded = false;
|
||||||
|
this.data.graph = this.createDataset();
|
||||||
|
|
||||||
|
this._eventTarget = new EventTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener(type, listener, options) {
|
||||||
|
this._eventTarget.addEventListener(type, listener, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEventListener(type, listener, options) {
|
||||||
|
this._eventTarget.removeEventListener(type, listener, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchEvent(event) {
|
||||||
|
return this._eventTarget.dispatchEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -61,7 +77,7 @@ export class RdfDataset extends EventTarget {
|
||||||
* Pre-load function to reset the graph loading state.
|
* Pre-load function to reset the graph loading state.
|
||||||
*/
|
*/
|
||||||
beforeLoadFn() {
|
beforeLoadFn() {
|
||||||
this.graphLoaded = false
|
this.data.graphLoaded = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -70,12 +86,12 @@ export class RdfDataset extends EventTarget {
|
||||||
* @param {import("rdf-ext").NamedNode} ns - The namespace associated with the prefix.
|
* @param {import("rdf-ext").NamedNode} ns - The namespace associated with the prefix.
|
||||||
*/
|
*/
|
||||||
onPrefixFn(prefix, ns) {
|
onPrefixFn(prefix, ns) {
|
||||||
this.prefixes[prefix] = ns.value;
|
this.data.prefixes[prefix] = ns.value;
|
||||||
this.dispatchEvent(new CustomEvent('prefix', { detail: { prefix, ns } }));
|
this.dispatchEvent(new CustomEvent('prefix', { detail: { prefix, ns } }));
|
||||||
}
|
}
|
||||||
onPrefixEndFn() {
|
onPrefixEndFn() {
|
||||||
this.prefixesLoaded = true
|
this.data.prefixesLoaded = true
|
||||||
this.dispatchEvent(new CustomEvent('prefixesLoaded', { detail: this.prefixes }));
|
this.dispatchEvent(new CustomEvent('prefixesLoaded', { detail: this.data.prefixes }));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -87,9 +103,9 @@ export class RdfDataset extends EventTarget {
|
||||||
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
||||||
}
|
}
|
||||||
async onDataEndFn() {
|
async onDataEndFn() {
|
||||||
this.serializedGraph = await this.serializeGraph()
|
this.data.serializedGraph = await this.serializeGraph()
|
||||||
this.graphLoaded = true
|
this.data.graphLoaded = true
|
||||||
this.dispatchEvent(new CustomEvent('graphLoaded', { detail: this.graph }));
|
this.dispatchEvent(new CustomEvent('graphLoaded', { detail: this.data.graph }));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -97,7 +113,7 @@ export class RdfDataset extends EventTarget {
|
||||||
* @param {import("rdf-ext").Quad} quad - The RDF quad to add.
|
* @param {import("rdf-ext").Quad} quad - The RDF quad to add.
|
||||||
*/
|
*/
|
||||||
addQuad(quad) {
|
addQuad(quad) {
|
||||||
this.graph.add(quad)
|
this.data.graph.add(quad)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -105,7 +121,7 @@ export class RdfDataset extends EventTarget {
|
||||||
* @returns {Promise<string>} The serialized RDF graph in Turtle format.
|
* @returns {Promise<string>} The serialized RDF graph in Turtle format.
|
||||||
*/
|
*/
|
||||||
async serializeGraph() {
|
async serializeGraph() {
|
||||||
return (await this.rdfPretty.io.dataset.toText('text/turtle', this.graph)).trim()
|
return (await this.rdfPretty.io.dataset.toText('text/turtle', this.data.graph)).trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -116,7 +132,7 @@ export class RdfDataset extends EventTarget {
|
||||||
isRdfList(node) {
|
isRdfList(node) {
|
||||||
let hasFirst = false;
|
let hasFirst = false;
|
||||||
let hasRest = false;
|
let hasRest = false;
|
||||||
this.graph.forEach((quad) => {
|
this.data.graph.forEach((quad) => {
|
||||||
if (quad.subject.equals(node)) {
|
if (quad.subject.equals(node)) {
|
||||||
if (quad.predicate.value === RDF.first.value) hasFirst = true;
|
if (quad.predicate.value === RDF.first.value) hasFirst = true;
|
||||||
if (quad.predicate.value === RDF.rest.value) hasRest = true;
|
if (quad.predicate.value === RDF.rest.value) hasRest = true;
|
||||||
|
|
@ -136,11 +152,11 @@ export class RdfDataset extends EventTarget {
|
||||||
while (currentNode && currentNode.value !== RDF.nil.value) {
|
while (currentNode && currentNode.value !== RDF.nil.value) {
|
||||||
let listItem = null;
|
let listItem = null;
|
||||||
// Get the first element in the RDF list
|
// Get the first element in the RDF list
|
||||||
this.graph.forEach((quad) => {
|
this.data.graph.forEach((quad) => {
|
||||||
if (quad.subject.equals(currentNode) && quad.predicate.value === RDF.first.value) {
|
if (quad.subject.equals(currentNode) && quad.predicate.value === RDF.first.value) {
|
||||||
// Resolve blank nodes recursively, but handle literals and IRIs separately
|
// Resolve blank nodes recursively, but handle literals and IRIs separately
|
||||||
if (quad.object.termType === "BlankNode") {
|
if (quad.object.termType === "BlankNode") {
|
||||||
listItem = this.resolveBlankNode(quad.object, this.graph);
|
listItem = this.resolveBlankNode(quad.object, this.data.graph);
|
||||||
} else if (quad.object.termType === "Literal") {
|
} else if (quad.object.termType === "Literal") {
|
||||||
listItem = quad.object.value; // Store literal value
|
listItem = quad.object.value; // Store literal value
|
||||||
} else if (quad.object.termType === "NamedNode") {
|
} else if (quad.object.termType === "NamedNode") {
|
||||||
|
|
@ -153,7 +169,7 @@ export class RdfDataset extends EventTarget {
|
||||||
}
|
}
|
||||||
// Move to the next item in the list (rdf:rest)
|
// Move to the next item in the list (rdf:rest)
|
||||||
let nextNode = null;
|
let nextNode = null;
|
||||||
this.graph.forEach((quad) => {
|
this.data.graph.forEach((quad) => {
|
||||||
if (quad.subject.equals(currentNode) && quad.predicate.value === RDF.rest.value) {
|
if (quad.subject.equals(currentNode) && quad.predicate.value === RDF.rest.value) {
|
||||||
nextNode = quad.object;
|
nextNode = quad.object;
|
||||||
}
|
}
|
||||||
|
|
@ -165,7 +181,7 @@ export class RdfDataset extends EventTarget {
|
||||||
|
|
||||||
resolveBlankNode(blankNode) {
|
resolveBlankNode(blankNode) {
|
||||||
let resolvedObject = {};
|
let resolvedObject = {};
|
||||||
this.graph.forEach((quad) => {
|
this.data.graph.forEach((quad) => {
|
||||||
if (quad.subject.equals(blankNode)) {
|
if (quad.subject.equals(blankNode)) {
|
||||||
const predicate = quad.predicate.value;
|
const predicate = quad.predicate.value;
|
||||||
const object = quad.object;
|
const object = quad.object;
|
||||||
|
|
@ -191,11 +207,11 @@ export class RdfDataset extends EventTarget {
|
||||||
getLiteralAndNamedNodes(predicate, propertyClass, prefixes) {
|
getLiteralAndNamedNodes(predicate, propertyClass, prefixes) {
|
||||||
var propClassCurie = toCURIE(propertyClass, prefixes)
|
var propClassCurie = toCURIE(propertyClass, prefixes)
|
||||||
// a) use the literal node with xsd data type
|
// a) use the literal node with xsd data type
|
||||||
const literalNodes = rdf.grapoi({ dataset: this.graph })
|
const literalNodes = rdf.grapoi({ dataset: this.data.graph })
|
||||||
.hasOut(predicate, rdf.literal(String(propClassCurie), XSD.anyURI))
|
.hasOut(predicate, rdf.literal(String(propClassCurie), XSD.anyURI))
|
||||||
.quads();
|
.quads();
|
||||||
// b) and the named node
|
// b) and the named node
|
||||||
const uriNodes = rdf.grapoi({ dataset: this.graph })
|
const uriNodes = rdf.grapoi({ dataset: this.data.graph })
|
||||||
.hasOut(predicate, rdf.namedNode(propertyClass))
|
.hasOut(predicate, rdf.namedNode(propertyClass))
|
||||||
.quads();
|
.quads();
|
||||||
// return as a concatenated array of quads
|
// return as a concatenated array of quads
|
||||||
|
|
@ -203,12 +219,12 @@ export class RdfDataset extends EventTarget {
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubjectTriples(someTerm) {
|
getSubjectTriples(someTerm) {
|
||||||
const quads = rdf.grapoi({ dataset: this.graph, term: someTerm }).out().quads();
|
const quads = rdf.grapoi({ dataset: this.data.graph, term: someTerm }).out().quads();
|
||||||
return Array.from(quads)
|
return Array.from(quads)
|
||||||
}
|
}
|
||||||
|
|
||||||
getObjectTriples(someTerm) {
|
getObjectTriples(someTerm) {
|
||||||
const quads = rdf.grapoi({ dataset: this.graph, term: someTerm }).in().quads();
|
const quads = rdf.grapoi({ dataset: this.data.graph, term: someTerm }).in().quads();
|
||||||
return Array.from(quads)
|
return Array.from(quads)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,13 @@ import { toIRI} from '../modules/utils';
|
||||||
|
|
||||||
export class ShapesDataset extends RdfDataset {
|
export class ShapesDataset extends RdfDataset {
|
||||||
|
|
||||||
constructor() {
|
constructor(data = {}) {
|
||||||
super()
|
super(data)
|
||||||
this.propertyGroups = {}
|
this.data.propertyGroups = {}
|
||||||
this.nodeShapes = {}
|
this.data.nodeShapes = {}
|
||||||
this.nodeShapeNames = {}
|
this.data.nodeShapeNames = {}
|
||||||
this.nodeShapeNamesArray = []
|
this.data.nodeShapeNamesArray = []
|
||||||
this.nodeShapeIRIs = null
|
this.data.nodeShapeIRIs = null
|
||||||
}
|
}
|
||||||
|
|
||||||
onDataFn(quad) {
|
onDataFn(quad) {
|
||||||
|
|
@ -25,30 +25,30 @@ export class ShapesDataset extends RdfDataset {
|
||||||
const object = quad.object;
|
const object = quad.object;
|
||||||
// Isolate sh:NodeShape instances
|
// Isolate sh:NodeShape instances
|
||||||
if (predicate === RDF.type.value && object.value === SHACL.NodeShape.value) {
|
if (predicate === RDF.type.value && object.value === SHACL.NodeShape.value) {
|
||||||
this.nodeShapes[subject] = {properties: []};
|
this.data.nodeShapes[subject] = {properties: []};
|
||||||
}
|
}
|
||||||
// Get properties of node shapes
|
// Get properties of node shapes
|
||||||
if (predicate === SHACL.property.value) {
|
if (predicate === SHACL.property.value) {
|
||||||
this.nodeShapes[subject].properties.push(object);
|
this.data.nodeShapes[subject].properties.push(object);
|
||||||
}
|
}
|
||||||
// Get property groups, if any
|
// Get property groups, if any
|
||||||
if (predicate === RDF.type.value && object.value === SHACL.PropertyGroup.value) {
|
if (predicate === RDF.type.value && object.value === SHACL.PropertyGroup.value) {
|
||||||
this.propertyGroups[subject] = {};
|
this.data.propertyGroups[subject] = {};
|
||||||
}
|
}
|
||||||
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
this.dispatchEvent(new CustomEvent('quad', { detail: quad }));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onDataEndFn() {
|
async onDataEndFn() {
|
||||||
// Loop through all nodeshapes to restructure them
|
// Loop through all nodeshapes to restructure them
|
||||||
for (const [key, val] of Object.entries(this.nodeShapes)) {
|
for (const [key, val] of Object.entries(this.data.nodeShapes)) {
|
||||||
// Get attributes (other than 'properties') of the nodeshape
|
// Get attributes (other than 'properties') of the nodeshape
|
||||||
this.graph.forEach(quad => {
|
this.data.graph.forEach(quad => {
|
||||||
if (quad.subject.value === key && quad.predicate.value != SHACL.property.value) {
|
if (quad.subject.value === key && quad.predicate.value != SHACL.property.value) {
|
||||||
// Check if the object is a blank node and resolve it
|
// Check if the object is a blank node and resolve it
|
||||||
if (quad.object.termType === 'BlankNode') {
|
if (quad.object.termType === 'BlankNode') {
|
||||||
this.nodeShapes[key][quad.predicate.value] = this.resolveBlankNode(quad.object);
|
this.data.nodeShapes[key][quad.predicate.value] = this.resolveBlankNode(quad.object);
|
||||||
} else {
|
} else {
|
||||||
this.nodeShapes[key][quad.predicate.value] = quad.object.value;
|
this.data.nodeShapes[key][quad.predicate.value] = quad.object.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -62,7 +62,7 @@ export class ShapesDataset extends RdfDataset {
|
||||||
} else {
|
} else {
|
||||||
// Non-blank nodes are kept as they are, but eventually store only their `.value`
|
// Non-blank nodes are kept as they are, but eventually store only their `.value`
|
||||||
var new_node = {};
|
var new_node = {};
|
||||||
this.graph.forEach((quad) => {
|
this.data.graph.forEach((quad) => {
|
||||||
if (quad.subject.value === node.value) {
|
if (quad.subject.value === node.value) {
|
||||||
new_node[quad.predicate.value] = quad.object.value; // Store only .value
|
new_node[quad.predicate.value] = quad.object.value; // Store only .value
|
||||||
}
|
}
|
||||||
|
|
@ -71,27 +71,27 @@ export class ShapesDataset extends RdfDataset {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const iri of Object.keys(this.nodeShapes)) {
|
for (const iri of Object.keys(this.data.nodeShapes)) {
|
||||||
var parts = iri.split('/')
|
var parts = iri.split('/')
|
||||||
this.nodeShapeNames[parts[parts.length - 1]] = iri
|
this.data.nodeShapeNames[parts[parts.length - 1]] = iri
|
||||||
}
|
}
|
||||||
this.nodeShapeNamesArray = Object.keys(this.nodeShapeNames).sort()
|
this.data.nodeShapeNamesArray = Object.keys(this.data.nodeShapeNames).sort()
|
||||||
this.nodeShapeIRIs = Object.keys(this.nodeShapes).sort()
|
this.data.nodeShapeIRIs = Object.keys(this.data.nodeShapes).sort()
|
||||||
// Now handle the (possibility of) property groups
|
// Now handle the (possibility of) property groups
|
||||||
for (const [key, value] of Object.entries(this.propertyGroups)) {
|
for (const [key, value] of Object.entries(this.data.propertyGroups)) {
|
||||||
this.graph.forEach(quad => {
|
this.data.graph.forEach(quad => {
|
||||||
if (quad.subject.value === key && quad.predicate.value != RDF.type.value ) {
|
if (quad.subject.value === key && quad.predicate.value != RDF.type.value ) {
|
||||||
this.propertyGroups[key][quad.predicate.value] = quad.object.value
|
this.data.propertyGroups[key][quad.predicate.value] = quad.object.value
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.serializedGraph = await this.serializeGraph()
|
this.data.serializedGraph = await this.serializeGraph()
|
||||||
this.graphLoaded = true
|
this.data.graphLoaded = true
|
||||||
this.dispatchEvent(new CustomEvent('graphLoaded', { detail: this.graph }));
|
this.dispatchEvent(new CustomEvent('graphLoaded', { detail: this.data.graph }));
|
||||||
}
|
}
|
||||||
|
|
||||||
getPropertyNodeKind(class_uri, property_uri, id_uri) {
|
getPropertyNodeKind(class_uri, property_uri, id_uri) {
|
||||||
var nodeShape = this.nodeShapes[class_uri]
|
var nodeShape = this.data.nodeShapes[class_uri]
|
||||||
var propertyShapes = nodeShape.properties
|
var propertyShapes = nodeShape.properties
|
||||||
// Find associated property shape, for information about nodekind
|
// Find associated property shape, for information about nodekind
|
||||||
var propertyShape = propertyShapes.find((prop) => prop[SHACL.path.value] == property_uri)
|
var propertyShape = propertyShapes.find((prop) => prop[SHACL.path.value] == property_uri)
|
||||||
|
|
@ -125,7 +125,7 @@ export class ShapesDataset extends RdfDataset {
|
||||||
if (propertyShape.hasOwnProperty(SHACL.class.value)) {
|
if (propertyShape.hasOwnProperty(SHACL.class.value)) {
|
||||||
var shClass = propertyShape[SHACL.class.value];
|
var shClass = propertyShape[SHACL.class.value];
|
||||||
// this now assumes that the class is part of the driving shacl shapes graph
|
// this now assumes that the class is part of the driving shacl shapes graph
|
||||||
var associatedNodeShape = this.nodeShapes[toIRI(shClass, this.prefixes)]
|
var associatedNodeShape = this.data.nodeShapes[toIRI(shClass, this.data.prefixes)]
|
||||||
var hasIdField = associatedNodeShape.properties.find((prop) => prop[SHACL.path.value] == id_uri)
|
var hasIdField = associatedNodeShape.properties.find((prop) => prop[SHACL.path.value] == id_uri)
|
||||||
if (hasIdField) {
|
if (hasIdField) {
|
||||||
nodeFunc = rdf.namedNode
|
nodeFunc = rdf.namedNode
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ describe('ClassDataset', () => {
|
||||||
|
|
||||||
console.log("Running ClassDataset Test 1...")
|
console.log("Running ClassDataset Test 1...")
|
||||||
|
|
||||||
expect(dataset.graphLoaded).toBe(false);
|
expect(dataset.data.graphLoaded).toBe(false);
|
||||||
expect(dataset.prefixesLoaded).toBe(false);
|
expect(dataset.data.prefixesLoaded).toBe(false);
|
||||||
|
|
||||||
server = httpServer.createServer({ });
|
server = httpServer.createServer({ });
|
||||||
server.listen(PORT, HOST, (err) => {
|
server.listen(PORT, HOST, (err) => {
|
||||||
|
|
@ -29,9 +29,9 @@ describe('ClassDataset', () => {
|
||||||
const fileUrl = `http://${HOST}:${PORT}/tests/mockData.ttl`
|
const fileUrl = `http://${HOST}:${PORT}/tests/mockData.ttl`
|
||||||
dataset.loadRDF(fileUrl);
|
dataset.loadRDF(fileUrl);
|
||||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||||
expect(dataset.graph.size).toBe(1);
|
expect(dataset.data.graph.size).toBe(1);
|
||||||
expect(dataset.graphLoaded).toBe(true);
|
expect(dataset.data.graphLoaded).toBe(true);
|
||||||
expect(dataset.prefixesLoaded).toBe(true);
|
expect(dataset.data.prefixesLoaded).toBe(true);
|
||||||
const serializedGraph = await dataset.serializeGraph();
|
const serializedGraph = await dataset.serializeGraph();
|
||||||
expect(serializedGraph).not.toContain('<http://example.com/subject>');
|
expect(serializedGraph).not.toContain('<http://example.com/subject>');
|
||||||
expect(serializedGraph).not.toContain('<http://example.com/predicate>');
|
expect(serializedGraph).not.toContain('<http://example.com/predicate>');
|
||||||
|
|
|
||||||
|
|
@ -93,7 +93,7 @@ describe('FormBase', () => {
|
||||||
form.saveNode(class_uri, subject_uri, shapesDS, rdfDSnew, false)
|
form.saveNode(class_uri, subject_uri, shapesDS, rdfDSnew, false)
|
||||||
// Even though formdata has 3 predicates for the record,
|
// Even though formdata has 3 predicates for the record,
|
||||||
// the id_iri field should not be saved as a separate quad
|
// the id_iri field should not be saved as a separate quad
|
||||||
expect(rdfDSnew.graph.size).toBe(2)
|
expect(rdfDSnew.data.graph.size).toBe(2)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ describe('RdfDataset', () => {
|
||||||
// test creation of class instance
|
// test creation of class instance
|
||||||
it('should create an empty dataset', () => {
|
it('should create an empty dataset', () => {
|
||||||
console.log(`Running RdfDataset Test ${i++}...`)
|
console.log(`Running RdfDataset Test ${i++}...`)
|
||||||
expect(dataset.graph.size).toBe(0);
|
expect(dataset.data.graph.size).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add a quad to the dataset', () => {
|
it('should add a quad to the dataset', () => {
|
||||||
|
|
@ -32,8 +32,8 @@ describe('RdfDataset', () => {
|
||||||
|
|
||||||
dataset.addQuad(quad);
|
dataset.addQuad(quad);
|
||||||
|
|
||||||
expect(dataset.graph.size).toBe(1);
|
expect(dataset.data.graph.size).toBe(1);
|
||||||
expect(dataset.graph.has(quad)).toBe(true);
|
expect(dataset.data.graph.has(quad)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should correctly detect an RDF list', () => {
|
it('should correctly detect an RDF list', () => {
|
||||||
|
|
@ -88,18 +88,18 @@ describe('RdfDataset', () => {
|
||||||
if (err && err.code !== 'EADDRINUSE') throw err;
|
if (err && err.code !== 'EADDRINUSE') throw err;
|
||||||
console.log(`Test server started on http://${HOST}:${PORT}`);
|
console.log(`Test server started on http://${HOST}:${PORT}`);
|
||||||
});
|
});
|
||||||
expect(dataset.graphLoaded).toBe(false);
|
expect(dataset.data.graphLoaded).toBe(false);
|
||||||
expect(dataset.prefixesLoaded).toBe(false);
|
expect(dataset.data.prefixesLoaded).toBe(false);
|
||||||
const fileUrl = `http://${HOST}:${PORT}/tests/mockData.ttl`
|
const fileUrl = `http://${HOST}:${PORT}/tests/mockData.ttl`
|
||||||
const graphLoadedHandler = vi.fn();
|
const graphLoadedHandler = vi.fn();
|
||||||
dataset.addEventListener('graphLoaded', graphLoadedHandler);
|
dataset.addEventListener('graphLoaded', graphLoadedHandler);
|
||||||
dataset.loadRDF(fileUrl);
|
dataset.loadRDF(fileUrl);
|
||||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||||
expect(graphLoadedHandler).toHaveBeenCalledTimes(1);
|
expect(graphLoadedHandler).toHaveBeenCalledTimes(1);
|
||||||
expect(dataset.graph.size).toBe(2);
|
expect(dataset.data.graph.size).toBe(2);
|
||||||
expect(dataset.prefixes['ex']).toBe('http://example.com/');
|
expect(dataset.data.prefixes['ex']).toBe('http://example.com/');
|
||||||
expect(dataset.graphLoaded).toBe(true);
|
expect(dataset.data.graphLoaded).toBe(true);
|
||||||
expect(dataset.prefixesLoaded).toBe(true);
|
expect(dataset.data.prefixesLoaded).toBe(true);
|
||||||
|
|
||||||
console.log(`Closing server on http://${HOST}:${PORT}`);
|
console.log(`Closing server on http://${HOST}:${PORT}`);
|
||||||
server.close();
|
server.close();
|
||||||
|
|
@ -112,7 +112,7 @@ describe('RdfDataset', () => {
|
||||||
dataset.addEventListener('prefix', prefixHandler);
|
dataset.addEventListener('prefix', prefixHandler);
|
||||||
dataset.onPrefixFn('ex', rdf.namedNode('http://example.com/'));
|
dataset.onPrefixFn('ex', rdf.namedNode('http://example.com/'));
|
||||||
expect(prefixHandler).toHaveBeenCalledTimes(1);
|
expect(prefixHandler).toHaveBeenCalledTimes(1);
|
||||||
expect(dataset.prefixes['ex']).toBe('http://example.com/');
|
expect(dataset.data.prefixes['ex']).toBe('http://example.com/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should resolve blank nodes correctly', () => {
|
it('should resolve blank nodes correctly', () => {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ describe('ShapesDataset', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should load RDF data from Turtle file and populate all shapes-related variables', async () => {
|
it('should load RDF data from Turtle file and populate all shapes-related variables', async () => {
|
||||||
expect(dataset.graphLoaded).toBe(false);
|
expect(dataset.data.graphLoaded).toBe(false);
|
||||||
expect(dataset.prefixesLoaded).toBe(false);
|
expect(dataset.data.prefixesLoaded).toBe(false);
|
||||||
server = httpServer.createServer({ });
|
server = httpServer.createServer({ });
|
||||||
server.listen(PORT, HOST, (err) => {
|
server.listen(PORT, HOST, (err) => {
|
||||||
if (err && err.code !== 'EADDRINUSE') throw err;
|
if (err && err.code !== 'EADDRINUSE') throw err;
|
||||||
|
|
@ -25,26 +25,26 @@ describe('ShapesDataset', () => {
|
||||||
const fileUrl = `http://${HOST}:${PORT}/tests/mockShapes.ttl`
|
const fileUrl = `http://${HOST}:${PORT}/tests/mockShapes.ttl`
|
||||||
dataset.loadRDF(fileUrl);
|
dataset.loadRDF(fileUrl);
|
||||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||||
expect(dataset.graphLoaded).toBe(true);
|
expect(dataset.data.graphLoaded).toBe(true);
|
||||||
expect(dataset.prefixesLoaded).toBe(true);
|
expect(dataset.data.prefixesLoaded).toBe(true);
|
||||||
expect(dataset.graph.size).toBe(318); // number of quads in the mockShapes.ttl file
|
expect(dataset.data.graph.size).toBe(318); // number of quads in the mockShapes.ttl file
|
||||||
// Test content of all loaded variables
|
// Test content of all loaded variables
|
||||||
expect(dataset.nodeShapeNames).toEqual(
|
expect(dataset.data.nodeShapeNames).toEqual(
|
||||||
{
|
{
|
||||||
AttributeSpecification: 'https://concepts.datalad.org/s/things/v1/AttributeSpecification',
|
AttributeSpecification: 'https://concepts.datalad.org/s/things/v1/AttributeSpecification',
|
||||||
Person: 'https://concepts.datalad.org/s/social/unreleased/Person',
|
Person: 'https://concepts.datalad.org/s/social/unreleased/Person',
|
||||||
DOI: 'https://concepts.datalad.org/s/identifiers/unreleased/DOI'
|
DOI: 'https://concepts.datalad.org/s/identifiers/unreleased/DOI'
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
expect(dataset.nodeShapeNamesArray).toEqual(['AttributeSpecification', 'DOI', 'Person'])
|
expect(dataset.data.nodeShapeNamesArray).toEqual(['AttributeSpecification', 'DOI', 'Person'])
|
||||||
expect(dataset.nodeShapeIRIs).toEqual(
|
expect(dataset.data.nodeShapeIRIs).toEqual(
|
||||||
[
|
[
|
||||||
'https://concepts.datalad.org/s/identifiers/unreleased/DOI',
|
'https://concepts.datalad.org/s/identifiers/unreleased/DOI',
|
||||||
'https://concepts.datalad.org/s/social/unreleased/Person',
|
'https://concepts.datalad.org/s/social/unreleased/Person',
|
||||||
'https://concepts.datalad.org/s/things/v1/AttributeSpecification'
|
'https://concepts.datalad.org/s/things/v1/AttributeSpecification'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
expect(dataset.propertyGroups).toEqual(
|
expect(dataset.data.propertyGroups).toEqual(
|
||||||
{
|
{
|
||||||
'https://concepts.datalad.org/s/things/v1/BasicPropertyGroup': {
|
'https://concepts.datalad.org/s/things/v1/BasicPropertyGroup': {
|
||||||
'http://www.w3.org/ns/shacl#order': '0',
|
'http://www.w3.org/ns/shacl#order': '0',
|
||||||
|
|
@ -58,7 +58,7 @@ describe('ShapesDataset', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
expect(dataset.prefixes).toEqual(
|
expect(dataset.data.prefixes).toEqual(
|
||||||
{
|
{
|
||||||
'ex': 'http://example.com/',
|
'ex': 'http://example.com/',
|
||||||
'dlidentifiers': 'https://concepts.datalad.org/s/identifiers/unreleased/',
|
'dlidentifiers': 'https://concepts.datalad.org/s/identifiers/unreleased/',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue