diff --git a/.changeset/modern-masks-knock.md b/.changeset/modern-masks-knock.md new file mode 100644 index 0000000..a6e3285 --- /dev/null +++ b/.changeset/modern-masks-knock.md @@ -0,0 +1,5 @@ +--- +"cube-link": patch +--- + +Visualize validation profile (closes #114) diff --git a/package-lock.json b/package-lock.json index e498ed8..7a95d09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "cube-link", - "version": "0.1.3", + "version": "0.1.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cube-link", - "version": "0.1.3", + "version": "0.1.4", "license": "MIT", "dependencies": { "@rdfjs/namespace": "^1.1.0", diff --git a/package.json b/package.json index a45841f..7ea6113 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "test:basic-cube-constraint": "./test/check-metadata.sh --profile=basic-cube-constraint", "test:standalone-cube-constraint": "./test/check-metadata.sh --profile=standalone-cube-constraint", "test:standalone-constraint-constraint": "./test/check-metadata.sh --profile=standalone-constraint-constraint", + "test:profile-visualize": "./test/check-metadata.sh --profile=profile-visualize", "test:profile-opendataswiss": "./test/check-metadata.sh --profile=profile-opendataswiss", "test:profile-opendataswiss-lindas": "./test/check-metadata.sh --profile=profile-opendataswiss-lindas", "release": "changeset tag" diff --git a/test/profile-visualize/invalid-datatype-langstring.ttl b/test/profile-visualize/invalid-datatype-langstring.ttl new file mode 100644 index 0000000..93d692b --- /dev/null +++ b/test/profile-visualize/invalid-datatype-langstring.ttl @@ -0,0 +1,56 @@ +PREFIX rdfs: +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + schema:workExample ; + schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + 4.9 . + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + schema:name "Value" ; + sh:path ; + sh:datatype rdf:langString ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/test/profile-visualize/invalid-datatype-langstring.ttl.approved.txt b/test/profile-visualize/invalid-datatype-langstring.ttl.approved.txt new file mode 100644 index 0000000..c8af1f6 --- /dev/null +++ b/test/profile-visualize/invalid-datatype-langstring.ttl.approved.txt @@ -0,0 +1,63 @@ +@prefix sh: . +@prefix rdf: . +@prefix schema: . +@prefix xsd: . +@prefix cube: . + +_:report a sh:ValidationReport ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeConstraintComponent ; + sh:sourceShape [ + sh:path cube:observationConstraint ; + sh:maxCount 1 ; + sh:minCount 1 ; + sh:node ; + ] ; + sh:focusNode ; + sh:value ; + sh:resultMessage "Value does not have shape " ; + sh:detail [ + rdf:type sh:ValidationResult ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:NodeKindConstraintComponent ; + sh:sourceShape [ + sh:nodeKind sh:IRI ; + ] ; + sh:focusNode _:b1 ; + sh:value _:b1 ; + sh:resultMessage "Value does not have node kind " ; + ], [ + rdf:type sh:ValidationResult ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:OrConstraintComponent ; + sh:sourceShape _:b393 ; + sh:focusNode ; + sh:value _:b2 ; + sh:resultMessage "Observation constraint must have exactly one datatype. It cannot be rdf:langString" ; + sh:resultPath sh:property ; + ] ; + sh:resultPath cube:observationConstraint ; + ], [ + rdf:type sh:ValidationResult ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:OrConstraintComponent ; + sh:sourceShape _:b393 ; + sh:focusNode ; + sh:value _:b2 ; + sh:resultMessage "Observation constraint must have exactly one datatype. It cannot be rdf:langString" ; + sh:resultPath sh:property ; + ] ; + sh:conforms false . + +_:b393 sh:path sh:property ; + sh:or ( + [ + sh:node ; + ] + [ + sh:node ; + ] + ) ; + sh:message "Observation constraint must have exactly one datatype. It cannot be rdf:langString" . diff --git a/test/profile-visualize/invalid-no-status.ttl b/test/profile-visualize/invalid-no-status.ttl new file mode 100644 index 0000000..7658786 --- /dev/null +++ b/test/profile-visualize/invalid-no-status.ttl @@ -0,0 +1,55 @@ +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + schema:workExample ; + # schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + 4.9 . + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + schema:name "Value" ; + sh:path ; + sh:datatype xsd:decimal ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/test/profile-visualize/invalid-no-status.ttl.approved.txt b/test/profile-visualize/invalid-no-status.ttl.approved.txt new file mode 100644 index 0000000..7043212 --- /dev/null +++ b/test/profile-visualize/invalid-no-status.ttl.approved.txt @@ -0,0 +1,24 @@ +@prefix sh: . +@prefix rdf: . +@prefix schema: . +@prefix xsd: . +@prefix cube: . + +_:report a sh:ValidationReport ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:MinCountConstraintComponent ; + sh:sourceShape [ + sh:path schema:creativeWorkStatus ; + sh:in ( + + + ) ; + sh:minCount 1 ; + ] ; + sh:focusNode ; + sh:resultPath schema:creativeWorkStatus ; + sh:resultMessage "Less than 1 values" ; + ] ; + sh:conforms false . diff --git a/test/profile-visualize/invalid-temporal.ttl b/test/profile-visualize/invalid-temporal.ttl new file mode 100644 index 0000000..fdc06af --- /dev/null +++ b/test/profile-visualize/invalid-temporal.ttl @@ -0,0 +1,63 @@ +PREFIX time: +PREFIX qudt: +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + schema:workExample ; + schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + "2000"^^xsd:gYear ; +. + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + # no datatype, no time:unitType + schema:name "Year" ; + sh:path ; + sh:nodeKind sh:Literal ; + meta:dataKind + [ + a time:GeneralDateTimeDescription ; + ] ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/test/profile-visualize/invalid-temporal.ttl.approved.txt b/test/profile-visualize/invalid-temporal.ttl.approved.txt new file mode 100644 index 0000000..09c56d6 --- /dev/null +++ b/test/profile-visualize/invalid-temporal.ttl.approved.txt @@ -0,0 +1,17 @@ +@prefix sh: . +@prefix rdf: . +@prefix schema: . +@prefix xsd: . +@prefix cube: . + +_:report a sh:ValidationReport ; + sh:result [ + rdf:type sh:ValidationResult ; + sh:resultSeverity sh:Violation ; + sh:sourceConstraintComponent sh:OrConstraintComponent ; + sh:sourceShape ; + sh:focusNode _:b3 ; + sh:value _:b3 ; + sh:resultMessage "Temporal dimension must be one of XSD datatypes: gYear, gYearMonth, date, dateTime, or have time:unitType" ; + ] ; + sh:conforms false . diff --git a/test/profile-visualize/valid-draft.ttl b/test/profile-visualize/valid-draft.ttl new file mode 100644 index 0000000..2f72ac5 --- /dev/null +++ b/test/profile-visualize/valid-draft.ttl @@ -0,0 +1,55 @@ +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + schema:workExample ; + schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + 4.9 . + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + schema:name "Value" ; + sh:path ; + sh:datatype xsd:decimal ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/test/profile-visualize/valid-temporal.ttl b/test/profile-visualize/valid-temporal.ttl new file mode 100644 index 0000000..9e255ff --- /dev/null +++ b/test/profile-visualize/valid-temporal.ttl @@ -0,0 +1,93 @@ +PREFIX time: +PREFIX qudt: +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + schema:workExample ; + schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + "2000"^^xsd:gYear ; + "2000-06"^^xsd:gYearMonth ; + "2000-06-01"^^xsd:date ; +
"2000-06-01T11:10Z"^^xsd:dateTime ; +. + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + schema:name "Year" ; + sh:path ; + sh:nodeKind sh:Literal ; + meta:dataKind + [ + a time:GeneralDateTimeDescription ; + time:unitType time:unitYear ; + ] ; + ], + [ + schema:name "Year-Month" ; + sh:path ; + sh:datatype xsd:gYearMonth ; + meta:dataKind + [ + a time:GeneralDateTimeDescription ; + ] ; + ], + [ + schema:name "Date" ; + sh:path ; + sh:datatype xsd:date ; + meta:dataKind + [ + a time:GeneralDateTimeDescription ; + ] ; + ], + [ + schema:name "DateTime" ; + sh:path
; + sh:datatype xsd:dateTime ; + meta:dataKind + [ + a time:GeneralDateTimeDescription ; + ] ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/test/profile-visualize/valid-work-example-warning.ttl b/test/profile-visualize/valid-work-example-warning.ttl new file mode 100644 index 0000000..d16f53e --- /dev/null +++ b/test/profile-visualize/valid-work-example-warning.ttl @@ -0,0 +1,55 @@ +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + # schema:workExample ; + schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + 4.9 . + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + schema:name "Value" ; + sh:path ; + sh:datatype xsd:decimal ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/test/profile-visualize/valid.ttl b/test/profile-visualize/valid.ttl new file mode 100644 index 0000000..6368745 --- /dev/null +++ b/test/profile-visualize/valid.ttl @@ -0,0 +1,60 @@ +PREFIX rdf: +PREFIX meta: +PREFIX sh: +PREFIX xsd: +PREFIX dcterms: +PREFIX schema: +PREFIX dcat: +PREFIX cube: +PREFIX ex: + +ex:Cube + a cube:Cube, dcat:Dataset ; + cube:observationSet ; + cube:observationConstraint ; + schema:name "Example cube" ; + schema:publisher ; + schema:creator ; + schema:contributor ; + dcterms:identifier "cube-1234" ; + schema:workExample ; + schema:creativeWorkStatus ; + dcterms:creator ex:John-Doe ; + schema:dateCreated "2020-10-10"^^xsd:date ; + schema:dateModified "2020-10-10"^^xsd:date ; + schema:datePublished "2020-11-11"^^xsd:date ; + schema:contactPoint + [ + schema:name "John Doe" ; + schema:email "john@doe.tech" ; + ] ; +. + + cube:observation . + + a cube:Observation ; + cube:observedBy ; + 4.9 . + + a cube:Constraint ; + sh:closed true ; + sh:property + [ + schema:name "Dimenson 1" ; + sh:path ; + sh:datatype xsd:decimal ; + ], + [ + schema:name "Measure" ; + sh:path ; + sh:datatype xsd:decimal ; + ], + [ + sh:path rdf:type ; + sh:nodeKind sh:IRI + ], + [ + sh:path cube:observedBy ; + sh:nodeKind sh:IRI + ] ; +. diff --git a/validation/profile-visualize.ttl b/validation/profile-visualize.ttl new file mode 100644 index 0000000..f6e2ab3 --- /dev/null +++ b/validation/profile-visualize.ttl @@ -0,0 +1,123 @@ +PREFIX meta: +PREFIX time: +PREFIX rdf: +PREFIX xsd: +PREFIX dcterms: +PREFIX dcat: +PREFIX schema: +PREFIX sh: +prefix code: +prefix cube: +prefix : + +[ + code:imports <./standalone-cube-constraint> ; + code:extension "ttl" ; +] . + +:CubeShape + a sh:NodeShape ; + sh:targetClass cube:Cube ; + sh:property + [ + sh:path cube:observationConstraint ; + sh:node :ObservationConstraintShape ; + sh:minCount 1 ; + sh:maxCount 1 ; + ], + [ + sh:path schema:name ; + sh:minCount 1 ; + sh:dataType xsd:langString ; + ], + [ + sh:path dcterms:creator ; + sh:minCount 1 ; + sh:severity sh:Warning ; + sh:deactivated true ; + ], + [ + sh:path schema:workExample ; + sh:hasValue ; + ], + [ + sh:path schema:creativeWorkStatus ; + sh:minCount 1 ; + sh:in + ( + + + ) ; + ], + [ + sh:path [ sh:alternativePath ( schema:validThrough schema:expires ) ] ; + sh:maxCount 0 ; + sh:message "Cube cannot be expired" ; + ] ; +. + + +:ObservationConstraintShape + a sh:NodeShape ; + sh:targetClass cube:Constraint ; + sh:property + [ + sh:path sh:property ; + sh:or + ( + [ + sh:node :ObservationConstraintDatatypeProperty ; + ] + [ + sh:node :ObservationConstraintCoreProperty ; + ] + ) ; + sh:message "Observation constraint must have exactly one datatype. It cannot be rdf:langString" + ] ; +. + +:ObservationConstraintDatatypeProperty + sh:property + [ + sh:path sh:datatype ; + sh:maxCount 1 ; + sh:not [ sh:hasValue rdf:langString ] ; + ] ; +. + +:ObservationConstraintCoreProperty + sh:property + [ + sh:path sh:path ; + sh:in ( rdf:type cube:observedBy ) + ] ; +. + +:TemporalDimensionConstraint + a sh:NodeShape ; + sh:targetClass time:GeneralDateTimeDescription ; + sh:message "Temporal dimension must be one of XSD datatypes: gYear, gYearMonth, date, dateTime, or have time:unitType" ; + sh:or + ( + [ + sh:property + [ + sh:path ( [ sh:inversePath meta:dataKind ] sh:datatype ) ; + sh:minCount 1 ; + sh:in ( xsd:gYear xsd:gYearMonth xsd:date xsd:dateTime ) ; + ], + [ + sh:path time:unitType ; + sh:maxCount 0 ; + ] + ] + [ + sh:property + [ + sh:path time:unitType ; + sh:minCount 1 ; + sh:maxCount 1 ; + ] ; + ] + ) +.