Support the correct nodeKind determination for a limited sh:or scenario #13
4 changed files with 45 additions and 8 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "shacl-tulip",
|
"name": "shacl-tulip",
|
||||||
"version": "0.0.3",
|
"version": "0.0.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./src/index.js",
|
"main": "./src/index.js",
|
||||||
"module": "./src/index.js",
|
"module": "./src/index.js",
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,19 @@ dlsocial:Person a sh:NodeShape ;
|
||||||
sh:maxCount 1 ;
|
sh:maxCount 1 ;
|
||||||
sh:nodeKind sh:IRI ;
|
sh:nodeKind sh:IRI ;
|
||||||
sh:order 2 ;
|
sh:order 2 ;
|
||||||
sh:path dlspatial:at_location ] ;
|
sh:path dlspatial:at_location ],
|
||||||
|
[ sh:description "The type of person, which is one of two classes: a 'Parent' or a 'Child'" ;
|
||||||
|
sh:maxCount 1 ;
|
||||||
|
sh:minCount 1 ;
|
||||||
|
sh:or ( [ sh:class ex:Parent ] [ sh:class ex:Child ] ) ;
|
||||||
|
sh:order 1 ;
|
||||||
|
sh:path dlthings:person_type ],
|
||||||
|
[ sh:description "The organization that the Person belongs to" ;
|
||||||
|
sh:maxCount 1 ;
|
||||||
|
sh:minCount 1 ;
|
||||||
|
sh:or ( [ sh:class ex:Organization ] [ sh:nodeKind sh:Literal ; sh:datatype xsd:string ] ) ;
|
||||||
|
sh:order 1 ;
|
||||||
|
sh:path dlthings:belongs_to ] ;
|
||||||
sh:targetClass dlsocial:Person .
|
sh:targetClass dlsocial:Person .
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,6 +145,15 @@ export class ShapesDataset extends RdfDataset {
|
||||||
// Assume Literal nodekind for any arrays
|
// Assume Literal nodekind for any arrays
|
||||||
console.log(`\t- NodeKind not found for property shape: ${property_uri}; found 'sh:in'. Setting to default literal`)
|
console.log(`\t- NodeKind not found for property shape: ${property_uri}; found 'sh:in'. Setting to default literal`)
|
||||||
nodeFunc = literal
|
nodeFunc = literal
|
||||||
|
} else if (
|
||||||
|
propertyShape.hasOwnProperty(SHACL.or.value) &&
|
||||||
|
Array.isArray(propertyShape[SHACL.or.value]) &&
|
||||||
|
propertyShape[SHACL.or.value].every(obj => obj.hasOwnProperty(SHACL.class.value))
|
||||||
|
) {
|
||||||
|
// This is a temporary solution to exactly match the property values entered using `shacl-vue`'s `ShaclORClassEditor`
|
||||||
|
// A future replacement should account for a generic `sh:or`
|
||||||
|
console.log(`\t- NodeKind not found for property shape: ${property_uri}; found 'sh:or' with every element containing 'sh:class'. Setting to namedNode`)
|
||||||
|
nodeFunc = namedNode
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.log(`\t- NodeKind not found for property shape: ${property_uri}. Setting to default literal`)
|
console.log(`\t- NodeKind not found for property shape: ${property_uri}. Setting to default literal`)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { describe, it, expect, beforeEach} from 'vitest';
|
import { describe, it, expect, beforeEach} from 'vitest';
|
||||||
import { ShapesDataset } from '@/classes/ShapesDataset';
|
import { ShapesDataset } from '@/classes/ShapesDataset';
|
||||||
import { DataFactory } from 'n3';
|
import { DataFactory, NamedNode } from 'n3';
|
||||||
const { literal, blankNode } = DataFactory;
|
const { literal, blankNode, namedNode } = DataFactory;
|
||||||
import httpServer from 'http-server';
|
import httpServer from 'http-server';
|
||||||
let server;
|
let server;
|
||||||
const PORT = 8082;
|
const PORT = 8082;
|
||||||
|
|
@ -28,7 +28,7 @@ describe('ShapesDataset', () => {
|
||||||
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve));
|
||||||
expect(dataset.data.graphLoaded).toBe(true);
|
expect(dataset.data.graphLoaded).toBe(true);
|
||||||
expect(dataset.data.prefixesLoaded).toBe(true);
|
expect(dataset.data.prefixesLoaded).toBe(true);
|
||||||
expect(dataset.data.graph.size).toBe(318); // number of quads in the mockShapes.ttl file
|
expect(dataset.data.graph.size).toBe(345); // number of quads in the mockShapes.ttl file
|
||||||
// Test content of all loaded variables
|
// Test content of all loaded variables
|
||||||
expect(dataset.data.nodeShapeNames).toEqual(
|
expect(dataset.data.nodeShapeNames).toEqual(
|
||||||
{
|
{
|
||||||
|
|
@ -76,16 +76,15 @@ describe('ShapesDataset', () => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
// Test getPropertyNodeKind
|
// Test getPropertyNodeKind
|
||||||
|
// Test literal nodekind
|
||||||
// expect(getPropertyNodeKind(class_uri, property_uri, id_uri))
|
|
||||||
var nk1 = dataset.getPropertyNodeKind(
|
var nk1 = dataset.getPropertyNodeKind(
|
||||||
'https://concepts.datalad.org/s/social/unreleased/Person',
|
'https://concepts.datalad.org/s/social/unreleased/Person',
|
||||||
'https://concepts.datalad.org/s/social/unreleased/honorific_name_prefix',
|
'https://concepts.datalad.org/s/social/unreleased/honorific_name_prefix',
|
||||||
'https://concepts.datalad.org/s/things/v1/id'
|
'https://concepts.datalad.org/s/things/v1/id'
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(nk1[0]).toBeTypeOf('function')
|
expect(nk1[0]).toBeTypeOf('function')
|
||||||
expect(nk1[0]).toEqual(literal)
|
expect(nk1[0]).toEqual(literal)
|
||||||
|
// Test blankNode
|
||||||
var nk2 = dataset.getPropertyNodeKind(
|
var nk2 = dataset.getPropertyNodeKind(
|
||||||
'https://concepts.datalad.org/s/social/unreleased/Person',
|
'https://concepts.datalad.org/s/social/unreleased/Person',
|
||||||
'https://concepts.datalad.org/s/things/v1/attributes',
|
'https://concepts.datalad.org/s/things/v1/attributes',
|
||||||
|
|
@ -93,6 +92,23 @@ describe('ShapesDataset', () => {
|
||||||
)
|
)
|
||||||
expect(nk2[0]).toBeTypeOf('function')
|
expect(nk2[0]).toBeTypeOf('function')
|
||||||
expect(nk2[0]).toEqual(blankNode)
|
expect(nk2[0]).toEqual(blankNode)
|
||||||
|
// Test sh:or with ALL elements in array containing sh:class
|
||||||
|
var nk3 = dataset.getPropertyNodeKind(
|
||||||
|
'https://concepts.datalad.org/s/social/unreleased/Person',
|
||||||
|
'https://concepts.datalad.org/s/things/v1/person_type',
|
||||||
|
'https://concepts.datalad.org/s/things/v1/id'
|
||||||
|
)
|
||||||
|
expect(nk3[0]).toBeTypeOf('function')
|
||||||
|
expect(nk3[0]).toEqual(namedNode)
|
||||||
|
// Test sh:or with NOT all elements in array containing sh:class
|
||||||
|
var nk4 = dataset.getPropertyNodeKind(
|
||||||
|
'https://concepts.datalad.org/s/social/unreleased/Person',
|
||||||
|
'https://concepts.datalad.org/s/things/v1/belongs_to',
|
||||||
|
'https://concepts.datalad.org/s/things/v1/id'
|
||||||
|
)
|
||||||
|
expect(nk4[0]).toBeTypeOf('function')
|
||||||
|
expect(nk4[0]).toEqual(literal)
|
||||||
|
|
||||||
server.close();
|
server.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue