diff --git a/package.json b/package.json index fdae6c5..5d5468f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shacl-tulip", - "version": "0.0.3", + "version": "0.0.4", "type": "module", "main": "./src/index.js", "module": "./src/index.js", diff --git a/public/tests/mockShapes.ttl b/public/tests/mockShapes.ttl index 189f32c..9d50430 100644 --- a/public/tests/mockShapes.ttl +++ b/public/tests/mockShapes.ttl @@ -166,7 +166,19 @@ dlsocial:Person a sh:NodeShape ; sh:maxCount 1 ; sh:nodeKind sh:IRI ; 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 . diff --git a/src/classes/ShapesDataset.js b/src/classes/ShapesDataset.js index 629c2e3..aa2badf 100644 --- a/src/classes/ShapesDataset.js +++ b/src/classes/ShapesDataset.js @@ -145,6 +145,15 @@ export class ShapesDataset extends RdfDataset { // Assume Literal nodekind for any arrays console.log(`\t- NodeKind not found for property shape: ${property_uri}; found 'sh:in'. Setting to default 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 { console.log(`\t- NodeKind not found for property shape: ${property_uri}. Setting to default literal`) diff --git a/tests/ShapesDataset.test.js b/tests/ShapesDataset.test.js index edf6a18..f852ad5 100644 --- a/tests/ShapesDataset.test.js +++ b/tests/ShapesDataset.test.js @@ -1,7 +1,7 @@ import { describe, it, expect, beforeEach} from 'vitest'; import { ShapesDataset } from '@/classes/ShapesDataset'; -import { DataFactory } from 'n3'; -const { literal, blankNode } = DataFactory; +import { DataFactory, NamedNode } from 'n3'; +const { literal, blankNode, namedNode } = DataFactory; import httpServer from 'http-server'; let server; const PORT = 8082; @@ -28,7 +28,7 @@ describe('ShapesDataset', () => { await new Promise(resolve => dataset.addEventListener('graphLoaded', resolve)); expect(dataset.data.graphLoaded).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 expect(dataset.data.nodeShapeNames).toEqual( { @@ -76,16 +76,15 @@ describe('ShapesDataset', () => { } ) // Test getPropertyNodeKind - - // expect(getPropertyNodeKind(class_uri, property_uri, id_uri)) + // Test literal nodekind var nk1 = dataset.getPropertyNodeKind( 'https://concepts.datalad.org/s/social/unreleased/Person', 'https://concepts.datalad.org/s/social/unreleased/honorific_name_prefix', 'https://concepts.datalad.org/s/things/v1/id' ) - expect(nk1[0]).toBeTypeOf('function') expect(nk1[0]).toEqual(literal) + // Test blankNode var nk2 = dataset.getPropertyNodeKind( 'https://concepts.datalad.org/s/social/unreleased/Person', 'https://concepts.datalad.org/s/things/v1/attributes', @@ -93,6 +92,23 @@ describe('ShapesDataset', () => { ) expect(nk2[0]).toBeTypeOf('function') 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(); });