├── .github ├── CODEOWNERS ├── dependabot.yml └── workflows │ ├── release.yaml │ ├── ci.yaml │ └── test.yaml ├── .gitignore ├── .dockerignore ├── views ├── meta.html ├── index.html └── relation.html ├── img ├── cube-link-basic.png ├── cube-link-dimensions.png └── cube-link-observedBy.png ├── meta ├── abstract.md ├── index.html ├── config.js └── meta.ttl ├── relation ├── abstract.md ├── index.html ├── config.js ├── core.md └── relation.ttl ├── trifid ├── config.local.json ├── config.json ├── redirect.cjs └── config-base.json ├── test ├── check-metadata.sh ├── observations │ ├── withoutName.ttl.approved.txt │ ├── withoutType.ttl.approved.txt │ ├── undefinedAllowed.ttl.approved.txt │ ├── undefinedOrBounded.ttl.approved.txt │ ├── undefinedNotAllowed.ttl.approved.txt │ ├── withoutName.ttl │ ├── withoutType.ttl │ ├── undefinedNotAllowed.ttl │ ├── undefinedAllowed.ttl │ └── undefinedOrBounded.ttl ├── basic-cube-constraint │ ├── valid.minimal.ttl │ ├── invalid.withoutObservationSet.ttl │ ├── invalid.withoutProperties.ttl │ ├── invalid.withoutObservations.ttl │ ├── invalid.withoutObservationSet.ttl.approved.txt │ ├── invalid.withoutProperties.ttl.approved.txt │ └── invalid.withoutObservations.ttl.approved.txt ├── profile-opendataswiss-lindas │ ├── invalid.noTypeDataset.ttl.approved.txt │ ├── invalid.noWorkExample.ttl.approved.txt │ ├── invalid.expired.ttl.approved.txt │ ├── invalid.draft.ttl.approved.txt │ ├── invalid.draft.ttl │ ├── valid.ttl │ ├── invalid.noTypeDataset.ttl │ ├── invalid.noWorkExample.ttl │ └── invalid.expired.ttl ├── profile-visualize │ ├── warning-missing-sh-in.ttl.approved.txt │ ├── invalid-no-status.ttl.approved.txt │ ├── invalid-data-kind-unexpected.ttl.approved.txt │ ├── invalid-data-kinds.ttl.approved.txt │ ├── invalid-datatype-langstring.ttl.approved.txt │ ├── invalid-datatype-multiple.ttl.approved.txt │ ├── invalid-no-status.ttl │ ├── valid-work-example-warning.ttl │ ├── valid-draft.ttl │ ├── invalid-datatype-langstring.ttl │ ├── invalid-datatype-multiple.ttl │ ├── invalid-temporal.ttl.approved.txt │ ├── valid.ttl │ ├── warning-missing-sh-in.ttl │ ├── valid-sh-in.ttl │ ├── invalid-scale-types.ttl │ ├── valid-data-kinds.ttl │ ├── invalid-data-kinds.ttl │ ├── invalid-temporal.ttl │ ├── invalid-data-kind-unexpected.ttl │ └── invalid-scale-types.ttl.approved.txt ├── standalone-constraint-constraint │ ├── invalid.dimensionRelation-multipleDcType.ttl.approved.txt │ ├── invalid.annotation-missingValue.ttl.approved.txt │ ├── invalid.annotation-invalidRanges.ttl.approved.txt │ ├── invalid.annotation-mixedConstraints.ttl.approved.txt │ ├── invalid.annotation-tooManyValues.ttl.approved.txt │ ├── warning-qudt-unit.ttl.approved.txt │ ├── invalid.withoutName.ttl.approved.txt │ ├── invalid.withoutType.ttl.approved.txt │ ├── invalid.withoutName.ttl │ ├── invalid.withoutType.ttl │ ├── valid.undefinedNotAllowed.ttl │ ├── valid.undefinedAllowed.ttl │ ├── invalid.annotation-keyDimensions.ttl.approved.txt │ ├── valid.undefinedOrBounded.ttl │ ├── invalid.dimensionRelation-relatesToNotMatching.ttl.approved.txt │ ├── invalid.malformedList.ttl │ ├── warning-qudt-unit.ttl │ ├── invalid.dimensionRelation-relatesToNotMatching.ttl │ ├── invalid.dimensionRelation-multipleDcType.ttl │ ├── invalid.malformedList.ttl.approved.txt │ ├── invalid.annotation-missingValue.ttl │ ├── valid.dimensionRelation.ttl │ ├── invalid.annotation-mixedConstraints.ttl │ ├── invalid.annotation-invalidRanges.ttl │ ├── invalid.annotation-keyDimensions.ttl │ ├── invalid.annotation-tooManyValues.ttl │ └── valid.annotation.ttl ├── profile-opendataswiss │ ├── invalid.missing-identifier.cube.ttl.approved.txt │ ├── invalid.publisherNoClass.ttl.approved.txt │ ├── invalid.missing-identifier.cube.ttl │ ├── invalid.publisherNoClass.ttl │ ├── valid.publisherBlankNode.ttl │ └── valid.ttl ├── standalone-cube-constraint │ ├── invalid.blankContactPoint.missingEmail.ttl.approved.txt │ ├── invalid.blankContactPoint.missingName.ttl.approved.txt │ ├── valid.blankContactPoint.ttl │ ├── invalid.blankContactPoint.missingName.ttl │ └── invalid.blankContactPoint.missingEmail.ttl └── check-observations.sh ├── .changeset ├── config.json └── README.md ├── documentation ├── abstract.md ├── existingwork.md └── constraints.md ├── validation ├── profile-opendataswiss-lindas.ttl ├── shared │ └── data-kind.ttl ├── basic-cube-constraint.ttl └── basic-cube-constraint-ml.ttl ├── Dockerfile ├── config.js ├── best-practice.md ├── index.html ├── package.json ├── vocab.ttl ├── constraint.ttl ├── CHANGELOG.md └── README.md /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | /.github/ @ludovicm67 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | *.received.* 4 | *.log 5 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gitignore 3 | node_modules/ 4 | Dockerfile 5 | .github 6 | -------------------------------------------------------------------------------- /views/meta.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

meta

4 | 5 | 6 | -------------------------------------------------------------------------------- /views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

index

4 | 5 | 6 | -------------------------------------------------------------------------------- /views/relation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

relation

4 | 5 | 6 | -------------------------------------------------------------------------------- /img/cube-link-basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zazuko/cube-link/HEAD/img/cube-link-basic.png -------------------------------------------------------------------------------- /img/cube-link-dimensions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zazuko/cube-link/HEAD/img/cube-link-dimensions.png -------------------------------------------------------------------------------- /img/cube-link-observedBy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zazuko/cube-link/HEAD/img/cube-link-observedBy.png -------------------------------------------------------------------------------- /meta/abstract.md: -------------------------------------------------------------------------------- 1 | This vocubulary is intended as a companion vocabulary to the [Cube Schema vocabulary](..). -------------------------------------------------------------------------------- /relation/abstract.md: -------------------------------------------------------------------------------- 1 | This vocubulary is intended as a companion vocabulary to the [Cube Schema vocabulary](..). -------------------------------------------------------------------------------- /trifid/config.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseConfig": "cwd:trifid/config.json", 3 | "datasetBaseUrl": "https://cube.link/" 4 | } 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | -------------------------------------------------------------------------------- /test/check-metadata.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | npx shacl-test --shapes="validation/$1.ttl" \ 4 | --valid-cases="test/$1/valid*.ttl" \ 5 | --invalid-cases="test/$1/invalid*.ttl" \ 6 | --command="npx b59 cube check-metadata --profile" \ 7 | --prefixes=schema,cube=https://cube.link/ \ 8 | ${*:2} 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [], 11 | "privatePackages": { 12 | "tag": true, 13 | "version": true 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/observations/withoutName.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:conforms true . 10 | -------------------------------------------------------------------------------- /test/observations/withoutType.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:conforms true . 10 | -------------------------------------------------------------------------------- /test/observations/undefinedAllowed.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:conforms true . 10 | -------------------------------------------------------------------------------- /test/observations/undefinedOrBounded.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:conforms true . 10 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/valid.minimal.ttl: -------------------------------------------------------------------------------- 1 | @prefix xsd: . 2 | @prefix dc: . 3 | @prefix rdf: . 4 | @prefix sh: . 5 | @prefix cube: . 6 | @base . 7 | 8 | a cube:Cube ; 9 | cube:observationSet ; 10 | cube:observationConstraint . 11 | cube:observation . 12 | sh:property 13 | [ sh:path rdf:type ] , 14 | [ sh:path cube:observedBy ] , 15 | [ sh:path dc:date ] . 16 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/invalid.withoutObservationSet.ttl: -------------------------------------------------------------------------------- 1 | @prefix xsd: . 2 | @prefix dc: . 3 | @prefix rdf: . 4 | @prefix sh: . 5 | @prefix cube: . 6 | @base . 7 | 8 | a cube:Cube ; 9 | #cube:observationSet ; 10 | cube:observationConstraint . 11 | cube:observation . 12 | sh:property 13 | [ sh:path rdf:type ] , 14 | [ sh:path cube:observedBy ] , 15 | [ sh:path dc:date ] . 16 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/invalid.withoutProperties.ttl: -------------------------------------------------------------------------------- 1 | @prefix xsd: . 2 | @prefix dc: . 3 | @prefix rdf: . 4 | @prefix sh: . 5 | @prefix cube: . 6 | @base . 7 | 8 | a cube:Cube ; 9 | cube:observationSet ; 10 | cube:observationConstraint . 11 | cube:observation . 12 | # sh:property 13 | #[ sh:path rdf:type ] , 14 | #[ sh:path cube:observedBy ] , 15 | #[ sh:path dc:date ] . 16 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/invalid.withoutObservations.ttl: -------------------------------------------------------------------------------- 1 | @prefix xsd: . 2 | @prefix dc: . 3 | @prefix rdf: . 4 | @prefix sh: . 5 | @prefix cube: . 6 | @base . 7 | 8 | a cube:Cube ; 9 | cube:observationSet ; 10 | cube:observationConstraint . 11 | # cube:observation . 12 | sh:property 13 | [ sh:path rdf:type ] , 14 | [ sh:path cube:observedBy ] , 15 | [ sh:path dc:date ] . 16 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.noTypeDataset.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:ClassConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode ; 15 | sh:value ; 16 | ] ; 17 | sh:conforms false . 18 | -------------------------------------------------------------------------------- /test/profile-visualize/warning-missing-sh-in.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix schema: . 4 | @prefix xsd: . 5 | @prefix cube: . 6 | 7 | _:report a sh:ValidationReport ; 8 | sh:result [ 9 | rdf:type sh:ValidationResult ; 10 | sh:resultSeverity sh:Info ; 11 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 12 | sh:sourceShape ; 13 | sh:focusNode _:b2 ; 14 | sh:value _:b2 ; 15 | sh:resultMessage "For performance reason, add list of occurring elements to nominal and ordinal Key Dimensions" ; 16 | ] ; 17 | sh:conforms false . 18 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.dimensionRelation-multipleDcType.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path ; 15 | sh:maxCount 1 ; 16 | ] ; 17 | sh:focusNode _:b5 ; 18 | sh:resultPath ; 19 | sh:resultMessage "More than 1 values" ; 20 | ] ; 21 | sh:conforms false . 22 | -------------------------------------------------------------------------------- /documentation/abstract.md: -------------------------------------------------------------------------------- 1 | A good amount of data in organizations is maintained in tables with multiple columns. Typically you can think of a multitude of Excel or CSV tables. This data often has a dimension which describes the time, sometimes other dimensions for classifying the data, and in most cases some actual observed values or counts. 2 | 3 | Such tables are holding the data in a structured form, but most of the time, the information to understand the columns and also the necessary metadata enabling the creation of use-full representations in charts and visualizations is missing. 4 | 5 | With the creation of Cubes you as data provider and domain specialist of the data are able to augment and annotate your data with everything necessary to understand the input data – directly in the to be published dataset. Fully annotated Cubes can also be used to visualize your data proper tooling. -------------------------------------------------------------------------------- /meta/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 12 | Cube Schema - Meta vocabulary 13 | 14 | 15 |

Cube Schema - Meta vocabulary

16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /relation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 12 | Cube Schema - Relation vocabulary 13 | 14 | 15 |

Cube Schema - Relation vocabulary

16 |
17 |
18 |
19 | 20 |
21 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-missingValue.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path _:b690 ; 15 | sh:minCount 1 ; 16 | ] ; 17 | sh:focusNode _:b4 ; 18 | sh:resultPath _:b690 ; 19 | sh:resultMessage "Less than 1 values" ; 20 | ] ; 21 | sh:conforms false . 22 | 23 | _:b690 sh:alternativePath ( 24 | schema:minValue 25 | schema:maxValue 26 | ) . 27 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.noWorkExample.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:HasValueConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path schema:workExample ; 15 | sh:hasValue ; 16 | ] ; 17 | sh:focusNode ; 18 | sh:resultPath schema:workExample ; 19 | sh:resultMessage "Missing expected value " ; 20 | ] ; 21 | sh:conforms false . 22 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-invalidRanges.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode _:b5 ; 15 | sh:value _:b5 ; 16 | sh:resultMessage "annotation context only allows constraints sh:hasValue, sh:in, sh:minInclusive, sh:maxInclusive, sh:minExclusive, sh:maxExclusive and they cannot be mixed" ; 17 | ] ; 18 | sh:conforms false . 19 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.expired.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path _:b628 ; 15 | sh:maxCount 0 ; 16 | sh:message "Cube cannot be expired" ; 17 | ] ; 18 | sh:focusNode ; 19 | sh:resultPath _:b628 ; 20 | sh:resultMessage "Cube cannot be expired" ; 21 | ] ; 22 | sh:conforms false . 23 | 24 | _:b628 sh:alternativePath ( 25 | schema:validThrough 26 | schema:expires 27 | ) . 28 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-mixedConstraints.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode _:b5 ; 15 | sh:value _:b5 ; 16 | sh:resultMessage "annotation context only allows constraints sh:hasValue, sh:in, sh:minInclusive, sh:maxInclusive, sh:minExclusive, sh:maxExclusive and they cannot be mixed" ; 17 | ] ; 18 | sh:conforms false . 19 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.draft.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:HasValueConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path schema:creativeWorkStatus ; 15 | sh:hasValue ; 16 | ] ; 17 | sh:focusNode ; 18 | sh:resultPath schema:creativeWorkStatus ; 19 | sh:resultMessage "Missing expected value " ; 20 | ] ; 21 | sh:conforms false . 22 | -------------------------------------------------------------------------------- /test/observations/undefinedNotAllowed.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:DatatypeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path ; 15 | sh:datatype xsd:decimal ; 16 | schema:name "some Quantity" ; 17 | ] ; 18 | sh:focusNode ; 19 | sh:resultPath ; 20 | sh:value ""^^cube:Undefined ; 21 | sh:resultMessage "Value does not have datatype " ; 22 | ] ; 23 | sh:conforms false . 24 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-no-status.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path schema:creativeWorkStatus ; 15 | sh:in ( 16 | 17 | 18 | ) ; 19 | sh:minCount 1 ; 20 | ] ; 21 | sh:focusNode ; 22 | sh:resultPath schema:creativeWorkStatus ; 23 | sh:resultMessage "Less than 1 values" ; 24 | ] ; 25 | sh:conforms false . 26 | -------------------------------------------------------------------------------- /test/profile-opendataswiss/invalid.missing-identifier.cube.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path ; 15 | sh:datatype xsd:string ; 16 | sh:maxCount 1 ; 17 | sh:minCount 1 ; 18 | sh:flags "i" ; 19 | sh:pattern "^[A-Z0-9-_]+@[A-Z0-9-_]+$" ; 20 | ] ; 21 | sh:focusNode ; 22 | sh:resultPath ; 23 | sh:resultMessage "Less than 1 values" ; 24 | ] ; 25 | sh:conforms false . 26 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/invalid.withoutObservationSet.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path cube:observationSet ; 15 | sh:minCount 1 ; 16 | sh:node ; 17 | sh:message "cube:Cube needs at least one cube:ObservationSet" ; 18 | ] ; 19 | sh:focusNode ; 20 | sh:resultPath cube:observationSet ; 21 | sh:resultMessage "cube:Cube needs at least one cube:ObservationSet" ; 22 | ] ; 23 | sh:conforms false . 24 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-tooManyValues.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path schema:minValue ; 15 | sh:maxCount 1 ; 16 | ] ; 17 | sh:focusNode _:b4 ; 18 | sh:resultPath schema:minValue ; 19 | sh:resultMessage "More than 1 values" ; 20 | ], [ 21 | rdf:type sh:ValidationResult ; 22 | sh:resultSeverity sh:Violation ; 23 | sh:sourceConstraintComponent sh:MaxCountConstraintComponent ; 24 | sh:sourceShape [ 25 | sh:path schema:maxValue ; 26 | sh:maxCount 1 ; 27 | ] ; 28 | sh:focusNode _:b6 ; 29 | sh:resultPath schema:maxValue ; 30 | sh:resultMessage "More than 1 values" ; 31 | ] ; 32 | sh:conforms false . 33 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/warning-qudt-unit.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix schema: . 4 | @prefix xsd: . 5 | @prefix cube: . 6 | 7 | _:report a sh:ValidationReport ; 8 | sh:result [ 9 | rdf:type sh:ValidationResult ; 10 | sh:resultSeverity sh:Warning ; 11 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 12 | sh:sourceShape [ 13 | sh:path sh:property ; 14 | sh:or ( 15 | [ 16 | sh:path ; 17 | sh:equals ; 18 | ] 19 | [ 20 | sh:path ; 21 | sh:maxCount 0 ; 22 | ] 23 | ) ; 24 | sh:message "The use of qudt:unit is deprecated, please use qudt:hasUnit instead" ; 25 | sh:severity sh:Warning ; 26 | ] ; 27 | sh:focusNode ; 28 | sh:resultPath sh:property ; 29 | sh:value _:b3 ; 30 | sh:resultMessage "The use of qudt:unit is deprecated, please use qudt:hasUnit instead" ; 31 | ] ; 32 | sh:conforms false . 33 | -------------------------------------------------------------------------------- /test/profile-opendataswiss/invalid.publisherNoClass.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path ; 15 | sh:maxCount 1 ; 16 | sh:minCount 1 ; 17 | sh:xone ( 18 | [ 19 | sh:nodeKind sh:IRI ; 20 | ] 21 | [ 22 | sh:nodeKind sh:BlankNode ; 23 | sh:class ; 24 | ] 25 | ) ; 26 | sh:message "Publisher must be a foaf:Organization DCAT-AP." ; 27 | ] ; 28 | sh:focusNode ; 29 | sh:resultPath ; 30 | sh:value _:b2 ; 31 | sh:resultMessage "Publisher must be a foaf:Organization DCAT-AP." ; 32 | ] ; 33 | sh:conforms false . 34 | -------------------------------------------------------------------------------- /test/observations/withoutName.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @prefix qudt: . 8 | @base . 9 | 10 | a cube:Cube ; 11 | cube:observationConstraint ; 12 | cube:observationSet . 13 | 14 | cube:observation , . 15 | 16 | a cube:Observation ; cube:observedBy ; 17 | 4.9 . 18 | 19 | a cube:Observation ; cube:observedBy ; 20 | 1.0 . 21 | 22 | a cube:Constraint ; 23 | sh:targetClass cube:Observation ; 24 | sh:closed true ; 25 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI] ; 26 | sh:property [ sh:path cube:observedBy ; sh:nodeKind sh:IRI ] ; 27 | sh:property [ 28 | sh:path ; 29 | sh:datatype xsd:decimal ; 30 | # schema:name "some Quantity" ; 31 | ] ; 32 | . -------------------------------------------------------------------------------- /test/observations/withoutType.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @prefix qudt: . 8 | @base . 9 | 10 | a cube:Cube ; 11 | cube:observationConstraint ; 12 | cube:observationSet . 13 | 14 | cube:observation , . 15 | 16 | a cube:Observation ; cube:observedBy ; 17 | 4.9 . 18 | 19 | a cube:Observation ; cube:observedBy ; 20 | 1.0 . 21 | 22 | a cube:Constraint ; 23 | sh:targetClass cube:Observation ; 24 | sh:closed true ; 25 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI] ; 26 | sh:property [ sh:path cube:observedBy ; sh:nodeKind sh:IRI ] ; 27 | sh:property [ 28 | sh:path ; 29 | #sh:datatype xsd:decimal ; 30 | schema:name "some Quantity" ; 31 | ] ; 32 | . -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.withoutName.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path sh:property ; 15 | sh:node ; 16 | sh:message "needs a schema:name" ; 17 | ] ; 18 | sh:focusNode ; 19 | sh:value _:b3 ; 20 | sh:detail [ 21 | rdf:type sh:ValidationResult ; 22 | sh:resultSeverity sh:Violation ; 23 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 24 | sh:sourceShape ; 25 | sh:focusNode _:b3 ; 26 | sh:value _:b3 ; 27 | ] ; 28 | sh:resultPath sh:property ; 29 | sh:resultMessage "needs a schema:name" ; 30 | ] ; 31 | sh:conforms false . 32 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.draft.ttl: -------------------------------------------------------------------------------- 1 | PREFIX xsd: 2 | PREFIX dcterms: 3 | PREFIX schema: 4 | PREFIX dcat: 5 | PREFIX cube: 6 | PREFIX ex: 7 | 8 | ex:Cube 9 | a cube:Cube, dcat:Dataset ; 10 | cube:observationSet ; 11 | schema:name "Example cube" ; 12 | schema:publisher ; 13 | schema:creator ; 14 | schema:contributor ; 15 | dcterms:identifier "cube-1234" ; 16 | schema:workExample ; 17 | schema:creativeWorkStatus ; 18 | dcterms:creator ex:John-Doe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "John Doe" ; 25 | schema:email "john@doe.tech" ; 26 | ] ; 27 | . 28 | 29 | cube:observation . 30 | 31 | a cube:Observation ; 32 | cube:observedBy ; 33 | 4.9 . 34 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/valid.ttl: -------------------------------------------------------------------------------- 1 | PREFIX xsd: 2 | PREFIX dcterms: 3 | PREFIX schema: 4 | PREFIX dcat: 5 | PREFIX cube: 6 | PREFIX ex: 7 | 8 | ex:Cube 9 | a cube:Cube, dcat:Dataset ; 10 | cube:observationSet ; 11 | schema:name "Example cube" ; 12 | schema:publisher ; 13 | schema:creator ; 14 | schema:contributor ; 15 | dcterms:identifier "cube-1234" ; 16 | schema:workExample ; 17 | schema:creativeWorkStatus ; 18 | dcterms:creator ex:John-Doe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "John Doe" ; 25 | schema:email "john@doe.tech" ; 26 | ] ; 27 | . 28 | 29 | cube:observation . 30 | 31 | a cube:Observation ; 32 | cube:observedBy ; 33 | 4.9 . 34 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.noTypeDataset.ttl: -------------------------------------------------------------------------------- 1 | PREFIX xsd: 2 | PREFIX dcterms: 3 | PREFIX schema: 4 | PREFIX dcat: 5 | PREFIX cube: 6 | PREFIX ex: 7 | 8 | ex:Cube 9 | a cube:Cube ; # dcat:Dataset ; 10 | cube:observationSet ; 11 | schema:name "Example cube" ; 12 | schema:publisher ; 13 | schema:creator ; 14 | schema:contributor ; 15 | dcterms:identifier "cube-1234" ; 16 | schema:workExample ; 17 | schema:creativeWorkStatus ; 18 | dcterms:creator ex:John-Doe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "John Doe" ; 25 | schema:email "john@doe.tech" ; 26 | ] ; 27 | . 28 | 29 | cube:observation . 30 | 31 | a cube:Observation ; 32 | cube:observedBy ; 33 | 4.9 . 34 | -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.noWorkExample.ttl: -------------------------------------------------------------------------------- 1 | PREFIX xsd: 2 | PREFIX dcterms: 3 | PREFIX schema: 4 | PREFIX dcat: 5 | PREFIX cube: 6 | PREFIX ex: 7 | 8 | ex:Cube 9 | a cube:Cube, dcat:Dataset ; 10 | cube:observationSet ; 11 | schema:name "Example cube" ; 12 | schema:publisher ; 13 | schema:creator ; 14 | schema:contributor ; 15 | dcterms:identifier "cube-1234" ; 16 | # schema:workExample ; 17 | schema:creativeWorkStatus ; 18 | dcterms:creator ex:John-Doe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "John Doe" ; 25 | schema:email "john@doe.tech" ; 26 | ] ; 27 | . 28 | 29 | cube:observation . 30 | 31 | a cube:Observation ; 32 | cube:observedBy ; 33 | 4.9 . 34 | -------------------------------------------------------------------------------- /test/observations/undefinedNotAllowed.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet . 12 | 13 | cube:observation , , . 14 | 15 | a cube:Observation ; cube:observedBy ; 16 | 4.9 . 17 | 18 | a cube:Observation ; cube:observedBy ; 19 | 1.0 . 20 | 21 | a cube:Observation ; cube:observedBy ; 22 | ""^^cube:Undefined . 23 | 24 | a cube:Constraint ; 25 | sh:targetClass cube:Observation ; 26 | sh:closed true ; 27 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI] ; 28 | sh:property [ sh:path cube:observedBy ; ; sh:nodeKind sh:IRI ] ; 29 | sh:property [ 30 | sh:datatype xsd:decimal ; 31 | sh:path ; 32 | schema:name "some Quantity" 33 | ] ; 34 | . -------------------------------------------------------------------------------- /test/profile-opendataswiss-lindas/invalid.expired.ttl: -------------------------------------------------------------------------------- 1 | PREFIX xsd: 2 | PREFIX dcterms: 3 | PREFIX schema: 4 | PREFIX dcat: 5 | PREFIX cube: 6 | PREFIX ex: 7 | 8 | ex:Cube 9 | a cube:Cube, dcat:Dataset ; 10 | cube:observationSet ; 11 | schema:name "Example cube" ; 12 | schema:publisher ; 13 | schema:creator ; 14 | schema:contributor ; 15 | dcterms:identifier "cube-1234" ; 16 | schema:workExample ; 17 | schema:creativeWorkStatus ; 18 | dcterms:creator ex:John-Doe ; 19 | schema:expires "2020-12-31T23:59:59Z"^^xsd:dateTime ; 20 | schema:dateCreated "2020-10-10"^^xsd:date ; 21 | schema:dateModified "2020-10-10"^^xsd:date ; 22 | schema:datePublished "2020-11-11"^^xsd:date ; 23 | schema:contactPoint 24 | [ 25 | schema:name "John Doe" ; 26 | schema:email "john@doe.tech" ; 27 | ] ; 28 | . 29 | 30 | cube:observation . 31 | 32 | a cube:Observation ; 33 | cube:observedBy ; 34 | 4.9 . 35 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.withoutType.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path sh:property ; 15 | sh:node ; 16 | sh:message "needs a sh:datatype, sh:nodeKind or sh:datatype within sh:or (...)" ; 17 | ] ; 18 | sh:focusNode ; 19 | sh:value _:b3 ; 20 | sh:detail [ 21 | rdf:type sh:ValidationResult ; 22 | sh:resultSeverity sh:Violation ; 23 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 24 | sh:sourceShape ; 25 | sh:focusNode _:b3 ; 26 | sh:value _:b3 ; 27 | ] ; 28 | sh:resultPath sh:property ; 29 | sh:resultMessage "needs a sh:datatype, sh:nodeKind or sh:datatype within sh:or (...)" ; 30 | ] ; 31 | sh:conforms false . 32 | -------------------------------------------------------------------------------- /validation/profile-opendataswiss-lindas.ttl: -------------------------------------------------------------------------------- 1 | PREFIX dcterms: 2 | PREFIX dcat: 3 | PREFIX schema: 4 | PREFIX sh: 5 | prefix code: 6 | prefix cube: 7 | prefix : 8 | 9 | [ 10 | code:imports <./standalone-cube-constraint> ; 11 | code:extension "ttl" ; 12 | ] . 13 | 14 | :CubeShape 15 | a sh:NodeShape ; 16 | sh:targetClass cube:Cube ; 17 | sh:class dcat:Dataset ; 18 | sh:property 19 | [ 20 | sh:path dcterms:identifier ; 21 | sh:minCount 1 ; 22 | sh:maxCount 1 ; 23 | ], 24 | [ 25 | sh:path dcterms:creator ; 26 | sh:minCount 1 ; 27 | ], 28 | [ 29 | sh:path schema:workExample ; 30 | sh:hasValue ; 31 | ], 32 | [ 33 | sh:path schema:creativeWorkStatus ; 34 | sh:hasValue ; 35 | ], 36 | [ 37 | sh:path [ sh:alternativePath ( schema:validThrough schema:expires ) ] ; 38 | sh:maxCount 0 ; 39 | sh:message "Cube cannot be expired" ; 40 | ] ; 41 | . 42 | -------------------------------------------------------------------------------- /test/observations/undefinedAllowed.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet . 12 | 13 | cube:observation , , . 14 | 15 | a cube:Observation ; cube:observedBy ; 16 | 4.9 . 17 | 18 | a cube:Observation ; cube:observedBy ; 19 | 1.0 . 20 | 21 | a cube:Observation ; cube:observedBy ; 22 | ""^^cube:Undefined . 23 | 24 | a cube:Constraint ; 25 | sh:targetClass cube:Observation ; 26 | sh:closed true ; 27 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI] ; 28 | sh:property [ sh:path cube:observedBy ; ; sh:nodeKind sh:IRI ] ; 29 | sh:property [ 30 | sh:or ([ sh:datatype xsd:decimal ] [ sh:datatype cube:Undefined ]) ; 31 | sh:path ; 32 | schema:name "some Quantity" 33 | ] ; 34 | . -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM docker.io/library/node:22 AS respec 2 | 3 | # Install some required dependencies to run Puppeteer (for ReSpec) 4 | RUN apt-get update && apt-get install -y \ 5 | chromium \ 6 | fonts-liberation \ 7 | gconf-service \ 8 | libasound2 \ 9 | libatk1.0-0 \ 10 | libcairo2 \ 11 | libcups2 \ 12 | libfontconfig1 \ 13 | libgbm-dev \ 14 | libgdk-pixbuf2.0-0 \ 15 | libgtk-3-0 \ 16 | libicu-dev \ 17 | libjpeg-dev \ 18 | libnspr4 \ 19 | libnss3 \ 20 | libpango-1.0-0 \ 21 | libpangocairo-1.0-0 \ 22 | libpng-dev \ 23 | libx11-6 \ 24 | libx11-xcb1 \ 25 | libxcb1 \ 26 | libxcomposite1 \ 27 | libxcursor1 \ 28 | libxdamage1 \ 29 | libxext6 \ 30 | libxfixes3 \ 31 | libxi6 \ 32 | libxrandr2 \ 33 | libxrender1 \ 34 | libxss1 \ 35 | libxtst6 \ 36 | xdg-utils 37 | 38 | WORKDIR /app 39 | COPY package.json package-lock.json ./ 40 | RUN npm install 41 | COPY . . 42 | # Start a server locally, and generate the ReSpec HTML file 43 | RUN npm run build 44 | 45 | # Final Docker image 46 | FROM docker.io/library/node:22-alpine 47 | 48 | EXPOSE 8080 49 | 50 | WORKDIR /app 51 | 52 | RUN apk add --no-cache tini 53 | 54 | # Install Trifid 55 | ENV NODE_ENV=production 56 | COPY package.json package-lock.json ./ 57 | RUN npm install 58 | 59 | COPY --from=respec /app/dist ./dist 60 | COPY img . 61 | COPY . . 62 | 63 | CMD [ "tini", "--", "npm", "run", "trifid:local" ] 64 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.withoutName.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @prefix qudt: . 8 | @base . 9 | 10 | a cube:Cube ; 11 | cube:observationConstraint ; 12 | cube:observationSet . 13 | 14 | cube:observation , . 15 | 16 | a cube:Observation ; cube:observedBy ; 17 | 4.9 . 18 | 19 | a cube:Observation ; cube:observedBy ; 20 | 1.0 . 21 | 22 | a cube:Constraint ; 23 | sh:targetClass cube:Observation ; 24 | sh:closed true ; 25 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 26 | sh:property [ sh:path cube:observedBy ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 27 | sh:property [ 28 | sh:path ; 29 | sh:datatype xsd:decimal ; 30 | # schema:name "some Quantity" ; 31 | sh:minCount 1 ; 32 | sh:maxCount 1 ; 33 | ] ; 34 | . 35 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.withoutType.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @prefix qudt: . 8 | @base . 9 | 10 | a cube:Cube ; 11 | cube:observationConstraint ; 12 | cube:observationSet . 13 | 14 | cube:observation , . 15 | 16 | a cube:Observation ; cube:observedBy ; 17 | 4.9 . 18 | 19 | a cube:Observation ; cube:observedBy ; 20 | 1.0 . 21 | 22 | a cube:Constraint ; 23 | sh:targetClass cube:Observation ; 24 | sh:closed true ; 25 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 26 | sh:property [ sh:path cube:observedBy ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 27 | sh:property [ 28 | sh:path ; 29 | #sh:datatype xsd:decimal ; 30 | schema:name "some Quantity" ; 31 | sh:minCount 1 ; 32 | sh:maxCount 1 ; 33 | ] ; 34 | . 35 | -------------------------------------------------------------------------------- /test/standalone-cube-constraint/invalid.blankContactPoint.missingEmail.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path schema:contactPoint ; 15 | sh:minCount 1 ; 16 | sh:xone ( 17 | [ 18 | sh:nodeKind sh:IRI ; 19 | ] 20 | [ 21 | sh:nodeKind sh:BlankNode ; 22 | sh:property [ 23 | sh:path schema:email ; 24 | sh:minCount 1 ; 25 | sh:message "Contact point needs an email" ; 26 | sh:datatype xsd:string ; 27 | ], [ 28 | sh:path schema:name ; 29 | sh:minCount 1 ; 30 | sh:message "Contact point needs a name" ; 31 | sh:datatype xsd:string ; 32 | ] ; 33 | ] 34 | ) ; 35 | sh:message "cube:Cube needs a schema:contactpoint" ; 36 | ] ; 37 | sh:focusNode ; 38 | sh:resultPath schema:contactPoint ; 39 | sh:value _:b1 ; 40 | sh:resultMessage "cube:Cube needs a schema:contactpoint" ; 41 | ] ; 42 | sh:conforms false . 43 | -------------------------------------------------------------------------------- /test/standalone-cube-constraint/invalid.blankContactPoint.missingName.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path schema:contactPoint ; 15 | sh:minCount 1 ; 16 | sh:xone ( 17 | [ 18 | sh:nodeKind sh:IRI ; 19 | ] 20 | [ 21 | sh:nodeKind sh:BlankNode ; 22 | sh:property [ 23 | sh:path schema:email ; 24 | sh:minCount 1 ; 25 | sh:message "Contact point needs an email" ; 26 | sh:datatype xsd:string ; 27 | ], [ 28 | sh:path schema:name ; 29 | sh:minCount 1 ; 30 | sh:message "Contact point needs a name" ; 31 | sh:datatype xsd:string ; 32 | ] ; 33 | ] 34 | ) ; 35 | sh:message "cube:Cube needs a schema:contactpoint" ; 36 | ] ; 37 | sh:focusNode ; 38 | sh:resultPath schema:contactPoint ; 39 | sh:value _:b1 ; 40 | sh:resultMessage "cube:Cube needs a schema:contactpoint" ; 41 | ] ; 42 | sh:conforms false . 43 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | 2 | var respecConfig = { 3 | specStatus: "ZZ-DRAFT", 4 | shortName: 'cube-link', 5 | maxTocLevel: 4, 6 | latestVersion: "https://cube.link", 7 | github: { 8 | repoURL: "https://github.com/zazuko/cube-link", 9 | branch: "documentation", // alternative branch 10 | }, 11 | otherLinks: [ 12 | { 13 | key: "Related Vocabularies", 14 | data: [ 15 | { 16 | value: "Cube Schema - Meta vocabulary", 17 | href: "./meta/", 18 | }, 19 | { 20 | value: "Cube Schema - Relation vocabulary", 21 | href: "./relation/", 22 | }, 23 | ], 24 | }, 25 | ], 26 | editors: [ 27 | { 28 | name: "Bart van Leeuwen", 29 | company: "Zazuko", 30 | companyURL: "https://www.zazuko.com", 31 | }], 32 | authors: [{ 33 | name: "Thomas Bergwinkl", 34 | company: "Zazuko", 35 | companyURL: "https://www.zazuko.com", 36 | }, 37 | { 38 | name: "Adrian Gschwend", 39 | company: "Zazuko", 40 | companyURL: "https://www.zazuko.com", 41 | }, 42 | { 43 | name: "Bart van Leeuwen", 44 | company: "Zazuko", 45 | companyURL: "https://www.zazuko.com", 46 | }, 47 | { 48 | name: "Michael Luggen", 49 | company: "Zazuko", 50 | companyURL: "https://www.zazuko.com", 51 | }] 52 | }; 53 | 54 | module.exports = respecConfig 55 | -------------------------------------------------------------------------------- /test/check-observations.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPT_PATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" 4 | SHACL_TEST_PATH="$(npm root)/@zazuko/shacl-test" 5 | FAILED=0 6 | 7 | filter='' 8 | 9 | # get arguments --profile 10 | while [ $# -gt 0 ]; do 11 | case "$1" in 12 | --approve) 13 | approvalsFlags='-f' 14 | ;; 15 | --filter=*) 16 | filter="${1#*=}" 17 | ;; 18 | *) 19 | printf "***************************\n" 20 | printf "* Error: Invalid argument.*\n" 21 | printf "***************************\n" 22 | exit 1 23 | esac 24 | shift 25 | done 26 | 27 | # iterate over valid cases, run validation and monitor exit code 28 | for file in "$SCRIPT_PATH"/observations/*.ttl; do 29 | # check if filter is set and skip if not matching 30 | if [ -n "$filter" ] && ! echo "$file" | grep -q "$filter"; then 31 | continue 32 | fi 33 | 34 | name=$(basename "$file") 35 | report=$(npx barnard59 cube check-observations --constraint "$file" < "$file" 2> "$file.log" | "$SHACL_TEST_PATH"/pretty-print.js --prefixes schema cube=https://cube.link/) 36 | 37 | if ! echo "$report" | npx approvals "$name" --outdir "$SCRIPT_PATH"/observations "$approvalsFlags" > /dev/null 2>&1 ; then 38 | "$SHACL_TEST_PATH"/report-failure.sh "$file" "$(cat "$file")" "$(cat "$file")" "check results" 39 | FAILED=1 40 | else 41 | echo "✅ PASS - $name" 42 | fi 43 | done 44 | 45 | exit $FAILED 46 | -------------------------------------------------------------------------------- /meta/config.js: -------------------------------------------------------------------------------- 1 | 2 | var respecConfig = { 3 | specStatus: "ZZ-DRAFT", 4 | shortName: 'cube-link/meta', 5 | maxTocLevel: 4, 6 | latestVersion: "https://cube.link/meta/", 7 | github: { 8 | repoURL: "https://github.com/zazuko/cube-link", 9 | branch: "documentation", // alternative branch 10 | }, 11 | otherLinks: [ 12 | { 13 | key: "Related Vocabularies", 14 | data: [ 15 | { 16 | value: "Cube Schema", 17 | href: "../", 18 | }, 19 | { 20 | value: "Cube Schema - Relation vocabulary", 21 | href: "../relation/", 22 | }, 23 | ], 24 | }, 25 | ], 26 | editors: [ 27 | { 28 | name: "Bart van Leeuwen", 29 | company: "Zazuko", 30 | companyURL: "https://www.zazuko.com", 31 | }], 32 | authors: [{ 33 | name: "Thomas Bergwinkl", 34 | company: "Zazuko", 35 | companyURL: "https://www.zazuko.com", 36 | }, 37 | { 38 | name: "Adrian Gschwend", 39 | company: "Zazuko", 40 | companyURL: "https://www.zazuko.com", 41 | }, 42 | { 43 | name: "Bart van Leeuwen", 44 | company: "Zazuko", 45 | companyURL: "https://www.zazuko.com", 46 | }, 47 | { 48 | name: "Michael Luggen", 49 | company: "Zazuko", 50 | companyURL: "https://www.zazuko.com", 51 | }] 52 | }; 53 | 54 | module.exports = respecConfig 55 | -------------------------------------------------------------------------------- /relation/config.js: -------------------------------------------------------------------------------- 1 | 2 | var respecConfig = { 3 | specStatus: "ZZ-DRAFT", 4 | shortName: 'cube-link/relation', 5 | maxTocLevel: 4, 6 | latestVersion: "https://cube.link/relation/", 7 | github: { 8 | repoURL: "https://github.com/zazuko/cube-link", 9 | branch: "documentation", // alternative branch 10 | }, 11 | otherLinks: [ 12 | { 13 | key: "Related Vocabularies", 14 | data: [ 15 | { 16 | value: "Cube Schema", 17 | href: "../", 18 | }, 19 | { 20 | value: "Cube Schema - Meta vocabulary", 21 | href: "../meta/", 22 | }, 23 | ], 24 | }, 25 | ], 26 | editors: [ 27 | { 28 | name: "Bart van Leeuwen", 29 | company: "Zazuko", 30 | companyURL: "https://www.zazuko.com", 31 | }], 32 | authors: [{ 33 | name: "Thomas Bergwinkl", 34 | company: "Zazuko", 35 | companyURL: "https://www.zazuko.com", 36 | }, 37 | { 38 | name: "Adrian Gschwend", 39 | company: "Zazuko", 40 | companyURL: "https://www.zazuko.com", 41 | }, 42 | { 43 | name: "Bart van Leeuwen", 44 | company: "Zazuko", 45 | companyURL: "https://www.zazuko.com", 46 | }, 47 | { 48 | name: "Michael Luggen", 49 | company: "Zazuko", 50 | companyURL: "https://www.zazuko.com", 51 | }] 52 | }; 53 | 54 | module.exports = respecConfig 55 | -------------------------------------------------------------------------------- /test/observations/undefinedOrBounded.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @prefix qudt: . 8 | @base . 9 | 10 | a cube:Cube ; 11 | cube:observationConstraint ; 12 | cube:observationSet . 13 | 14 | cube:observation , , . 15 | 16 | a cube:Observation ; cube:observedBy ; 17 | 4.9 . 18 | 19 | a cube:Observation ; cube:observedBy ; 20 | 1.0 . 21 | 22 | a cube:Observation ; cube:observedBy ; 23 | ""^^cube:Undefined . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI] ; 29 | sh:property [ sh:path cube:observedBy ; sh:nodeKind sh:IRI ] ; 30 | sh:property [ 31 | sh:path ; 32 | schema:name "some Quantity" ; 33 | sh:or ( 34 | [ sh:datatype cube:Undefined ] 35 | [ sh:datatype xsd:decimal ; sh:minInclusive -5 ; sh:maxInclusive 5 ] ) ; 36 | ] ; 37 | . -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/valid.undefinedNotAllowed.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet . 12 | 13 | cube:observation , , . 14 | 15 | a cube:Observation ; cube:observedBy ; 16 | 4.9 . 17 | 18 | a cube:Observation ; cube:observedBy ; 19 | 1.0 . 20 | 21 | a cube:Observation ; cube:observedBy ; 22 | ""^^cube:Undefined . 23 | 24 | a cube:Constraint ; 25 | sh:targetClass cube:Observation ; 26 | sh:closed true ; 27 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 28 | sh:property [ sh:path cube:observedBy ; ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 29 | sh:property [ 30 | sh:datatype xsd:decimal ; 31 | sh:path ; 32 | schema:name "some Quantity" ; 33 | sh:minCount 1 ; 34 | sh:maxCount 1 ; 35 | ] ; 36 | . 37 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | concurrency: ${{ github.workflow }}-${{ github.ref }} 9 | 10 | jobs: 11 | release: 12 | name: Release 13 | runs-on: ubuntu-latest 14 | steps: 15 | # This allow GitHub Actions to trigger the jobs for tags if needed 16 | - name: Generate token 17 | id: generate_token 18 | uses: tibdex/github-app-token@v2 19 | with: 20 | app_id: ${{ secrets.GH_APP_ID }} 21 | private_key: ${{ secrets.GH_PRIVATE_KEY }} 22 | 23 | - name: Checkout Repo 24 | uses: actions/checkout@v6 25 | with: 26 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 27 | fetch-depth: 0 28 | token: ${{ steps.generate_token.outputs.token }} 29 | 30 | - name: Setup Node.js 31 | uses: actions/setup-node@v6 32 | with: 33 | node-version: "lts/*" 34 | 35 | - name: Install Dependencies 36 | run: npm ci 37 | 38 | - name: Create Release Pull Request or Create a GitHub Release + tag 39 | uses: changesets/action@v1 40 | with: 41 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 42 | publish: yarn release 43 | env: 44 | GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }} 45 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 46 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/valid.undefinedAllowed.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet . 12 | 13 | cube:observation , , . 14 | 15 | a cube:Observation ; cube:observedBy ; 16 | 4.9 . 17 | 18 | a cube:Observation ; cube:observedBy ; 19 | 1.0 . 20 | 21 | a cube:Observation ; cube:observedBy ; 22 | ""^^cube:Undefined . 23 | 24 | a cube:Constraint ; 25 | sh:targetClass cube:Observation ; 26 | sh:closed true ; 27 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 28 | sh:property [ sh:path cube:observedBy ; ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 29 | sh:property [ 30 | sh:or ([ sh:datatype xsd:decimal ] [ sh:datatype cube:Undefined ]) ; 31 | sh:path ; 32 | schema:name "some Quantity" ; 33 | sh:minCount 1 ; 34 | sh:maxCount 1 ; 35 | ] ; 36 | . 37 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-keyDimensions.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NotConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode _:b5 ; 15 | sh:value _:b5 ; 16 | sh:resultMessage "annotation context must have exactly one sh:path which is cube's key dimension" ; 17 | ], [ 18 | rdf:type sh:ValidationResult ; 19 | sh:resultSeverity sh:Violation ; 20 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 21 | sh:sourceShape [ 22 | sh:path _:b707 ; 23 | sh:xone ( 24 | [ 25 | sh:class cube:KeyDimension ; 26 | ] 27 | [ 28 | sh:property [ 29 | sh:path [ 30 | sh:inversePath ; 31 | ] ; 32 | sh:minCount 1 ; 33 | ] ; 34 | ] 35 | ) ; 36 | ] ; 37 | sh:focusNode _:b7 ; 38 | sh:value _:b9 ; 39 | sh:resultPath _:b707 ; 40 | ] ; 41 | sh:conforms false . 42 | 43 | _:b707 rdf:first sh:path ; 44 | rdf:rest ( 45 | [ 46 | sh:inversePath sh:path ; 47 | ] 48 | ) . 49 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-data-kind-unexpected.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Warning ; 12 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode _:b3 ; 15 | sh:value _:b3 ; 16 | sh:resultMessage "Data kind should be one of the following: GeneralDateTimeDescription, GeoShape, GeoCoordinates" ; 17 | ], [ 18 | rdf:type sh:ValidationResult ; 19 | sh:resultSeverity sh:Violation ; 20 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 21 | sh:sourceShape [ 22 | sh:path rdf:type ; 23 | sh:minCount 1 ; 24 | ] ; 25 | sh:focusNode _:b5 ; 26 | sh:resultMessage "Less than 1 values" ; 27 | sh:resultPath rdf:type ; 28 | ], [ 29 | rdf:type sh:ValidationResult ; 30 | sh:resultSeverity sh:Warning ; 31 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 32 | sh:sourceShape ; 33 | sh:focusNode _:b5 ; 34 | sh:value _:b5 ; 35 | sh:resultMessage "Data kind should be one of the following: GeneralDateTimeDescription, GeoShape, GeoCoordinates" ; 36 | ] ; 37 | sh:conforms false . 38 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/invalid.withoutProperties.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path cube:observationConstraint ; 15 | sh:node ; 16 | sh:message "cube:Cube must point to a valid cube:Constraint" ; 17 | ] ; 18 | sh:focusNode ; 19 | sh:resultPath cube:observationConstraint ; 20 | sh:resultMessage "cube:Cube must point to a valid cube:Constraint" ; 21 | sh:detail [ 22 | rdf:type sh:ValidationResult ; 23 | sh:resultSeverity sh:Violation ; 24 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 25 | sh:sourceShape [ 26 | sh:path sh:property ; 27 | sh:message "cube:Constraint needs at least a certain amount of sh:properties" ; 28 | sh:minCount 3 ; 29 | ] ; 30 | sh:focusNode ; 31 | sh:resultPath sh:property ; 32 | sh:resultMessage "cube:Constraint needs at least a certain amount of sh:properties" ; 33 | ] ; 34 | sh:value ; 35 | ] ; 36 | sh:conforms false . 37 | -------------------------------------------------------------------------------- /test/basic-cube-constraint/invalid.withoutObservations.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path cube:observationSet ; 15 | sh:minCount 1 ; 16 | sh:node ; 17 | sh:message "cube:Cube needs at least one cube:ObservationSet" ; 18 | ] ; 19 | sh:focusNode ; 20 | sh:resultPath cube:observationSet ; 21 | sh:resultMessage "cube:Cube needs at least one cube:ObservationSet" ; 22 | sh:detail [ 23 | rdf:type sh:ValidationResult ; 24 | sh:resultSeverity sh:Violation ; 25 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 26 | sh:sourceShape [ 27 | sh:path cube:observation ; 28 | sh:minCount 1 ; 29 | sh:message "cube:ObservationSet needs at least one cube:observation" ; 30 | ] ; 31 | sh:focusNode ; 32 | sh:resultPath cube:observation ; 33 | sh:resultMessage "cube:ObservationSet needs at least one cube:observation" ; 34 | ] ; 35 | sh:value ; 36 | ] ; 37 | sh:conforms false . 38 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/valid.undefinedOrBounded.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @prefix qudt: . 8 | @base . 9 | 10 | a cube:Cube ; 11 | cube:observationConstraint ; 12 | cube:observationSet . 13 | 14 | cube:observation , , . 15 | 16 | a cube:Observation ; cube:observedBy ; 17 | 4.9 . 18 | 19 | a cube:Observation ; cube:observedBy ; 20 | 1.0 . 21 | 22 | a cube:Observation ; cube:observedBy ; 23 | ""^^cube:Undefined . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property [ sh:path rdf:type ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 29 | sh:property [ sh:path cube:observedBy ; sh:nodeKind sh:IRI ; sh:minCount 1; sh:maxCount 1 ] ; 30 | sh:property [ 31 | sh:path ; 32 | schema:name "some Quantity" ; 33 | sh:minCount 1 ; 34 | sh:maxCount 1 ; 35 | sh:or ( 36 | [ sh:datatype cube:Undefined ] 37 | [ sh:datatype xsd:decimal ; sh:minInclusive -5 ; sh:maxInclusive 5 ] ) ; 38 | ] ; 39 | . 40 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.dimensionRelation-relatesToNotMatching.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path sh:property ; 15 | sh:node ; 16 | ] ; 17 | sh:focusNode ; 18 | sh:resultPath sh:property ; 19 | sh:resultMessage "Value does not have shape " ; 20 | sh:detail [ 21 | rdf:type sh:ValidationResult ; 22 | sh:resultSeverity sh:Violation ; 23 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 24 | sh:sourceShape [ 25 | sh:path _:b675 ; 26 | sh:class cube:Constraint ; 27 | sh:minCount 1 ; 28 | sh:message "value of meta:relatesTo must be a cube dimension" ; 29 | ] ; 30 | sh:focusNode _:b5 ; 31 | sh:resultPath _:b675 ; 32 | sh:resultMessage "value of meta:relatesTo must be a cube dimension" ; 33 | ] ; 34 | sh:value _:b4 ; 35 | ] ; 36 | sh:conforms false . 37 | 38 | _:b675 rdf:first ; 39 | rdf:rest ( 40 | [ 41 | sh:inversePath sh:path ; 42 | ] 43 | [ 44 | sh:inversePath sh:property ; 45 | ] 46 | ) . 47 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.malformedList.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet . 12 | 13 | cube:observation . 14 | 15 | a cube:Observation ; 16 | cube:observedBy ; 17 | "one" . 18 | 19 | 20 | a cube:Constraint ; 21 | sh:targetClass cube:Observation ; 22 | sh:closed true ; 23 | sh:property 24 | [ 25 | sh:path rdf:type ; 26 | sh:nodeKind sh:IRI ; 27 | sh:minCount 1 ; 28 | sh:maxCount 1 ; 29 | sh:in [ a rdf:List ; rdf:first cube:Observation ; rdf:rest rdf:nil ] # well-formed list 30 | ] ; 31 | sh:property 32 | [ 33 | sh:path cube:observedBy ; ; 34 | sh:nodeKind sh:IRI ; 35 | sh:minCount 1 ; 36 | sh:maxCount 1 ; 37 | sh:in [ rdf:first ; rdf:rest rdf:wrong ] # malformed list 38 | ] ; 39 | sh:property 40 | [ 41 | sh:datatype xsd:string ; 42 | sh:path ; 43 | schema:name "dimension 1" ; 44 | sh:minCount 1 ; 45 | sh:maxCount 1 ; 46 | sh:in [ rdf:first "one" ] # malformed list 47 | ] ; 48 | . 49 | -------------------------------------------------------------------------------- /validation/shared/data-kind.ttl: -------------------------------------------------------------------------------- 1 | PREFIX meta: 2 | PREFIX rdf: 3 | PREFIX time: 4 | PREFIX schema: 5 | PREFIX sh: 6 | prefix : 7 | 8 | :DataKind 9 | a sh:NodeShape ; 10 | sh:targetObjectsOf meta:dataKind ; 11 | sh:xone ( :GeneralDateTimeDescription :GeoShape :GeoCoordinates ) ; 12 | sh:severity sh:Warning ; 13 | sh:message "Data kind should be one of the following: GeneralDateTimeDescription, GeoShape, GeoCoordinates" ; 14 | sh:property 15 | [ 16 | sh:path rdf:type ; 17 | sh:minCount 1 ; 18 | ] 19 | . 20 | 21 | :GeoShape 22 | a sh:NodeShape ; 23 | sh:targetClass schema:GeoShape ; 24 | sh:class schema:GeoShape ; 25 | sh:closed true ; 26 | sh:ignoredProperties ( rdf:type ) ; 27 | . 28 | 29 | :GeoCoordinates 30 | a sh:NodeShape ; 31 | sh:targetClass schema:GeoCoordinates ; 32 | sh:class schema:GeoCoordinates ; 33 | sh:closed true ; 34 | sh:ignoredProperties ( rdf:type ) ; 35 | . 36 | 37 | :GeneralDateTimeDescription 38 | a sh:NodeShape ; 39 | sh:targetClass time:GeneralDateTimeDescription ; 40 | sh:class time:GeneralDateTimeDescription ; 41 | sh:closed true ; 42 | sh:ignoredProperties ( rdf:type ) ; 43 | sh:property 44 | [ 45 | sh:path time:unitType ; 46 | sh:maxCount 1 ; 47 | sh:in 48 | ( 49 | time:unitYear time:unitMonth time:unitDay time:unitHour time:unitMinute time:unitSecond 50 | time:unitWeek 51 | ) ; 52 | ] ; 53 | . 54 | -------------------------------------------------------------------------------- /best-practice.md: -------------------------------------------------------------------------------- 1 | # RDF Cube Schema 2 | 3 | ## Best Practice 4 | 5 | ### Null/Empty values 6 | 7 | In _RDF Cube Schema_, all dimensions are mandatory for a cube. If a value could not be measured, it should be expressed as such. 8 | 9 | There is no generic "built-in" way to solve this in RDF. For some numeric datatypes, XML and [thus RDF](https://www.w3.org/TR/rdf11-concepts/#xsd-datatypes) defines ["not a number"](https://docstore.mik.ua/orelly/xml/schema/ch04_04.htm) (`NaN`) as a value. According to the specs, this is only valid for `xsd:float` and `xsd:double` and not for `xsd:decimal` and `xsd:integer`. 10 | 11 | To provide a generic solution that works for all number and IRIs, _RDF Cube Schema_ provides `cube:Undefined`. The following example shows how to use it in `cube:Observation` and in the attached shape: 12 | 13 | ```turtle 14 | # NamedNode Dimensions 15 | 16 | a cube:Observation; 17 | ex:namedNodeDimension cube:Undefined; 18 | 19 | a cube:Observation; 20 | ex:namedNodeDimension ex:realValue1; 21 | 22 | a cube:Observation; 23 | ex:namedNodeDimension ex:realValue2; 24 | 25 | ## Snippet for for the according shape: 26 | 27 | [ 28 | sh:path ex:namedNodeDimension; 29 | sh:nodeKind sh:IRI; 30 | sh:in(cube:Undefined, ex:realValue1, ex:realValue2) 31 | ] 32 | 33 | 34 | # Literals Dimensions 35 | 36 | a cube:Observation; 37 | ex:literalDimension ""^^cube:Undefined. 38 | 39 | ## Snippet for for the according shape: 40 | 41 | [ 42 | sh:path ex:literalDimension; 43 | sh:nodeKind sh:Literal; 44 | sh:or([ 45 | sh:datatype xsd:string 46 | ], [ 47 | sh:datatype cube:Undefined 48 | ]) 49 | ] 50 | ``` 51 | 52 | If it is necessary to state why the value is `cube:Undefined`, annotations should be used. 53 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 13 | 16 | 19 | Cube Schema 20 | 21 | 22 |

Cube Schema

23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 | 38 | 39 |
40 | 41 |
42 | 43 |
44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: Build and push Docker image 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - "dependabot/**/*" 7 | tags: 8 | - "v*.*.*" 9 | 10 | jobs: 11 | docker: 12 | runs-on: ubuntu-latest 13 | 14 | env: 15 | DOCKER_IMAGE: ghcr.io/zazuko/cube-link 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v6 20 | 21 | - name: Replace draft status 22 | run: sed -i 's/"ZZ-DRAFT"/"ZZ-BASIC"/g' config.js meta/config.js relation/config.js 23 | 24 | - name: Remove 'issue-summary' section 25 | run: sed -i '/issue-summary/d' index.html meta/index.html relation/index.html 26 | 27 | - name: Set up Docker Buildx 28 | uses: docker/setup-buildx-action@v3 29 | 30 | - name: Login to GitHub Container Registry 31 | uses: docker/login-action@v3 32 | with: 33 | registry: ghcr.io 34 | username: ${{ github.actor }} 35 | password: ${{ secrets.GITHUB_TOKEN }} 36 | 37 | - name: Docker meta 38 | id: docker_meta 39 | uses: docker/metadata-action@v5 40 | with: 41 | images: "${{ env.DOCKER_IMAGE }}" 42 | tags: | 43 | type=ref,event=branch 44 | type=semver,prefix=v,pattern={{version}} 45 | type=semver,prefix=v,pattern={{major}}.{{minor}} 46 | type=semver,prefix=v,pattern={{major}} 47 | type=sha 48 | 49 | - name: Build and push Docker images 50 | id: docker_build 51 | uses: docker/build-push-action@v6 52 | with: 53 | context: . 54 | file: ./Dockerfile 55 | push: ${{ github.event_name != 'pull_request' || !contains(github.ref, 'dependabot') }} 56 | tags: ${{ steps.docker_meta.outputs.tags }} 57 | labels: ${{ steps.docker_meta.outputs.labels }} 58 | -------------------------------------------------------------------------------- /validation/basic-cube-constraint.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix dash: . 3 | @prefix rdf: . 4 | @prefix rdfs: . 5 | @prefix schema: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | @prefix cube: . 9 | 10 | # 11 | # This is the bare minimal SHACL shape for validating a cube. 12 | # All cubes should pass this validation. 13 | # 14 | 15 | :CubeShape 16 | a sh:NodeShape ; 17 | sh:targetClass cube:Cube ; 18 | sh:property [ 19 | sh:path cube:observationSet ; 20 | sh:minCount 1 ; 21 | sh:node :ObservationSetShape ; 22 | sh:message "cube:Cube needs at least one cube:ObservationSet" 23 | ] ; 24 | sh:property [ 25 | # optional, but recommended 26 | sh:path cube:observationConstraint ; 27 | sh:node :ObservationConstraintShape ; 28 | sh:message "cube:Cube must point to a valid cube:Constraint" 29 | ] . 30 | 31 | :ObservationSetShape 32 | a sh:NodeShape ; 33 | sh:targetClass cube:ObservationSet ; 34 | sh:property [ 35 | sh:path cube:observation ; 36 | sh:minCount 1 ; 37 | sh:message "cube:ObservationSet needs at least one cube:observation" 38 | ] . 39 | 40 | :ObservationConstraintShape 41 | a sh:NodeShape ; 42 | sh:targetClass cube:Constraint ; 43 | sh:property [ 44 | # we assume at least 3 dimensions, otherwise we would have an empty list of dimensions 45 | # one for cube:observedBy, one for rdf:type and at least one cube dimension 46 | sh:path sh:property ; 47 | sh:minCount 3 ; 48 | sh:message "cube:Constraint needs at least a certain amount of sh:properties" 49 | ] . 50 | -------------------------------------------------------------------------------- /test/standalone-cube-constraint/valid.blankContactPoint.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet ; 12 | schema:name "Example cube" ; 13 | schema:publisher ; 14 | schema:creator ; 15 | schema:contributor ; 16 | schema:dateCreated "2020-10-10"^^xsd:date ; 17 | schema:dateModified "2020-10-10"^^xsd:date ; 18 | schema:datePublished "2020-11-11"^^xsd:date ; 19 | schema:contactPoint 20 | [ 21 | schema:name "John Doe" ; 22 | schema:email "john@doe.tech" ; 23 | ] . 24 | 25 | cube:observation . 26 | 27 | a cube:Observation ; 28 | cube:observedBy ; 29 | 4.9 . 30 | 31 | a cube:Constraint ; 32 | sh:targetClass cube:Observation ; 33 | sh:closed true ; 34 | sh:property 35 | [ 36 | sh:path rdf:type ; 37 | sh:nodeKind sh:IRI ; 38 | sh:minCount 1 ; 39 | sh:maxCount 1 ; 40 | ] ; 41 | sh:property 42 | [ 43 | sh:path cube:observedBy ; ; 44 | sh:nodeKind sh:IRI ; 45 | sh:minCount 1 ; 46 | sh:maxCount 1 ; 47 | ] ; 48 | sh:property 49 | [ 50 | sh:datatype xsd:decimal ; 51 | sh:path ; 52 | schema:name "some Quantity" ; 53 | sh:minCount 1 ; 54 | sh:maxCount 1 ; 55 | ] ; 56 | . 57 | -------------------------------------------------------------------------------- /test/standalone-cube-constraint/invalid.blankContactPoint.missingName.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet ; 12 | schema:name "Example cube" ; 13 | schema:publisher ; 14 | schema:creator ; 15 | schema:contributor ; 16 | schema:dateCreated "2020-10-10"^^xsd:date ; 17 | schema:dateModified "2020-10-10"^^xsd:date ; 18 | schema:datePublished "2020-11-11"^^xsd:date ; 19 | schema:contactPoint 20 | [ 21 | # schema:name "John Doe" ; 22 | schema:email "john@doe.tech" ; 23 | ] . 24 | 25 | cube:observation . 26 | 27 | a cube:Observation ; 28 | cube:observedBy ; 29 | 4.9 . 30 | 31 | a cube:Constraint ; 32 | sh:targetClass cube:Observation ; 33 | sh:closed true ; 34 | sh:property 35 | [ 36 | sh:path rdf:type ; 37 | sh:nodeKind sh:IRI ; 38 | sh:minCount 1 ; 39 | sh:maxCount 1 ; 40 | ] ; 41 | sh:property 42 | [ 43 | sh:path cube:observedBy ; ; 44 | sh:nodeKind sh:IRI ; 45 | sh:minCount 1 ; 46 | sh:maxCount 1 ; 47 | ] ; 48 | sh:property 49 | [ 50 | sh:datatype xsd:decimal ; 51 | sh:path ; 52 | schema:name "some Quantity" ; 53 | sh:minCount 1 ; 54 | sh:maxCount 1 ; 55 | ] ; 56 | . 57 | -------------------------------------------------------------------------------- /test/standalone-cube-constraint/invalid.blankContactPoint.missingEmail.ttl: -------------------------------------------------------------------------------- 1 | @prefix rdf: . 2 | @prefix cube: . 3 | @prefix observation: . 4 | @prefix sh: . 5 | @prefix xsd: . 6 | @prefix schema: . 7 | @base . 8 | 9 | a cube:Cube ; 10 | cube:observationConstraint ; 11 | cube:observationSet ; 12 | schema:name "Example cube" ; 13 | schema:publisher ; 14 | schema:creator ; 15 | schema:contributor ; 16 | schema:dateCreated "2020-10-10"^^xsd:date ; 17 | schema:dateModified "2020-10-10T12:34:56"^^xsd:dateTime ; 18 | schema:datePublished "2020-11-11"^^xsd:date ; 19 | schema:contactPoint 20 | [ 21 | schema:name "John Doe" ; 22 | # schema:email "john@doe.tech" ; 23 | ] . 24 | 25 | cube:observation . 26 | 27 | a cube:Observation ; 28 | cube:observedBy ; 29 | 4.9 . 30 | 31 | a cube:Constraint ; 32 | sh:targetClass cube:Observation ; 33 | sh:closed true ; 34 | sh:property 35 | [ 36 | sh:path rdf:type ; 37 | sh:nodeKind sh:IRI ; 38 | sh:minCount 1 ; 39 | sh:maxCount 1 ; 40 | ] ; 41 | sh:property 42 | [ 43 | sh:path cube:observedBy ; ; 44 | sh:nodeKind sh:IRI ; 45 | sh:minCount 1 ; 46 | sh:maxCount 1 ; 47 | ] ; 48 | sh:property 49 | [ 50 | sh:datatype xsd:decimal ; 51 | sh:path ; 52 | schema:name "some Quantity" ; 53 | sh:minCount 1 ; 54 | sh:maxCount 1 ; 55 | ] ; 56 | . 57 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-data-kinds.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:ClosedConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode _:b3 ; 15 | sh:resultPath ; 16 | sh:value "bar" ; 17 | sh:resultMessage "Predicate is not allowed (closed shape)" ; 18 | ], [ 19 | rdf:type sh:ValidationResult ; 20 | sh:resultSeverity sh:Violation ; 21 | sh:sourceConstraintComponent sh:ClosedConstraintComponent ; 22 | sh:sourceShape ; 23 | sh:focusNode _:b5 ; 24 | sh:resultPath ; 25 | sh:value "bar" ; 26 | sh:resultMessage "Predicate is not allowed (closed shape)" ; 27 | ], [ 28 | rdf:type sh:ValidationResult ; 29 | sh:resultSeverity sh:Warning ; 30 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 31 | sh:sourceShape ; 32 | sh:focusNode _:b3 ; 33 | sh:value _:b3 ; 34 | sh:resultMessage "Data kind should be one of the following: GeneralDateTimeDescription, GeoShape, GeoCoordinates" ; 35 | ], [ 36 | rdf:type sh:ValidationResult ; 37 | sh:resultSeverity sh:Warning ; 38 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 39 | sh:sourceShape ; 40 | sh:focusNode _:b5 ; 41 | sh:value _:b5 ; 42 | sh:resultMessage "Data kind should be one of the following: GeneralDateTimeDescription, GeoShape, GeoCoordinates" ; 43 | ] ; 44 | sh:conforms false . 45 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/warning-qudt-unit.ttl: -------------------------------------------------------------------------------- 1 | PREFIX unit: 2 | PREFIX qudt: 3 | @prefix rdf: . 4 | @prefix cube: . 5 | @prefix observation: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | @prefix schema: . 9 | @base . 10 | 11 | a cube:Cube ; 12 | cube:observationConstraint ; 13 | cube:observationSet . 14 | 15 | cube:observation , , . 16 | 17 | a cube:Observation ; 18 | cube:observedBy ; 19 | 4.9 . 20 | 21 | a cube:Observation ; 22 | cube:observedBy ; 23 | 1.0 . 24 | 25 | a cube:Observation ; 26 | cube:observedBy ; 27 | ""^^cube:Undefined . 28 | 29 | a cube:Constraint ; 30 | sh:targetClass cube:Observation ; 31 | sh:closed true ; 32 | sh:property 33 | [ 34 | sh:path rdf:type ; 35 | sh:nodeKind sh:IRI ; 36 | sh:minCount 1 ; 37 | sh:maxCount 1 38 | ] ; 39 | sh:property 40 | [ 41 | sh:path cube:observedBy ; ; 42 | sh:nodeKind sh:IRI ; 43 | sh:minCount 1 ; 44 | sh:maxCount 1 45 | ] ; 46 | sh:property 47 | [ 48 | sh:datatype xsd:decimal ; 49 | sh:path ; 50 | schema:name "some Quantity" ; 51 | sh:minCount 1 ; 52 | sh:maxCount 1 ; 53 | qudt:unit unit:KiloGM ; 54 | ] ; 55 | sh:property 56 | [ 57 | sh:datatype xsd:decimal ; 58 | sh:path ; 59 | schema:name "some Quantity" ; 60 | sh:minCount 1 ; 61 | sh:maxCount 1 ; 62 | qudt:hasUnit unit:KiloGM ; 63 | ] ; 64 | . 65 | -------------------------------------------------------------------------------- /relation/core.md: -------------------------------------------------------------------------------- 1 | # Relation vocabulary # 2 | 3 | ## Classes ## 4 | 5 | The classes in the relation vocabulary are instances of meta:DimensionRelation as well as a rdfs:Class. 6 | This facilitates validation of the Dimension Constraints 7 | 8 | ### relation:StandardError {#StandardError} 9 | 10 | The standard error is the standard deviation of the mean of the sample. 11 | 12 | #### relation:StandardError1SD {#StandardError1SD} 13 | 14 | The standard error is the standard deviation of the mean of the sample. 15 | 16 | #### relation:StandardError2SD {#StandardError2SD} 17 | The standard error is 2 standard deviation of the mean of the sample. 18 | 19 | #### relation:StandardError3SD {#StandardError3SD} 20 | The standard error is 3 standard deviation of the mean of the sample. 21 | 22 | ### relation:StandardDeviation {#StandardDeviation} 23 | 24 | Dispersion of the values of a random variable around its expected value. 25 | 26 | ### relation:Confidence {#MarginOfError} 27 | 28 | Use `Confidence` to specify uncertainty in the estimate. It can be used multiple times, 29 | in which case add `dcterms:type` to each dimension relation to specify the type of confidence 30 | (Margin of Error, Confidence Interval, etc.). 31 | 32 | #### relation:ConfidenceUpperBound and relation:ConfidenceLowerBound {#ConfidenceBounds} 33 | 34 | In case of asymmetric confidence intervals, use `relation:ConfidenceUpperBound` together with 35 | `relation:ConfidenceLowerBound` to specify the upper and lower bounds of the confidence interval. 36 | 37 | ```turtle 38 | [ 39 | sh:property [ 40 | sh:path ex:measurement-dimension ; 41 | ] ; 42 | sh:property [ 43 | sh:path ex:lower-confidence-dimension ; 44 | meta:dimensionRelation [ 45 | a relation:ConfidenceLowerBound ; 46 | dcterms:type "Confidence interval" ; 47 | meta:relatesTo ex:measurement-dimension ; 48 | ] ; 49 | ] ; 50 | sh:property [ 51 | sh:path ex:upper-confidence-dimension ; 52 | meta:dimensionRelation [ 53 | a relation:ConfidenceUpperBound ; 54 | dcterms:type "Confidence interval" ; 55 | meta:relatesTo ex:measurement-dimension ; 56 | ] ; 57 | ] ; 58 | ] . 59 | ``` 60 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.dimensionRelation-relatesToNotMatching.ttl: -------------------------------------------------------------------------------- 1 | @prefix dcterms: . 2 | @prefix relation: . 3 | @prefix meta: . 4 | @prefix rdf: . 5 | @prefix cube: . 6 | @prefix observation: . 7 | @prefix sh: . 8 | @prefix xsd: . 9 | @prefix schema: . 10 | @base . 11 | 12 | a cube:Cube ; 13 | cube:observationConstraint ; 14 | cube:observationSet . 15 | 16 | cube:observation , , . 17 | 18 | a cube:Observation ; 19 | cube:observedBy ; 20 | 4.9 ; 21 | 0.1 ; 22 | . 23 | 24 | a cube:Constraint ; 25 | sh:targetClass cube:Observation ; 26 | sh:closed true ; 27 | sh:property 28 | [ 29 | sh:path rdf:type ; 30 | sh:nodeKind sh:IRI ; 31 | sh:minCount 1 ; 32 | sh:maxCount 1 33 | ] ; 34 | sh:property 35 | [ 36 | sh:path cube:observedBy ; ; 37 | sh:nodeKind sh:IRI ; 38 | sh:minCount 1 ; 39 | sh:maxCount 1 40 | ] ; 41 | sh:property 42 | [ 43 | sh:datatype xsd:decimal ; 44 | sh:path ; 45 | schema:name "dimension" ; 46 | sh:minCount 1 ; 47 | sh:maxCount 1 ; 48 | ], 49 | [ 50 | sh:datatype xsd:decimal ; 51 | sh:path ; 52 | schema:name "upper confidence" ; 53 | sh:minCount 1 ; 54 | sh:maxCount 1 ; 55 | meta:dimensionRelation 56 | [ 57 | a relation:ConfidenceUpperBound ; 58 | dcterms:type "Confidence interval" ; 59 | meta:relatesTo ; 60 | ] ; 61 | ]; 62 | . 63 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.dimensionRelation-multipleDcType.ttl: -------------------------------------------------------------------------------- 1 | PREFIX dcterms: 2 | @prefix relation: . 3 | @prefix meta: . 4 | @prefix rdf: . 5 | @prefix cube: . 6 | @prefix observation: . 7 | @prefix sh: . 8 | @prefix xsd: . 9 | @prefix schema: . 10 | @base . 11 | 12 | a cube:Cube ; 13 | cube:observationConstraint ; 14 | cube:observationSet . 15 | 16 | cube:observation , , . 17 | 18 | a cube:Observation ; 19 | cube:observedBy ; 20 | 4.9 ; 21 | 0.1 ; 22 | . 23 | 24 | a cube:Constraint ; 25 | sh:targetClass cube:Observation ; 26 | sh:closed true ; 27 | sh:property 28 | [ 29 | sh:path rdf:type ; 30 | sh:nodeKind sh:IRI ; 31 | sh:minCount 1 ; 32 | sh:maxCount 1 33 | ] ; 34 | sh:property 35 | [ 36 | sh:path cube:observedBy ; ; 37 | sh:nodeKind sh:IRI ; 38 | sh:minCount 1 ; 39 | sh:maxCount 1 40 | ] ; 41 | sh:property 42 | [ 43 | a cube:MeasureDimension ; 44 | sh:datatype xsd:decimal ; 45 | sh:path ; 46 | schema:name "dimension" ; 47 | sh:minCount 1 ; 48 | sh:maxCount 1 ; 49 | ], 50 | [ 51 | sh:datatype xsd:decimal ; 52 | sh:path ; 53 | schema:name "upper confidence" ; 54 | sh:minCount 1 ; 55 | sh:maxCount 1 ; 56 | meta:dimensionRelation 57 | [ 58 | a relation:ConfidenceUpperBound ; 59 | dcterms:type "Confidence interval", "bogus" ; 60 | meta:relatesTo ; 61 | ] ; 62 | ]; 63 | . 64 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-datatype-langstring.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path cube:observationConstraint ; 15 | sh:maxCount 1 ; 16 | sh:minCount 1 ; 17 | sh:node ; 18 | ] ; 19 | sh:focusNode ; 20 | sh:resultPath cube:observationConstraint ; 21 | sh:value ; 22 | sh:resultMessage "Value does not have shape " ; 23 | sh:detail [ 24 | rdf:type sh:ValidationResult ; 25 | sh:resultSeverity sh:Violation ; 26 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 27 | sh:sourceShape _:b634 ; 28 | sh:focusNode ; 29 | sh:resultPath sh:property ; 30 | sh:value _:b2 ; 31 | sh:resultMessage "Dimension constraint must have exactly one datatype. It cannot be rdf:langString" ; 32 | ] ; 33 | ], [ 34 | rdf:type sh:ValidationResult ; 35 | sh:resultSeverity sh:Violation ; 36 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 37 | sh:sourceShape _:b634 ; 38 | sh:focusNode ; 39 | sh:resultPath sh:property ; 40 | sh:value _:b2 ; 41 | sh:resultMessage "Dimension constraint must have exactly one datatype. It cannot be rdf:langString" ; 42 | ] ; 43 | sh:conforms false . 44 | 45 | _:b634 sh:path sh:property ; 46 | sh:or ( 47 | [ 48 | sh:node ; 49 | ] 50 | [ 51 | sh:node ; 52 | ] 53 | ) ; 54 | sh:message "Dimension constraint must have exactly one datatype. It cannot be rdf:langString" . 55 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-datatype-multiple.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path cube:observationConstraint ; 15 | sh:maxCount 1 ; 16 | sh:minCount 1 ; 17 | sh:node ; 18 | ] ; 19 | sh:focusNode ; 20 | sh:resultPath cube:observationConstraint ; 21 | sh:value ; 22 | sh:resultMessage "Value does not have shape " ; 23 | sh:detail [ 24 | rdf:type sh:ValidationResult ; 25 | sh:resultSeverity sh:Violation ; 26 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 27 | sh:sourceShape _:b634 ; 28 | sh:focusNode ; 29 | sh:resultPath sh:property ; 30 | sh:value _:b2 ; 31 | sh:resultMessage "Dimension constraint must have exactly one datatype. It cannot be rdf:langString" ; 32 | ] ; 33 | ], [ 34 | rdf:type sh:ValidationResult ; 35 | sh:resultSeverity sh:Violation ; 36 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 37 | sh:sourceShape _:b634 ; 38 | sh:focusNode ; 39 | sh:resultPath sh:property ; 40 | sh:value _:b2 ; 41 | sh:resultMessage "Dimension constraint must have exactly one datatype. It cannot be rdf:langString" ; 42 | ] ; 43 | sh:conforms false . 44 | 45 | _:b634 sh:path sh:property ; 46 | sh:or ( 47 | [ 48 | sh:node ; 49 | ] 50 | [ 51 | sh:node ; 52 | ] 53 | ) ; 54 | sh:message "Dimension constraint must have exactly one datatype. It cannot be rdf:langString" . 55 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-no-status.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | # schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 . 39 | 40 | a cube:Constraint ; 41 | sh:closed true ; 42 | sh:property 43 | [ 44 | schema:name "Value" ; 45 | sh:path ; 46 | sh:datatype xsd:decimal ; 47 | sh:nodeKind sh:Literal ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | qudt:scaleType qudt:NominalScale ; 51 | ], 52 | [ 53 | sh:path rdf:type ; 54 | sh:nodeKind sh:IRI ; 55 | sh:minCount 1 ; 56 | sh:maxCount 1 ; 57 | ], 58 | [ 59 | sh:path cube:observedBy ; 60 | sh:nodeKind sh:IRI ; 61 | sh:minCount 1 ; 62 | sh:maxCount 1 ; 63 | ] ; 64 | . 65 | -------------------------------------------------------------------------------- /test/profile-visualize/valid-work-example-warning.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | # schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 . 39 | 40 | a cube:Constraint ; 41 | sh:closed true ; 42 | sh:property 43 | [ 44 | schema:name "Value" ; 45 | sh:path ; 46 | sh:datatype xsd:decimal ; 47 | sh:nodeKind sh:Literal ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | qudt:scaleType qudt:NominalScale ; 51 | ], 52 | [ 53 | sh:path rdf:type ; 54 | sh:nodeKind sh:IRI ; 55 | sh:minCount 1 ; 56 | sh:maxCount 1 ; 57 | ], 58 | [ 59 | sh:path cube:observedBy ; 60 | sh:nodeKind sh:IRI ; 61 | sh:minCount 1 ; 62 | sh:maxCount 1 ; 63 | ] ; 64 | . 65 | -------------------------------------------------------------------------------- /test/profile-visualize/valid-draft.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 . 39 | 40 | a cube:Constraint ; 41 | sh:closed true ; 42 | sh:property 43 | [ 44 | schema:name "Value" ; 45 | sh:path ; 46 | sh:datatype xsd:decimal ; 47 | sh:nodeKind sh:Literal ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | qudt:scaleType qudt:NominalScale ; 51 | ], 52 | [ 53 | sh:path rdf:type ; 54 | sh:nodeKind sh:IRI ; 55 | sh:minCount 1 ; 56 | sh:maxCount 1 ; 57 | qudt:scaleType qudt:NominalScale ; 58 | ], 59 | [ 60 | sh:path cube:observedBy ; 61 | sh:nodeKind sh:IRI ; 62 | sh:minCount 1 ; 63 | sh:maxCount 1 ; 64 | ] ; 65 | . 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cube-link", 3 | "version": "0.2.3", 4 | "private": true, 5 | "description": "Cube Schema", 6 | "type": "module", 7 | "scripts": { 8 | "build": "./build.sh", 9 | "trifid": "trifid --verbose --config=trifid/config.json", 10 | "trifid:local": "trifid --verbose --config=trifid/config.local.json", 11 | "lint": "standard", 12 | "test": "run-p --aggregate-output -cns \"test:* -- {@}\" --", 13 | "test:observations": "sh ./test/check-observations.sh", 14 | "test:basic-cube-constraint": "./test/check-metadata.sh basic-cube-constraint", 15 | "test:standalone-cube-constraint": "./test/check-metadata.sh standalone-cube-constraint", 16 | "test:standalone-constraint-constraint": "./test/check-metadata.sh standalone-constraint-constraint", 17 | "test:profile-visualize": "./test/check-metadata.sh profile-visualize", 18 | "test:profile-opendataswiss": "./test/check-metadata.sh profile-opendataswiss", 19 | "test:profile-opendataswiss-lindas": "./test/check-metadata.sh profile-opendataswiss-lindas", 20 | "release": "changeset tag" 21 | }, 22 | "files": [ 23 | "validate.js", 24 | "validation", 25 | "bin", 26 | "README.md" 27 | ], 28 | "repository": { 29 | "type": "git", 30 | "url": "git://github.com/zazuko/cube-link.git" 31 | }, 32 | "keywords": [ 33 | "cube", 34 | "rdf", 35 | "schema" 36 | ], 37 | "author": "Thomas Bergwinkl (https://www.bergnet.org/people/bergi/card#me)", 38 | "license": "MIT", 39 | "bugs": { 40 | "url": "https://github.com/zazuko/cube-link/issues" 41 | }, 42 | "homepage": "https://github.com/zazuko/cube-link", 43 | "dependencies": { 44 | "node-fetch-cache": "^3.1.3", 45 | "trifid": "^2.4.0" 46 | }, 47 | "devDependencies": { 48 | "@changesets/cli": "^2.26.2", 49 | "@zazuko/shacl-test": "^0.1", 50 | "approvals": "^7.3.0", 51 | "barnard59": "^5.0.0", 52 | "barnard59-base": "^2.4.2", 53 | "barnard59-cube": "^1.4.2", 54 | "barnard59-formats": "^2.1.0", 55 | "barnard59-http": "^2.0.0", 56 | "barnard59-sparql": "^2.3.0", 57 | "chromium": "^3.0.3", 58 | "npm-run-all": "^4.1.5", 59 | "pm2": "^5.3.1", 60 | "respec": "^35.0.0", 61 | "serve": "^14.2.5", 62 | "standard": "^14.3.4", 63 | "ts-node": "^10.2.1" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-datatype-langstring.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdfs: 3 | PREFIX rdf: 4 | PREFIX meta: 5 | PREFIX sh: 6 | PREFIX xsd: 7 | PREFIX dcterms: 8 | PREFIX schema: 9 | PREFIX dcat: 10 | PREFIX cube: 11 | PREFIX ex: 12 | 13 | ex:Cube 14 | a cube:Cube, dcat:Dataset ; 15 | cube:observationSet ; 16 | cube:observationConstraint ; 17 | schema:name "Example cube" ; 18 | schema:publisher ; 19 | schema:creator ; 20 | schema:contributor ; 21 | dcterms:identifier "cube-1234" ; 22 | schema:workExample ; 23 | schema:creativeWorkStatus ; 24 | dcterms:creator ex:John-Doe ; 25 | schema:dateCreated "2020-10-10"^^xsd:date ; 26 | schema:dateModified "2020-10-10"^^xsd:date ; 27 | schema:datePublished "2020-11-11"^^xsd:date ; 28 | schema:contactPoint 29 | [ 30 | schema:name "John Doe" ; 31 | schema:email "john@doe.tech" ; 32 | ] ; 33 | . 34 | 35 | cube:observation . 36 | 37 | a cube:Observation ; 38 | cube:observedBy ; 39 | 4.9 . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | schema:name "Value" ; 46 | sh:path ; 47 | sh:datatype rdf:langString ; 48 | sh:nodeKind sh:Literal ; 49 | sh:minCount 1 ; 50 | sh:maxCount 1 ; 51 | qudt:scaleType qudt:NominalScale ; 52 | ], 53 | [ 54 | sh:path rdf:type ; 55 | sh:nodeKind sh:IRI ; 56 | sh:minCount 1 ; 57 | sh:maxCount 1 ; 58 | ], 59 | [ 60 | sh:path cube:observedBy ; 61 | sh:nodeKind sh:IRI ; 62 | sh:minCount 1 ; 63 | sh:maxCount 1 ; 64 | ] ; 65 | . 66 | -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: Test validation 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | check-constraint: 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | os: 14 | - ubuntu-latest 15 | - windows-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v6 19 | 20 | - name: Set up Node.js 21 | uses: actions/setup-node@v6 22 | with: 23 | node-version: "lts/*" 24 | cache: npm 25 | 26 | - name: Install dependencies 27 | run: npm ci 28 | 29 | - name: Run tests 30 | shell: sh 31 | run: ./test/check-observations.sh 32 | 33 | - name: Show test results 34 | if: ${{ always() }} 35 | shell: sh 36 | run: for file in test/observations/*.log ; do echo === $file === ; cat $file ; done 37 | 38 | - name: Upload test results 39 | uses: actions/upload-artifact@v5 40 | if: ${{ failure() }} 41 | with: 42 | name: test-observations 43 | path: test 44 | 45 | check-cube: 46 | runs-on: ${{ matrix.os }} 47 | strategy: 48 | fail-fast: false 49 | matrix: 50 | os: 51 | - ubuntu-latest 52 | - windows-latest 53 | profile: 54 | - basic-cube-constraint 55 | - standalone-constraint-constraint 56 | - profile-visualize 57 | - profile-opendataswiss 58 | - profile-opendataswiss-lindas 59 | steps: 60 | - name: Checkout 61 | uses: actions/checkout@v6 62 | 63 | - name: Set up Node.js 64 | uses: actions/setup-node@v6 65 | with: 66 | node-version: "lts/*" 67 | cache: npm 68 | 69 | - name: Install dependencies 70 | run: npm ci 71 | 72 | - name: Run tests 73 | shell: sh 74 | run: ./test/check-metadata.sh ${{ matrix.profile }} 75 | 76 | - name: Show test results 77 | if: ${{ always() }} 78 | shell: sh 79 | run: for file in test/${{ matrix.profile }}/*.log ; do echo === $file === ; cat $file ; done 80 | 81 | - name: Upload test results 82 | uses: actions/upload-artifact@v5 83 | if: ${{ failure() }} 84 | with: 85 | name: test-${{ matrix.profile }} 86 | path: test 87 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-datatype-multiple.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdfs: 3 | PREFIX rdf: 4 | PREFIX meta: 5 | PREFIX sh: 6 | PREFIX xsd: 7 | PREFIX dcterms: 8 | PREFIX schema: 9 | PREFIX dcat: 10 | PREFIX cube: 11 | PREFIX ex: 12 | 13 | ex:Cube 14 | a cube:Cube, dcat:Dataset ; 15 | cube:observationSet ; 16 | cube:observationConstraint ; 17 | schema:name "Example cube" ; 18 | schema:publisher ; 19 | schema:creator ; 20 | schema:contributor ; 21 | dcterms:identifier "cube-1234" ; 22 | schema:workExample ; 23 | schema:creativeWorkStatus ; 24 | dcterms:creator ex:John-Doe ; 25 | schema:dateCreated "2020-10-10"^^xsd:date ; 26 | schema:dateModified "2020-10-10"^^xsd:date ; 27 | schema:datePublished "2020-11-11"^^xsd:date ; 28 | schema:contactPoint 29 | [ 30 | schema:name "John Doe" ; 31 | schema:email "john@doe.tech" ; 32 | ] ; 33 | . 34 | 35 | cube:observation . 36 | 37 | a cube:Observation ; 38 | cube:observedBy ; 39 | 4.9 . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | schema:name "Value" ; 46 | sh:path ; 47 | sh:datatype xsd:decimal ; 48 | sh:datatype xsd:float ; 49 | sh:nodeKind sh:Literal ; 50 | sh:minCount 1 ; 51 | sh:maxCount 1 ; 52 | qudt:scaleType qudt:NominalScale ; 53 | ], 54 | [ 55 | sh:path rdf:type ; 56 | sh:nodeKind sh:IRI ; 57 | sh:minCount 1 ; 58 | sh:maxCount 1 ; 59 | ], 60 | [ 61 | sh:path cube:observedBy ; 62 | sh:nodeKind sh:IRI ; 63 | sh:minCount 1 ; 64 | sh:maxCount 1 ; 65 | ] ; 66 | . 67 | -------------------------------------------------------------------------------- /documentation/existingwork.md: -------------------------------------------------------------------------------- 1 | # Related Work 2 | 3 | ## RDF Data Cube Vocabulary 4 | 5 | The [[[vocab-data-cube]]] is probably the oldest vocabulary in the domain of RDF for representing cubes. The authors of this document used RDF Data Cubes extensively in the past and ran into multiple issues with it. 6 | 7 | The authors of this specification are grateful for the work done by the original authors of the RDF Data Cube Vocabulary specification. This work would not have been possible without it and some parts look pretty much like the RDF Data Cube Vocabulary. 8 | 9 | It was considered to either clarify or update the RDF Data Cube Vocabulary specification. For the sake of simplicity, it was decided to start from scratch. 10 | 11 | ### Issues with RDF Data Cube Vocabulary 12 | 13 | * The metadata model is overly complex. 14 | * Many additional nodes are introduced that make querying the data in the real world overly complex. 15 | * Generating proper metadata from basic cubes is not easy, which increases complexity for automated pipelines. 16 | * There is a mix of forward- and backward-linking within the metadata model. 17 | * [Follow your nose](https://patterns.dataincubator.org/book/follow-your-nose.html) is often not possible. 18 | * There is more than one way to do it. Different people interpret the spec differently, which makes it very hard to write libraries that consume generic RDF Data Cubes. 19 | * There is a clear focus on [SDMX](https://en.wikipedia.org/wiki/SDMX), which introduces too rigorous restrictions and/or examples for use-cases outside the statistical domain. 20 | * Re-use of dimensions is not very common in the RDF Data Cube vocabulary, which makes it much harder to compare data across data providers. 21 | 22 | There are at least two efforts that extend the RDF Data Cube Vocabulary to address some of its limitations: 23 | 24 | * [[[?qb4st]]] 25 | * [QB4OLAP](https://github.com/lorenae/qb4olap/wiki) 26 | 27 | Both efforts could likely be solved/addressed within the _Cube Schema_ approach, this needs to be validated by interested parties. 28 | 29 | ## SSN 30 | 31 | The [[[vocab-ssn]]] defines a simplified model for describing observations from a sensor in RDF. 32 | 33 | The [Observation](https://www.w3.org/TR/vocab-ssn/#SOSAObservation) model is at least inspired by the RDF Data Cube Vocabulary but it is not very useful for use-cases outside of sensor networks. 34 | 35 | It should be relatively easy to replace SSN observations with the _Cube Schema_. -------------------------------------------------------------------------------- /test/profile-visualize/invalid-temporal.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:ClosedConstraintComponent ; 13 | sh:sourceShape ; 14 | sh:focusNode _:b5 ; 15 | sh:resultPath rdf:first ; 16 | sh:value "2000"^^xsd:gYear ; 17 | sh:resultMessage "Predicate is not allowed (closed shape)" ; 18 | ], [ 19 | rdf:type sh:ValidationResult ; 20 | sh:resultSeverity sh:Violation ; 21 | sh:sourceConstraintComponent sh:ClosedConstraintComponent ; 22 | sh:sourceShape ; 23 | sh:focusNode _:b5 ; 24 | sh:resultPath rdf:rest ; 25 | sh:value rdf:nil ; 26 | sh:resultMessage "Predicate is not allowed (closed shape)" ; 27 | ], [ 28 | rdf:type sh:ValidationResult ; 29 | sh:resultSeverity sh:Warning ; 30 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 31 | sh:sourceShape ; 32 | sh:focusNode _:b5 ; 33 | sh:value _:b5 ; 34 | sh:resultMessage "Data kind should be one of the following: GeneralDateTimeDescription, GeoShape, GeoCoordinates" ; 35 | ], [ 36 | rdf:type sh:ValidationResult ; 37 | sh:resultSeverity sh:Violation ; 38 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 39 | sh:sourceShape ; 40 | sh:focusNode _:b3 ; 41 | sh:value _:b3 ; 42 | sh:resultMessage "Temporal dimension must be one of XSD datatypes: gYear, gYearMonth, date, dateTime, or have time:unitType, or have an ordinal scaleType" ; 43 | ], [ 44 | rdf:type sh:ValidationResult ; 45 | sh:resultSeverity sh:Violation ; 46 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 47 | sh:sourceShape ; 48 | sh:focusNode _:b5 ; 49 | sh:value _:b5 ; 50 | sh:resultMessage "Temporal dimension must be one of XSD datatypes: gYear, gYearMonth, date, dateTime, or have time:unitType, or have an ordinal scaleType" ; 51 | ] ; 52 | sh:conforms false . 53 | -------------------------------------------------------------------------------- /trifid/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseConfig": "cwd:trifid/config-base.json", 3 | "handler": { 4 | "root": { 5 | "module": "trifid-handler-fetch", 6 | "options": { 7 | "resource": "https://cube.link/", 8 | "url": "cwd:vocab.ttl", 9 | "contentType": "text/turtle", 10 | "cache": "true" 11 | } 12 | }, 13 | "meta": { 14 | "path": "/meta/", 15 | "module": "trifid-handler-fetch", 16 | "options": { 17 | "resource": "https://cube.link/meta/", 18 | "url": "cwd:meta/meta.ttl", 19 | "contentType": "text/turtle", 20 | "cache": "true" 21 | } 22 | }, 23 | "relation": { 24 | "path": "/relation/", 25 | "module": "trifid-handler-fetch", 26 | "options": { 27 | "resource": "https://cube.link/relation/", 28 | "url": "cwd:relation/relation.ttl", 29 | "contentType": "text/turtle", 30 | "cache": "true" 31 | } 32 | } 33 | }, 34 | "renderer": { 35 | "root": null, 36 | "meta": { 37 | "path": "/meta/", 38 | "module": "trifid-renderer-simple", 39 | "template": "cwd:dist/meta.html", 40 | "templateError": "trifid:views/error.html", 41 | "alternativeMediaTypes": [ 42 | "application/ld+json", 43 | "application/n-triples", 44 | "application/rdf+xml", 45 | "text/turtle" 46 | ] 47 | }, 48 | "relation": { 49 | "path": "/relation/", 50 | "module": "trifid-renderer-simple", 51 | "template": "cwd:dist/relation.html", 52 | "templateError": "trifid:views/error.html", 53 | "alternativeMediaTypes": [ 54 | "application/ld+json", 55 | "application/n-triples", 56 | "application/rdf+xml", 57 | "text/turtle" 58 | ] 59 | }, 60 | "cube": { 61 | "module": "trifid-renderer-simple", 62 | "template": "cwd:dist/cube.html", 63 | "templateError": "trifid:views/error.html", 64 | "alternativeMediaTypes": [ 65 | "application/ld+json", 66 | "application/n-triples", 67 | "application/rdf+xml", 68 | "text/turtle" 69 | ] 70 | } 71 | }, 72 | "staticViews": { 73 | "/": null 74 | }, 75 | "staticFiles": { 76 | "images": { 77 | "path": "/img/", 78 | "folder": "cwd:img" 79 | } 80 | }, 81 | "plugins": { 82 | "vocab-redirect": { 83 | "priority": 55, 84 | "module": "trifid-core:./plugins/middleware", 85 | "middleware": "cwd:trifid/redirect.cjs" 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /test/profile-visualize/valid.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 ; 39 | . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | schema:name "Dimenson 1" ; 46 | sh:path ; 47 | sh:nodeKind sh:IRI ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | qudt:scaleType qudt:NominalScale ; 51 | ], 52 | [ 53 | schema:name "Measure" ; 54 | sh:path ; 55 | sh:datatype xsd:decimal ; 56 | sh:nodeKind sh:Literal ; 57 | sh:minCount 1 ; 58 | sh:maxCount 1 ; 59 | qudt:scaleType qudt:NominalScale ; 60 | ], 61 | [ 62 | sh:path rdf:type ; 63 | sh:nodeKind sh:IRI ; 64 | sh:minCount 1 ; 65 | sh:maxCount 1 ; 66 | ], 67 | [ 68 | sh:path cube:observedBy ; 69 | sh:nodeKind sh:IRI ; 70 | sh:minCount 1 ; 71 | sh:maxCount 1 ; 72 | ] ; 73 | . 74 | -------------------------------------------------------------------------------- /vocab.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | 3 | @prefix rdf: . 4 | @prefix rdfs: . 5 | 6 | 7 | # Core Schema 8 | 9 | <> 10 | rdfs:label "Cube Schema". 11 | 12 | a rdfs:Class; 13 | rdfs:label "Constraint"; 14 | rdfs:comment "Specifies constraints that need to be met on the Cube. Used for metadata and validation.". 15 | 16 | a rdfs:Class; 17 | rdfs:label "Cube"; 18 | rdfs:comment "Represents the entry point for a collection of observations, conforming to some common dimensional structure.". 19 | 20 | a rdfs:Class; 21 | rdfs:label "Observation"; 22 | rdfs:comment "A single observation in the cube, may have one or more associated dimensions.". 23 | 24 | a rdfs:Class; 25 | rdfs:label "Observation Set"; 26 | rdfs:comment "A set of observations.". 27 | 28 | a rdf:Property; 29 | rdfs:range ; 30 | rdfs:domain ; 31 | rdfs:label "observation"; 32 | rdfs:comment "Connects a set of observations with a single observation.". 33 | 34 | a rdf:Property; 35 | rdfs:range ; 36 | rdfs:domain ; 37 | rdfs:label "observation constraint"; 38 | rdfs:comment "Connects a cube with a constraint for metadata and validation.". 39 | 40 | a rdf:Property; 41 | rdfs:range ; 42 | rdfs:domain ; 43 | rdfs:label "observation set"; 44 | rdfs:comment "Connects a cube with a set of observations.". 45 | 46 | a rdf:Property; 47 | rdfs:domain ; 48 | rdfs:range rdfs:Resource; 49 | rdfs:label "observed by"; 50 | rdfs:comment "Connects an observation with the agent that created the observation. The agent can be a person, organisation, device or software. A description of the method to gather the data could be attached to the agent.". 51 | 52 | a rdfs:Datatype; 53 | rdfs:label "Undefined observation."; 54 | rdfs:comment "An observation which is not defined.". 55 | 56 | a rdfs:Class; 57 | rdfs:label "Key Dimension"; 58 | rdfs:comment "The KeyDimension tags one or multiple dimensions which are together uniquely identifying an observation. You can think of them as the Key in a relational database."; 59 | . 60 | 61 | a rdfs:Class; 62 | rdfs:label "Measure Dimension"; 63 | rdfs:comment "The MeasureDimension tags at least one dimension, but potentially multiple, which is the actual measurement, or statistical count attached to an observation.". 64 | 65 | -------------------------------------------------------------------------------- /test/profile-visualize/warning-missing-sh-in.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 ; 39 | . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | a cube:KeyDimension ; 46 | schema:name "Dimenson 1" ; 47 | sh:path ; 48 | sh:nodeKind sh:IRI ; 49 | sh:minCount 1 ; 50 | sh:maxCount 1 ; 51 | qudt:scaleType qudt:NominalScale ; 52 | ], 53 | [ 54 | schema:name "Measure" ; 55 | sh:path ; 56 | sh:datatype xsd:decimal ; 57 | sh:nodeKind sh:Literal ; 58 | sh:minCount 1 ; 59 | sh:maxCount 1 ; 60 | qudt:scaleType qudt:NominalScale ; 61 | ], 62 | [ 63 | sh:path rdf:type ; 64 | sh:nodeKind sh:IRI ; 65 | sh:minCount 1 ; 66 | sh:maxCount 1 ; 67 | ], 68 | [ 69 | sh:path cube:observedBy ; 70 | sh:nodeKind sh:IRI ; 71 | sh:minCount 1 ; 72 | sh:maxCount 1 ; 73 | ] ; 74 | . 75 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.malformedList.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 13 | sh:sourceShape _:b744 ; 14 | sh:focusNode _:b6 ; 15 | sh:resultPath rdf:rest ; 16 | sh:resultMessage "list node needs exactly one rdf:rest" ; 17 | ], [ 18 | rdf:type sh:ValidationResult ; 19 | sh:resultSeverity sh:Violation ; 20 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 21 | sh:sourceShape [ 22 | sh:path sh:property ; 23 | sh:message "sh:in needs to be a list" ; 24 | sh:node ; 25 | ] ; 26 | sh:focusNode ; 27 | sh:resultPath sh:property ; 28 | sh:resultMessage "sh:in needs to be a list" ; 29 | sh:detail [ 30 | rdf:type sh:ValidationResult ; 31 | sh:resultSeverity sh:Violation ; 32 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 33 | sh:sourceShape [ 34 | sh:path sh:in ; 35 | sh:node ; 36 | ] ; 37 | sh:focusNode _:b5 ; 38 | sh:resultPath sh:in ; 39 | sh:resultMessage "Value does not have shape " ; 40 | sh:detail [ 41 | rdf:type sh:ValidationResult ; 42 | sh:resultSeverity sh:Violation ; 43 | sh:sourceConstraintComponent sh:MinCountConstraintComponent ; 44 | sh:sourceShape _:b744 ; 45 | sh:focusNode _:b6 ; 46 | sh:resultPath rdf:rest ; 47 | sh:resultMessage "list node needs exactly one rdf:rest" ; 48 | ] ; 49 | sh:value _:b6 ; 50 | ] ; 51 | sh:value _:b5 ; 52 | ], [ 53 | rdf:type sh:ValidationResult ; 54 | sh:resultSeverity sh:Violation ; 55 | sh:sourceConstraintComponent sh:XoneConstraintComponent ; 56 | sh:sourceShape ; 57 | sh:focusNode rdf:wrong ; 58 | sh:resultMessage "rdf:rest value must be a list node or rdf:nil" ; 59 | sh:value rdf:wrong ; 60 | ] ; 61 | sh:conforms false . 62 | 63 | _:b744 sh:path rdf:rest ; 64 | sh:maxCount 1 ; 65 | sh:minCount 1 ; 66 | sh:message "list node needs exactly one rdf:rest" . 67 | -------------------------------------------------------------------------------- /test/profile-visualize/valid-sh-in.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 ; 39 | . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | a cube:KeyDimension ; 46 | schema:name "Dimenson 1" ; 47 | sh:path ; 48 | sh:nodeKind sh:IRI ; 49 | sh:minCount 1 ; 50 | sh:maxCount 1 ; 51 | qudt:scaleType qudt:NominalScale ; 52 | sh:in ( ) ; 53 | ], 54 | [ 55 | schema:name "Measure" ; 56 | sh:path ; 57 | sh:datatype xsd:decimal ; 58 | sh:nodeKind sh:Literal ; 59 | sh:minCount 1 ; 60 | sh:maxCount 1 ; 61 | qudt:scaleType qudt:NominalScale ; 62 | ], 63 | [ 64 | sh:path rdf:type ; 65 | sh:nodeKind sh:IRI ; 66 | sh:minCount 1 ; 67 | sh:maxCount 1 ; 68 | ], 69 | [ 70 | sh:path cube:observedBy ; 71 | sh:nodeKind sh:IRI ; 72 | sh:minCount 1 ; 73 | sh:maxCount 1 ; 74 | ] ; 75 | . 76 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-scale-types.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 ; 39 | . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | schema:name "Dimenson 1" ; 46 | sh:path ; 47 | sh:nodeKind sh:IRI ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | # scale type missing 51 | # qudt:scaleType qudt:NominalScale ; 52 | ], 53 | [ 54 | schema:name "Measure" ; 55 | sh:path ; 56 | sh:datatype xsd:decimal ; 57 | sh:nodeKind sh:Literal ; 58 | sh:minCount 1 ; 59 | sh:maxCount 1 ; 60 | # scale type outside allowed values 61 | qudt:scaleType qudt:EnumerationScale ; 62 | ], 63 | [ 64 | sh:path rdf:type ; 65 | sh:nodeKind sh:IRI ; 66 | sh:minCount 1 ; 67 | sh:maxCount 1 ; 68 | ], 69 | [ 70 | sh:path cube:observedBy ; 71 | sh:nodeKind sh:IRI ; 72 | sh:minCount 1 ; 73 | sh:maxCount 1 ; 74 | ] ; 75 | . 76 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-missingValue.ttl: -------------------------------------------------------------------------------- 1 | PREFIX ex: 2 | PREFIX dcterms: 3 | @prefix relation: . 4 | @prefix meta: . 5 | @prefix rdf: . 6 | @prefix cube: . 7 | @prefix observation: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | @prefix schema: . 11 | @base . 12 | 13 | a cube:Cube ; 14 | cube:observationConstraint ; 15 | cube:observationSet . 16 | 17 | cube:observation . 18 | 19 | a cube:Observation ; 20 | cube:observedBy ; 21 | 4.9 ; 22 | ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "measure" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | meta:annotation 51 | [ 52 | a meta:Limit ; 53 | schema:name "Target 2020+" ; 54 | meta:annotationContext 55 | [ 56 | sh:path ; 57 | sh:minInclusive ; 58 | ] ; 59 | ] ; 60 | ] ; 61 | sh:property 62 | [ 63 | a cube:KeyDimension ; 64 | sh:path ; 65 | schema:name "year" ; 66 | sh:minCount 1 ; 67 | sh:maxCount 1 ; 68 | sh:nodeKind sh:IRI ; 69 | ] ; 70 | sh:property 71 | [ 72 | a cube:KeyDimension ; 73 | sh:path ; 74 | schema:name "station" ; 75 | sh:minCount 1 ; 76 | sh:maxCount 1 ; 77 | sh:nodeKind sh:IRI ; 78 | ] ; 79 | . 80 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/valid.dimensionRelation.ttl: -------------------------------------------------------------------------------- 1 | PREFIX dcterms: 2 | @prefix relation: . 3 | @prefix meta: . 4 | @prefix rdf: . 5 | @prefix cube: . 6 | @prefix observation: . 7 | @prefix sh: . 8 | @prefix xsd: . 9 | @prefix schema: . 10 | @base . 11 | 12 | a cube:Cube ; 13 | cube:observationConstraint ; 14 | cube:observationSet . 15 | 16 | cube:observation , , . 17 | 18 | a cube:Observation ; 19 | cube:observedBy ; 20 | 4.9 ; 21 | 0.1 ; 22 | 0.15 ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "dimension" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | ], 51 | [ 52 | sh:datatype xsd:decimal ; 53 | sh:path ; 54 | schema:name "upper confidence" ; 55 | sh:minCount 1 ; 56 | sh:maxCount 1 ; 57 | meta:dimensionRelation 58 | [ 59 | a relation:ConfidenceUpperBound ; 60 | dcterms:type "Confidence interval" ; 61 | meta:relatesTo ; 62 | ] ; 63 | ], 64 | [ 65 | sh:datatype xsd:decimal ; 66 | sh:path ; 67 | schema:name "lower confidence" ; 68 | sh:minCount 1 ; 69 | sh:maxCount 1 ; 70 | meta:dimensionRelation 71 | [ 72 | a relation:ConfidenceLowerBound ; 73 | dcterms:type "Confidence interval" ; 74 | meta:relatesTo ; 75 | ] ; 76 | ] ; 77 | . 78 | -------------------------------------------------------------------------------- /validation/basic-cube-constraint-ml.ttl: -------------------------------------------------------------------------------- 1 | @prefix : . 2 | @prefix dash: . 3 | @prefix rdf: . 4 | @prefix rdfs: . 5 | @prefix schema: . 6 | @prefix sh: . 7 | @prefix xsd: . 8 | @prefix cube: . 9 | 10 | # 11 | # This is the bare minimal SHACL shape for validating a cube. 12 | # All cubes should pass this validation. 13 | # 14 | 15 | :CubeShape 16 | a sh:NodeShape ; 17 | sh:targetClass cube:Cube ; 18 | sh:property [ 19 | sh:path cube:observationSet ; 20 | sh:minCount 1 ; 21 | sh:node :ObservationSetShape ; 22 | sh:message "cube:Cube needs at least one cube:ObservationSet" 23 | ]; 24 | sh:property [ 25 | # optional, but recommended 26 | sh:path cube:observationConstraint ; 27 | sh:node :ObservationConstraintShape ; 28 | sh:message "cube:Cube must point to a valid cube:Constraint" 29 | ] . 30 | 31 | :ObservationSetShape 32 | a sh:NodeShape ; 33 | sh:targetClass cube:ObservationSet ; 34 | sh:property [ 35 | sh:path cube:observation ; 36 | sh:minCount 1 ; 37 | sh:message "cube:ObservationSet needs at least one cube:observation" 38 | ] . 39 | 40 | :ObservationConstraintShape 41 | a sh:NodeShape ; 42 | sh:targetClass cube:Constraint ; 43 | sh:property [ 44 | # we assume at least 3 dimensions, otherwise we would have an empty list of dimensions 45 | # one for cube:observedBy, one for rdf:type and at least one cube dimension 46 | sh:path sh:property ; 47 | sh:minCount 3 ; 48 | sh:message "cube:Constraint needs at least a certain amount of sh:properties" 49 | ] , 50 | [ 51 | # we assume at least 3 dimensions, otherwise we would have an empty list of dimensions 52 | # one for cube:observedBy, one for rdf:type and at least one cube dimension 53 | sh:path sh:property ; 54 | sh:node :SchemaNameML ; 55 | sh:message "When Schema:name is provided it should have all 3 languages" 56 | ] . 57 | 58 | :SchemaNameML a sh:NodeShape ; 59 | sh:property [ 60 | sh:or( 61 | [ 62 | sh:path schema:name; 63 | sh:minCount 3; 64 | sh:languageIn ( "en" "fr" "de" ); 65 | sh:message "When Schema:name is provided it should have all required languages" 66 | ] 67 | [ 68 | sh:path sh:path; 69 | sh:in (rdf:type cube:observedBy); 70 | ] 71 | ) 72 | ] . 73 | -------------------------------------------------------------------------------- /constraint.ttl: -------------------------------------------------------------------------------- 1 | @base . 2 | 3 | @prefix dc: . 4 | @prefix cube: . 5 | @prefix dh: . 6 | @prefix rdf: . 7 | @prefix rdfs: . 8 | @prefix sh: . 9 | @prefix xml: . 10 | @prefix xsd: . 11 | @prefix ex: . 12 | @prefix skos: . 13 | @prefix schema: . 14 | @prefix qudt: . 15 | 16 | a sh:NodeShape, cube:Constraint ; 17 | sh:closed true ; 18 | sh:property [ 19 | sh:path rdf:type ; 20 | sh:nodeKind sh:IRI ; 21 | sh:in ( cube:Observation ) 22 | ], [ 23 | sh:path cube:observedBy ; 24 | sh:nodeKind sh:IRI ; 25 | sh:in ( ) 26 | ], [ 27 | schema:name "Date and Time"@en, "Datum und Zeit"@de, "Date et heure"@fr; # optional, label of the vocab can be used 28 | sh:path dc:date ; 29 | sh:datatype xsd:dateTime ; 30 | sh:minCount 1 ; 31 | sh:maxCount 1 ; 32 | qudt:scaleType qudt:IntervalScale ; 33 | ], [ 34 | schema:name "Humidity"@en, "Feuchtigkeit"@de, "Humidité"@fr ; # optional, label of the vocab can be used 35 | sh:path dh:humidity ; 36 | sh:datatype xsd:decimal ; 37 | sh:minCount 1 ; 38 | sh:maxCount 1 ; 39 | sh:minInclusive 0 ; 40 | sh:maxInclusive 100 ; 41 | qudt:scaleType qudt:IntervalScale ; 42 | ], [ 43 | schema:name "Low Battery Power"@en, "Niedrige Batterieleistung"@de, "Piles faibles"@fr ; # optional, label of the vocab can be used 44 | sh:path dh:lowBatteryPower ; 45 | sh:datatype xsd:boolean ; 46 | sh:minCount 1 ; 47 | sh:maxCount 1 ; 48 | sh:in ( "true"^^xsd:boolean "false"^^xsd:boolean ) ; 49 | qudt:scaleType qudt:NominalScale ; 50 | ], [ 51 | schema:name "Temperature"@en, "Temperatur"@de, "Température"@fr ; # optional, label of the vocab can be used 52 | sh:path dh:temperature ; 53 | sh:datatype xsd:decimal ; 54 | sh:minCount 1 ; 55 | sh:maxCount 1 ; 56 | sh:minInclusive -50 ; 57 | sh:maxInclusive 50 ; 58 | qudt:scaleType qudt:IntervalScale ; 59 | ], [ 60 | schema:name "Raum"@de , "Pièce"@fr ,"Room"@en ; 61 | sh:path dh:room ; 62 | sh:maxCount 1 ; 63 | sh:class schema:Place ; 64 | sh:nodeKind sh:IRI ; 65 | sh:in ( ) ; 66 | qudt:scaleType qudt:NominalScale ; 67 | ] . 68 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-mixedConstraints.ttl: -------------------------------------------------------------------------------- 1 | PREFIX ex: 2 | PREFIX dcterms: 3 | @prefix relation: . 4 | @prefix meta: . 5 | @prefix rdf: . 6 | @prefix cube: . 7 | @prefix observation: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | @prefix schema: . 11 | @base . 12 | 13 | a cube:Cube ; 14 | cube:observationConstraint ; 15 | cube:observationSet . 16 | 17 | cube:observation . 18 | 19 | a cube:Observation ; 20 | cube:observedBy ; 21 | 4.9 ; 22 | ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "measure" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | meta:annotation 51 | [ 52 | a meta:Limit ; 53 | schema:maxValue 97 ; 54 | schema:name "Mixed target" ; 55 | meta:annotationContext 56 | [ 57 | sh:path ; 58 | sh:minInclusive ; 59 | sh:hasValue ; 60 | ] ; 61 | ] ; 62 | ] ; 63 | sh:property 64 | [ 65 | a cube:KeyDimension ; 66 | sh:path ; 67 | schema:name "year" ; 68 | sh:minCount 1 ; 69 | sh:maxCount 1 ; 70 | sh:nodeKind sh:IRI ; 71 | ] ; 72 | sh:property 73 | [ 74 | a cube:KeyDimension ; 75 | sh:path ; 76 | schema:name "station" ; 77 | sh:minCount 1 ; 78 | sh:maxCount 1 ; 79 | sh:nodeKind sh:IRI ; 80 | ] ; 81 | . 82 | -------------------------------------------------------------------------------- /relation/relation.ttl: -------------------------------------------------------------------------------- 1 | PREFIX rdf: 2 | PREFIX rdfs: 3 | PREFIX cube: 4 | PREFIX meta: 5 | PREFIX relation: 6 | PREFIX schema: 7 | 8 | relation:StandardError a meta:DimensionRelation; 9 | schema:name "Standard Error"; 10 | rdfs:label "Standard Error"; 11 | schema:description "The standard error is the standard deviation of the mean of the sample."; 12 | rdfs:comment "The standard error is the standard deviation of the mean of the sample."; 13 | schema:about ; 14 | schema:sameAs . 15 | 16 | relation:StandardError1SD a meta:DimensionRelation; 17 | rdfs:subClassOf relation:StandardError; 18 | schema:name "The standard error is the standard deviation of the mean of the sample."; 19 | rdfs:label "The standard error is the standard deviation of the mean of the sample."; 20 | schema:alternateName "SE". 21 | 22 | relation:StandardError2SD a meta:DimensionRelation; 23 | rdfs:subClassOf relation:StandardError; 24 | schema:name "The standard error is 2 standard deviation of the mean of the sample."; 25 | rdfs:label "The standard error is 2 standard deviation of the mean of the sample."; 26 | schema:alternateName "2SE". 27 | 28 | relation:StandardError3SD a meta:DimensionRelation; 29 | rdfs:subClassOf relation:StandardError; 30 | schema:name "The standard error is 3 standard deviation of the mean of the sample."; 31 | rdfs:label "The standard error is 3 standard deviation of the mean of the sample."; 32 | schema:alternateName "3SE". 33 | 34 | relation:StandardDeviation a meta:DimensionRelation; 35 | schema:name "Standard Deviation"; 36 | rdfs:label "Standard Deviation"; 37 | schema:alternateName "SD"; 38 | schema:description "Dispersion of the values of a random variable around its expected value."; 39 | rdfs:comment "Dispersion of the values of a random variable around its expected value."; 40 | schema:about ; 41 | schema:sameAs . 42 | 43 | relation:Confidence a meta:DimensionRelation; 44 | schema:name "Confidence" ; 45 | rdfs:label "Confidence" ; 46 | schema:about . 47 | 48 | relation:ConfidenceUpperBound 49 | a meta:DimensionRelation ; 50 | schema:name "Confidence (Upper Bound)" ; 51 | rdfs:label "Confidence (Upper Bound)" ; 52 | schema:about 53 | . 54 | 55 | relation:ConfidenceLowerBound 56 | a meta:DimensionRelation ; 57 | schema:name "Confidence (Lower Bound)" ; 58 | rdfs:label "Confidence (Lower Bound)" ; 59 | schema:about . 60 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-invalidRanges.ttl: -------------------------------------------------------------------------------- 1 | PREFIX ex: 2 | PREFIX dcterms: 3 | @prefix relation: . 4 | @prefix meta: . 5 | @prefix rdf: . 6 | @prefix cube: . 7 | @prefix observation: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | @prefix schema: . 11 | @base . 12 | 13 | a cube:Cube ; 14 | cube:observationConstraint ; 15 | cube:observationSet . 16 | 17 | cube:observation . 18 | 19 | a cube:Observation ; 20 | cube:observedBy ; 21 | 4.9 ; 22 | ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "measure" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | meta:annotation 51 | [ 52 | a meta:Limit ; 53 | schema:maxValue 97 ; 54 | schema:name "Target 2020+" ; 55 | meta:annotationContext 56 | [ 57 | sh:path ; 58 | sh:minInclusive ; 59 | sh:minExclusive ; 60 | ] ; 61 | ] ; 62 | ] ; 63 | sh:property 64 | [ 65 | a cube:KeyDimension ; 66 | sh:path ; 67 | schema:name "year" ; 68 | sh:minCount 1 ; 69 | sh:maxCount 1 ; 70 | sh:nodeKind sh:IRI ; 71 | ] ; 72 | sh:property 73 | [ 74 | a cube:KeyDimension ; 75 | sh:path ; 76 | schema:name "station" ; 77 | sh:minCount 1 ; 78 | sh:maxCount 1 ; 79 | sh:nodeKind sh:IRI ; 80 | ] ; 81 | . 82 | -------------------------------------------------------------------------------- /test/profile-visualize/valid-data-kinds.ttl: -------------------------------------------------------------------------------- 1 | PREFIX time: 2 | PREFIX qudt: 3 | PREFIX rdf: 4 | PREFIX meta: 5 | PREFIX sh: 6 | PREFIX xsd: 7 | PREFIX dcterms: 8 | PREFIX schema: 9 | PREFIX dcat: 10 | PREFIX cube: 11 | PREFIX ex: 12 | 13 | ex:Cube 14 | a cube:Cube, dcat:Dataset ; 15 | cube:observationSet ; 16 | cube:observationConstraint ; 17 | schema:name "Example cube" ; 18 | schema:publisher ; 19 | schema:creator ; 20 | schema:contributor ; 21 | dcterms:identifier "cube-1234" ; 22 | schema:workExample ; 23 | schema:creativeWorkStatus ; 24 | dcterms:creator ex:John-Doe ; 25 | schema:dateCreated "2020-10-10"^^xsd:date ; 26 | schema:dateModified "2020-10-10"^^xsd:date ; 27 | schema:datePublished "2020-11-11"^^xsd:date ; 28 | schema:contactPoint 29 | [ 30 | schema:name "John Doe" ; 31 | schema:email "john@doe.tech" ; 32 | ] ; 33 | . 34 | 35 | cube:observation . 36 | 37 | a cube:Observation ; 38 | cube:observedBy ; 39 | "WKT" ; 40 | "WKT" ; 41 | . 42 | 43 | a cube:Constraint ; 44 | sh:closed true ; 45 | sh:property 46 | [ 47 | schema:name "GeoShape" ; 48 | sh:path ; 49 | sh:nodeKind sh:Literal ; 50 | meta:dataKind 51 | [ 52 | a schema:GeoShape ; 53 | ] ; 54 | sh:minCount 1 ; 55 | sh:maxCount 1 ; 56 | qudt:scaleType qudt:NominalScale ; 57 | ], 58 | [ 59 | schema:name "GeoCoordinates" ; 60 | sh:path ; 61 | sh:nodeKind sh:Literal ; 62 | meta:dataKind 63 | [ 64 | a schema:GeoCoordinates ; 65 | ] ; 66 | sh:minCount 1 ; 67 | sh:maxCount 1 ; 68 | qudt:scaleType qudt:NominalScale ; 69 | ], 70 | [ 71 | sh:path rdf:type ; 72 | sh:nodeKind sh:IRI ; 73 | sh:minCount 1 ; 74 | sh:maxCount 1 ; 75 | ], 76 | [ 77 | sh:path cube:observedBy ; 78 | sh:nodeKind sh:IRI ; 79 | sh:minCount 1 ; 80 | sh:maxCount 1 ; 81 | ] ; 82 | . 83 | -------------------------------------------------------------------------------- /test/profile-opendataswiss/invalid.missing-identifier.cube.ttl: -------------------------------------------------------------------------------- 1 | PREFIX vcard: 2 | PREFIX xsd: 3 | PREFIX dcterms: 4 | PREFIX schema: 5 | PREFIX dcat: 6 | PREFIX cube: 7 | PREFIX ex: 8 | prefix dcat-theme: 9 | 10 | ex:cube 11 | a cube:Cube, dcat:Dataset ; 12 | dcterms:creator ex:JohnDoe ; 13 | schema:creator ex:JohnDoe ; 14 | schema:publisher ex:Org ; 15 | dcterms:publisher ex:Org ; 16 | cube:observationSet ; 17 | schema:name "Example cube" ; 18 | schema:contributor ex:JohnDoe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "Max Muster, BAFU Datenspezialist" ; 25 | schema:email "max-muster@bafu.admin.ch" ; 26 | ] ; 27 | dcat:contactPoint 28 | [ 29 | a vcard:Organization ; 30 | vcard:fn "Abteilung Lärm BAFU" ; 31 | vcard:hasEmail 32 | ], 33 | [ 34 | a vcard:Individual ; 35 | vcard:fn "Max Muster, BAFU Datenspezialist" ; 36 | vcard:hasEmail 37 | ] ; 38 | #dcterms:identifier "1234@acme-corp" ; 39 | schema:workExample ; 40 | schema:creativeWorkStatus ; 41 | dcterms:title "Example Cube"@en ; 42 | dcterms:description "This is an example cube"@en ; 43 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 44 | dcat:modified "2019-01-01T00:00:00Z"^^xsd:dateTime ; 45 | dcat:theme 46 | dcat-theme:work, 47 | dcat-theme:construction, 48 | dcat-theme:population ; 49 | dcat:landingPage ; 50 | dcat:accrualPeriodicity ; 51 | dcat:distribution 52 | [ 53 | dcterms:title "Example Cube"@en ; 54 | dcat:accessURL ; 55 | dcat:mediaType ; 56 | dcat:rights "NonCommercialAllowed-CommercialAllowed-ReferenceNotRequired" ; 57 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 58 | dcterms:description "This is an example cube"@en ; 59 | ] ; 60 | dcterms:language "de" ; 61 | . 62 | 63 | cube:observation . 64 | 65 | a cube:Observation ; 66 | cube:observedBy ; 67 | 4.9 . 68 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-data-kinds.ttl: -------------------------------------------------------------------------------- 1 | PREFIX time: 2 | PREFIX qudt: 3 | PREFIX rdf: 4 | PREFIX meta: 5 | PREFIX sh: 6 | PREFIX xsd: 7 | PREFIX dcterms: 8 | PREFIX schema: 9 | PREFIX dcat: 10 | PREFIX cube: 11 | PREFIX ex: 12 | 13 | ex:Cube 14 | a cube:Cube, dcat:Dataset ; 15 | cube:observationSet ; 16 | cube:observationConstraint ; 17 | schema:name "Example cube" ; 18 | schema:publisher ; 19 | schema:creator ; 20 | schema:contributor ; 21 | dcterms:identifier "cube-1234" ; 22 | schema:workExample ; 23 | schema:creativeWorkStatus ; 24 | dcterms:creator ex:John-Doe ; 25 | schema:dateCreated "2020-10-10"^^xsd:date ; 26 | schema:dateModified "2020-10-10"^^xsd:date ; 27 | schema:datePublished "2020-11-11"^^xsd:date ; 28 | schema:contactPoint 29 | [ 30 | schema:name "John Doe" ; 31 | schema:email "john@doe.tech" ; 32 | ] ; 33 | . 34 | 35 | cube:observation . 36 | 37 | a cube:Observation ; 38 | cube:observedBy ; 39 | "WKT" ; 40 | "WKT" ; 41 | . 42 | 43 | a cube:Constraint ; 44 | sh:closed true ; 45 | sh:property 46 | [ 47 | schema:name "GeoShape" ; 48 | sh:path ; 49 | sh:nodeKind sh:Literal ; 50 | meta:dataKind 51 | [ 52 | a schema:GeoShape ; 53 | ex:foo "bar" ; 54 | ] ; 55 | sh:minCount 1 ; 56 | sh:maxCount 1 ; 57 | qudt:scaleType qudt:NominalScale ; 58 | ], 59 | [ 60 | schema:name "GeoCoordinates" ; 61 | sh:path ; 62 | sh:nodeKind sh:Literal ; 63 | meta:dataKind 64 | [ 65 | a schema:GeoCoordinates ; 66 | ex:foo "bar" ; 67 | ] ; 68 | sh:minCount 1 ; 69 | sh:maxCount 1 ; 70 | qudt:scaleType qudt:NominalScale ; 71 | ], 72 | [ 73 | sh:path rdf:type ; 74 | sh:nodeKind sh:IRI ; 75 | sh:minCount 1 ; 76 | sh:maxCount 1 ; 77 | ], 78 | [ 79 | sh:path cube:observedBy ; 80 | sh:nodeKind sh:IRI ; 81 | sh:minCount 1 ; 82 | sh:maxCount 1 ; 83 | ] ; 84 | . 85 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-keyDimensions.ttl: -------------------------------------------------------------------------------- 1 | PREFIX ex: 2 | PREFIX dcterms: 3 | @prefix relation: . 4 | @prefix meta: . 5 | @prefix rdf: . 6 | @prefix cube: . 7 | @prefix observation: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | @prefix schema: . 11 | @base . 12 | 13 | a cube:Cube ; 14 | cube:observationConstraint ; 15 | cube:observationSet . 16 | 17 | cube:observation . 18 | 19 | a cube:Observation ; 20 | cube:observedBy ; 21 | 4.9 ; 22 | ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "measure" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | meta:annotation 51 | [ 52 | a meta:Limit ; 53 | schema:minValue 95 ; 54 | meta:annotationContext 55 | [ 56 | sh:path ; 57 | sh:hasValue 10 ; 58 | ] ; 59 | ] , 60 | [ 61 | a meta:Limit ; 62 | schema:maxValue 95 ; 63 | meta:annotationContext 64 | [ 65 | sh:path ; 66 | sh:hasValue ex:Station ; 67 | ] ; 68 | ] ; 69 | ] ; 70 | sh:property 71 | [ 72 | a cube:KeyDimension ; 73 | sh:path ; 74 | schema:name "year" ; 75 | sh:minCount 1 ; 76 | sh:maxCount 1 ; 77 | sh:nodeKind sh:IRI ; 78 | ] ; 79 | sh:property 80 | [ 81 | sh:path ; 82 | schema:name "station" ; 83 | sh:minCount 1 ; 84 | sh:maxCount 1 ; 85 | sh:nodeKind sh:IRI ; 86 | ] ; 87 | . 88 | -------------------------------------------------------------------------------- /trifid/redirect.cjs: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { Readable } = require('stream') 3 | const { fetchBuilder, MemoryCache } = require('node-fetch-cache') 4 | 5 | /** 6 | * Perform some redirections. 7 | * 8 | * @returns {import('express').RequestHandler} 9 | */ 10 | const factory = () => { 11 | const cachedFetch = fetchBuilder.withCache(new MemoryCache({ 12 | ttl: 60 * 60 * 1000, // 1 hour 13 | })) 14 | 15 | return async (req, res, next) => { 16 | const requestPath = req.path 17 | 18 | // ignore health request from the cluster 19 | if (requestPath === '/health') { 20 | return next() 21 | } 22 | 23 | if (requestPath.match(/^\/[^/]+$/)) { 24 | return res.redirect('/') 25 | } 26 | 27 | if (requestPath.match(/^\/meta\/[^/]+$/)) { 28 | return res.redirect('/meta/') 29 | } 30 | 31 | if (requestPath.match(/^\/relation\/[^/]+$/)) { 32 | return res.redirect('/relation/') 33 | } 34 | 35 | // Redirect to a version of a shape (for routes: `/vX.Y.Z/shape/NAME`, `/ref/COMMIT_ID/shape/NAME` and `/latest/shape/NAME`) 36 | const versionMatch = requestPath.match(/^\/((?v[0-9]+\.[0-9]+\.[0-9]+)|(ref\/(?.+))|latest)\/shape\/(?.+)/) 37 | if (versionMatch) { 38 | let versionPath 39 | 40 | const { version, ref, shapePath } = versionMatch?.groups || {} 41 | if (!version && !ref) { 42 | const tags = await cachedFetch('https://api.github.com/repos/zazuko/cube-link/tags').then(async (res) => { 43 | if (!res.ok) { 44 | await res.ejectFromCache() 45 | } 46 | return res.json() 47 | }).catch(() => { 48 | return [] 49 | }) 50 | 51 | // if an issue was identified, we redirect to the main branch as a fallback 52 | if (!tags || !Array.isArray(tags) || tags.length < 1) { 53 | versionPath = 'main' 54 | } else { 55 | versionPath = tags[0].name 56 | } 57 | } else if (ref) { 58 | versionPath = ref 59 | } else if (version) { 60 | versionPath = version 61 | } 62 | 63 | try { 64 | const rawGithub = await fetch(`https://raw.githubusercontent.com/zazuko/cube-link/${versionPath}/validation/${shapePath}.ttl`) 65 | if (rawGithub.ok) { 66 | res.set('Content-Type', 'text/turtle') 67 | } else { 68 | res.status(500) 69 | } 70 | // if the shape does not exist, we return a 404 71 | if (rawGithub.status === 404) { 72 | return res.sendStatus(404) 73 | } 74 | /** @type {any | null} */ 75 | const body = rawGithub.body 76 | if (!rawGithub.body) { 77 | throw new Error('No body') 78 | } 79 | return Readable.fromWeb(body).pipe(res) 80 | } catch (e) { 81 | return res.status(502).send(`Error fetching shape: ${e.message}`) 82 | } 83 | } 84 | 85 | next() 86 | } 87 | } 88 | 89 | module.exports = factory 90 | -------------------------------------------------------------------------------- /test/profile-opendataswiss/invalid.publisherNoClass.ttl: -------------------------------------------------------------------------------- 1 | PREFIX vcard: 2 | PREFIX foaf: 3 | PREFIX xsd: 4 | PREFIX dcterms: 5 | PREFIX schema: 6 | PREFIX dcat: 7 | PREFIX cube: 8 | PREFIX ex: 9 | prefix dcat-theme: 10 | 11 | ex:cube 12 | a cube:Cube, dcat:Dataset ; 13 | dcterms:creator ex:JohnDoe ; 14 | schema:creator ex:JohnDoe ; 15 | schema:publisher ex:Org ; 16 | cube:observationSet ; 17 | schema:name "Example cube" ; 18 | schema:contributor ex:JohnDoe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "Max Muster, BAFU Datenspezialist" ; 25 | schema:email "max-muster@bafu.admin.ch" ; 26 | ] ; 27 | dcterms:publisher 28 | [ 29 | # a foaf:Organization ; 30 | foaf:name "Acme Corp." ; 31 | ] ; 32 | dcat:contactPoint 33 | [ 34 | a vcard:Organization ; 35 | vcard:fn "Abteilung Lärm BAFU" ; 36 | vcard:hasEmail 37 | ], 38 | [ 39 | a vcard:Individual ; 40 | vcard:fn "Max Muster, BAFU Datenspezialist" ; 41 | vcard:hasEmail 42 | ] ; 43 | dcterms:identifier "1234@acme-corp" ; 44 | schema:workExample ; 45 | schema:creativeWorkStatus ; 46 | dcterms:title "Example Cube"@en ; 47 | dcterms:description "This is an example cube"@en ; 48 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 49 | dcat:modified "2019-01-01T00:00:00Z"^^xsd:dateTime ; 50 | dcat:theme 51 | dcat-theme:work, 52 | dcat-theme:construction, 53 | dcat-theme:population ; 54 | dcat:landingPage ; 55 | dcat:accrualPeriodicity ; 56 | dcat:distribution 57 | [ 58 | dcterms:title "Example Cube"@en ; 59 | dcat:accessURL ; 60 | dcat:mediaType ; 61 | dcat:rights "NonCommercialAllowed-CommercialAllowed-ReferenceNotRequired" ; 62 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 63 | dcterms:description "This is an example cube"@en ; 64 | ] ; 65 | dcterms:language "de" ; 66 | . 67 | 68 | cube:observation . 69 | 70 | a cube:Observation ; 71 | cube:observedBy ; 72 | 4.9 . 73 | -------------------------------------------------------------------------------- /test/profile-opendataswiss/valid.publisherBlankNode.ttl: -------------------------------------------------------------------------------- 1 | PREFIX vcard: 2 | PREFIX foaf: 3 | PREFIX xsd: 4 | PREFIX dcterms: 5 | PREFIX schema: 6 | PREFIX dcat: 7 | PREFIX cube: 8 | PREFIX ex: 9 | prefix dcat-theme: 10 | 11 | ex:cube 12 | a cube:Cube, dcat:Dataset ; 13 | dcterms:creator ex:JohnDoe ; 14 | schema:creator ex:JohnDoe ; 15 | schema:publisher ex:Org ; 16 | cube:observationSet ; 17 | schema:name "Example cube" ; 18 | schema:contributor ex:JohnDoe ; 19 | schema:dateCreated "2020-10-10"^^xsd:date ; 20 | schema:dateModified "2020-10-10"^^xsd:date ; 21 | schema:datePublished "2020-11-11"^^xsd:date ; 22 | schema:contactPoint 23 | [ 24 | schema:name "Max Muster, BAFU Datenspezialist" ; 25 | schema:email "max-muster@bafu.admin.ch" ; 26 | ] ; 27 | dcterms:publisher 28 | [ 29 | a foaf:Organization ; 30 | foaf:name "Acme Corp." ; 31 | ] ; 32 | dcat:contactPoint 33 | [ 34 | a vcard:Organization ; 35 | vcard:fn "Abteilung Lärm BAFU" ; 36 | vcard:hasEmail 37 | ], 38 | [ 39 | a vcard:Individual ; 40 | vcard:fn "Max Muster, BAFU Datenspezialist" ; 41 | vcard:hasEmail 42 | ] ; 43 | dcterms:identifier "1234@acme-corp" ; 44 | schema:workExample ; 45 | schema:creativeWorkStatus ; 46 | dcterms:title "Example Cube"@en ; 47 | dcterms:description "This is an example cube"@en ; 48 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 49 | dcat:modified "2019-01-01T00:00:00Z"^^xsd:dateTime ; 50 | dcat:theme 51 | dcat-theme:work, 52 | dcat-theme:construction, 53 | dcat-theme:population ; 54 | dcat:landingPage ; 55 | dcat:accrualPeriodicity ; 56 | dcat:distribution 57 | [ 58 | dcterms:title "Example Cube"@en ; 59 | dcat:accessURL ; 60 | dcat:mediaType ; 61 | dcat:rights "NonCommercialAllowed-CommercialAllowed-ReferenceNotRequired" ; 62 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 63 | dcterms:description "This is an example cube"@en ; 64 | ] ; 65 | dcterms:language "de" ; 66 | . 67 | 68 | cube:observation . 69 | 70 | a cube:Observation ; 71 | cube:observedBy ; 72 | 4.9 . 73 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-temporal.ttl: -------------------------------------------------------------------------------- 1 | PREFIX time: 2 | PREFIX qudt: 3 | PREFIX rdf: 4 | PREFIX meta: 5 | PREFIX sh: 6 | PREFIX xsd: 7 | PREFIX dcterms: 8 | PREFIX schema: 9 | PREFIX dcat: 10 | PREFIX cube: 11 | PREFIX ex: 12 | 13 | ex:Cube 14 | a cube:Cube, dcat:Dataset ; 15 | cube:observationSet ; 16 | cube:observationConstraint ; 17 | schema:name "Example cube" ; 18 | schema:publisher ; 19 | schema:creator ; 20 | schema:contributor ; 21 | dcterms:identifier "cube-1234" ; 22 | schema:workExample ; 23 | schema:creativeWorkStatus ; 24 | dcterms:creator ex:John-Doe ; 25 | schema:dateCreated "2020-10-10"^^xsd:date ; 26 | schema:dateModified "2020-10-10"^^xsd:date ; 27 | schema:datePublished "2020-11-11"^^xsd:date ; 28 | schema:contactPoint 29 | [ 30 | schema:name "John Doe" ; 31 | schema:email "john@doe.tech" ; 32 | ] ; 33 | . 34 | 35 | cube:observation . 36 | 37 | a cube:Observation ; 38 | cube:observedBy ; 39 | "2000"^^xsd:gYear ; 40 | . 41 | 42 | a cube:Constraint ; 43 | sh:closed true ; 44 | sh:property 45 | [ 46 | # no datatype, no time:unitType, not qudt:scaleType qudt:OrdinalScale 47 | schema:name "Year" ; 48 | sh:path ; 49 | sh:nodeKind sh:Literal ; 50 | meta:dataKind 51 | [ 52 | a time:GeneralDateTimeDescription ; 53 | ] ; 54 | sh:minCount 1 ; 55 | sh:maxCount 1 ; 56 | qudt:scaleType qudt:NominalScale ; 57 | ], 58 | [ 59 | # additional properties 60 | schema:name "Year" ; 61 | sh:path ; 62 | sh:nodeKind sh:Literal ; 63 | meta:dataKind 64 | [ 65 | a time:GeneralDateTimeDescription ; 66 | rdf:first "2000"^^xsd:gYear ; 67 | rdf:rest rdf:nil ; 68 | ] ; 69 | sh:minCount 1 ; 70 | sh:maxCount 1 ; 71 | qudt:scaleType qudt:NominalScale ; 72 | ], 73 | [ 74 | sh:path rdf:type ; 75 | sh:nodeKind sh:IRI ; 76 | sh:minCount 1 ; 77 | sh:maxCount 1 ; 78 | ], 79 | [ 80 | sh:path cube:observedBy ; 81 | sh:nodeKind sh:IRI ; 82 | sh:minCount 1 ; 83 | sh:maxCount 1 ; 84 | ] ; 85 | . 86 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-data-kind-unexpected.ttl: -------------------------------------------------------------------------------- 1 | PREFIX qudt: 2 | PREFIX rdf: 3 | PREFIX meta: 4 | PREFIX sh: 5 | PREFIX xsd: 6 | PREFIX dcterms: 7 | PREFIX schema: 8 | PREFIX dcat: 9 | PREFIX cube: 10 | PREFIX ex: 11 | 12 | ex:Cube 13 | a cube:Cube, dcat:Dataset ; 14 | cube:observationSet ; 15 | cube:observationConstraint ; 16 | schema:name "Example cube" ; 17 | schema:publisher ; 18 | schema:creator ; 19 | schema:contributor ; 20 | dcterms:identifier "cube-1234" ; 21 | schema:workExample ; 22 | schema:creativeWorkStatus ; 23 | dcterms:creator ex:John-Doe ; 24 | schema:dateCreated "2020-10-10"^^xsd:date ; 25 | schema:dateModified "2020-10-10"^^xsd:date ; 26 | schema:datePublished "2020-11-11"^^xsd:date ; 27 | schema:contactPoint 28 | [ 29 | schema:name "John Doe" ; 30 | schema:email "john@doe.tech" ; 31 | ] ; 32 | . 33 | 34 | cube:observation . 35 | 36 | a cube:Observation ; 37 | cube:observedBy ; 38 | 4.9 ; 39 | . 40 | 41 | a cube:Constraint ; 42 | sh:closed true ; 43 | sh:property 44 | [ 45 | schema:name "Dimenson 1" ; 46 | sh:path ; 47 | sh:nodeKind sh:IRI ; 48 | meta:dataKind 49 | [ 50 | a schema:Thing ; 51 | ] ; 52 | sh:minCount 1 ; 53 | sh:maxCount 1 ; 54 | qudt:scaleType qudt:NominalScale ; 55 | ], 56 | [ 57 | schema:name "Dimenson 2" ; 58 | sh:path ; 59 | sh:nodeKind sh:IRI ; 60 | sh:minCount 1 ; 61 | sh:maxCount 1 ; 62 | meta:dataKind 63 | [ 64 | ] ; 65 | qudt:scaleType qudt:NominalScale ; 66 | ], 67 | [ 68 | schema:name "Measure" ; 69 | sh:path ; 70 | sh:datatype xsd:decimal ; 71 | sh:nodeKind sh:Literal ; 72 | sh:minCount 1 ; 73 | sh:maxCount 1 ; 74 | qudt:scaleType qudt:NominalScale ; 75 | ], 76 | [ 77 | sh:path rdf:type ; 78 | sh:nodeKind sh:IRI ; 79 | sh:minCount 1 ; 80 | sh:maxCount 1 ; 81 | ], 82 | [ 83 | sh:path cube:observedBy ; 84 | sh:nodeKind sh:IRI ; 85 | sh:minCount 1 ; 86 | sh:maxCount 1 ; 87 | ] ; 88 | . 89 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # cube-link 2 | 3 | ## 0.2.3 4 | 5 | ### Patch Changes 6 | 7 | - a41f716: Improve validation of `meta:dimensionRelation`: 8 | 9 | 1. Check that upper/lower bound has at most one `dcterms:type` 10 | 2. Check that `meta:relatesTo` is actually a dimension 11 | 12 | - 71c3d52: Add an informative section about using [Time Ontology in OWL](https://www.w3.org/TR/owl-time/) for temporal dimensions 13 | - 46133ba: Only use `qudt:hasUnit` in documentation (instead of deprecated `qudt:unit`) 14 | - 641d841: Adding dimension annotations (`meta:annotation`) re https://gitlab.ldbar.ch/bafu/visualize/-/issues/542 15 | - de24a37: Relation vocabulary: added relation types for asymmetrical margin of error 16 | 17 | ## 0.2.2 18 | 19 | ### Patch Changes 20 | 21 | - d289758: `profile-visualize`: allowed temporal dimensions (`meta:dataKind a time:GeneralDateTimeDescription`) to have ordinal scale type 22 | - 615b1c2: Corrected the URLs in profile-visualize 23 | - 214b479: `standalone-cube-constraint`: `schema:dateModified` now allows both `xsd:dateTime` in addition to `xsd:date` (closes #166) 24 | - 214b479: `profile-visualize`: added `sh:class` to `meta:dataKind` shapes (closes #167) 25 | - 985383e: `standalone-cube-constraint`: Lower severity of `schema:publisher`, `schema:creator` and `schema:contributor` to warning 26 | - 818acbd: `profile-visualize`: Correct wording of scale type constraint 27 | - 5bad04f: `standalone-cube-constraint`: lowered the severity of missing observation to `sh:Warning` (re #168) 28 | 29 | ## 0.2.1 30 | 31 | ### Patch Changes 32 | 33 | - 9b04f0f: Fix Trifid instance so that it can work with a CommonJS module 34 | 35 | ## 0.2.0 36 | 37 | ### Minor Changes 38 | 39 | - 1c2205e: Include `standalone-constraint-constraint` in `standalone-cube-constraint` 40 | 41 | ### Patch Changes 42 | 43 | - 3f40fd5: Validating RDF Lists should now work with long lists of any size 44 | - 4645d09: Visualize validation profile (closes #114) 45 | - 9faf4fb: Validation profiles: switch to `sh:xone` where appropriate 46 | - d7d3256: Added validation profile for opendata.swiss (closes #118) 47 | 48 | ## 0.1.5 49 | 50 | ### Patch Changes 51 | 52 | - dd52484: Documentation of new cube validation tools 53 | 54 | ## 0.1.4 55 | 56 | ### Patch Changes 57 | 58 | - 81b209f: `standalone-cube-constraint`: Allow `schema:contactPoint` to be a blank node 59 | - 9d28874: Support git refs when serving shapes from Trifid 60 | 61 | ## 0.1.3 62 | 63 | ### Patch Changes 64 | 65 | - 86a40d7: In the CI, make sure to pull the Git repository with the token, to make sure it is able to trigger tags GitHub Actions workflows 66 | - 7777e94: Generate Docker tags and labels using docker/metadata-action 67 | 68 | ## 0.1.2 69 | 70 | ### Patch Changes 71 | 72 | - 6b78238: Bumping version only to trigger CI 73 | 74 | ## 0.1.1 75 | 76 | ### Patch Changes 77 | 78 | - 09e2f3d: Forward profiles directly from GitHub 79 | 80 | ## 0.1.0 81 | 82 | ### Minor Changes 83 | 84 | - 6d65dca: Adjust shape base to match how they are deployed (re #94) 85 | 86 | ### Patch Changes 87 | 88 | - a38baff: Fixes the problem that validation script did not correctly target cube observations 89 | -------------------------------------------------------------------------------- /test/profile-opendataswiss/valid.ttl: -------------------------------------------------------------------------------- 1 | PREFIX vcard: 2 | PREFIX xsd: 3 | PREFIX dcterms: 4 | PREFIX schema: 5 | PREFIX dcat: 6 | PREFIX cube: 7 | PREFIX ex: 8 | prefix dcat-theme: 9 | 10 | ex:cube 11 | a cube:Cube, dcat:Dataset ; 12 | cube:observationSet ; 13 | schema:name "Example cube" ; 14 | schema:publisher ex:JohnDoe ; 15 | schema:creator ex:JohnDoe ; 16 | schema:contributor ex:JohnDoe ; 17 | schema:dateCreated "2020-10-10"^^xsd:date ; 18 | schema:dateModified "2020-10-10"^^xsd:date ; 19 | schema:datePublished "2020-11-11"^^xsd:date ; 20 | schema:contactPoint 21 | [ 22 | schema:name "Max Muster, BAFU Datenspezialist" ; 23 | schema:email "max-muster@bafu.admin.ch" ; 24 | ] ; 25 | dcterms:creator ex:JohnDoe ; 26 | schema:creator ex:JohnDoe ; 27 | schema:publisher ex:Org ; 28 | dcterms:publisher ex:Org ; 29 | dcat:contactPoint 30 | [ 31 | a vcard:Organization ; 32 | vcard:fn "Abteilung Lärm BAFU" ; 33 | vcard:hasEmail 34 | ], 35 | [ 36 | a vcard:Individual ; 37 | vcard:fn "Max Muster, BAFU Datenspezialist" ; 38 | vcard:hasEmail 39 | ] ; 40 | dcterms:identifier "1234@acme-corp" ; 41 | schema:workExample ; 42 | schema:creativeWorkStatus ; 43 | dcterms:title "Example Cube"@en ; 44 | dcterms:description "This is an example cube"@en ; 45 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 46 | dcat:modified "2019-01-01T00:00:00Z"^^xsd:dateTime ; 47 | dcat:theme 48 | dcat-theme:work, 49 | dcat-theme:construction, 50 | dcat-theme:population ; 51 | dcat:landingPage ; 52 | dcat:accrualPeriodicity ; 53 | dcat:distribution 54 | [ 55 | dcterms:title "Example Cube"@en ; 56 | dcat:accessURL ; 57 | dcat:mediaType ; 58 | dcat:rights "NonCommercialAllowed-CommercialAllowed-ReferenceNotRequired" ; 59 | dcat:issued "2019-01-01T00:00:00Z"^^xsd:dateTime ; 60 | dcterms:description "This is an example cube"@en ; 61 | ] ; 62 | dcterms:language "de" ; 63 | dcat:temporal 64 | [ 65 | a dcat:PeriodOfTime ; 66 | schema:startDate "1905-03-01"^^xsd:date ; 67 | schema:endDate "2013-01-05"^^xsd:date 68 | ] ; 69 | . 70 | 71 | cube:observation . 72 | 73 | a cube:Observation ; 74 | cube:observedBy ; 75 | 4.9 . 76 | -------------------------------------------------------------------------------- /test/profile-visualize/invalid-scale-types.ttl.approved.txt: -------------------------------------------------------------------------------- 1 | @prefix sh: . 2 | @prefix rdf: . 3 | @prefix rdfs: . 4 | @prefix xsd: . 5 | @prefix schema: . 6 | @prefix cube: . 7 | 8 | _:report a sh:ValidationReport ; 9 | sh:result [ 10 | rdf:type sh:ValidationResult ; 11 | sh:resultSeverity sh:Violation ; 12 | sh:sourceConstraintComponent sh:NodeConstraintComponent ; 13 | sh:sourceShape [ 14 | sh:path cube:observationConstraint ; 15 | sh:maxCount 1 ; 16 | sh:minCount 1 ; 17 | sh:node ; 18 | ] ; 19 | sh:focusNode ; 20 | sh:resultPath cube:observationConstraint ; 21 | sh:value ; 22 | sh:resultMessage "Value does not have shape " ; 23 | sh:detail [ 24 | rdf:type sh:ValidationResult ; 25 | sh:resultSeverity sh:Violation ; 26 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 27 | sh:sourceShape _:b644 ; 28 | sh:focusNode ; 29 | sh:resultPath sh:property ; 30 | sh:value _:b2 ; 31 | sh:resultMessage "Dimension must have exactly one scaleType: qudt:IntervalScale, qudt:NominalScale, qudt:RatioScale, or qudt:OrdinalScale" ; 32 | ], [ 33 | rdf:type sh:ValidationResult ; 34 | sh:resultSeverity sh:Violation ; 35 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 36 | sh:sourceShape _:b644 ; 37 | sh:focusNode ; 38 | sh:resultPath sh:property ; 39 | sh:value _:b3 ; 40 | sh:resultMessage "Dimension must have exactly one scaleType: qudt:IntervalScale, qudt:NominalScale, qudt:RatioScale, or qudt:OrdinalScale" ; 41 | ] ; 42 | ], [ 43 | rdf:type sh:ValidationResult ; 44 | sh:resultSeverity sh:Violation ; 45 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 46 | sh:sourceShape _:b644 ; 47 | sh:focusNode ; 48 | sh:resultPath sh:property ; 49 | sh:value _:b2 ; 50 | sh:resultMessage "Dimension must have exactly one scaleType: qudt:IntervalScale, qudt:NominalScale, qudt:RatioScale, or qudt:OrdinalScale" ; 51 | ], [ 52 | rdf:type sh:ValidationResult ; 53 | sh:resultSeverity sh:Violation ; 54 | sh:sourceConstraintComponent sh:OrConstraintComponent ; 55 | sh:sourceShape _:b644 ; 56 | sh:focusNode ; 57 | sh:resultPath sh:property ; 58 | sh:value _:b3 ; 59 | sh:resultMessage "Dimension must have exactly one scaleType: qudt:IntervalScale, qudt:NominalScale, qudt:RatioScale, or qudt:OrdinalScale" ; 60 | ] ; 61 | sh:conforms false . 62 | 63 | _:b644 sh:path sh:property ; 64 | sh:or ( 65 | [ 66 | sh:node ; 67 | ] 68 | [ 69 | sh:node ; 70 | ] 71 | ) ; 72 | sh:message "Dimension must have exactly one scaleType: qudt:IntervalScale, qudt:NominalScale, qudt:RatioScale, or qudt:OrdinalScale" . 73 | -------------------------------------------------------------------------------- /meta/meta.ttl: -------------------------------------------------------------------------------- 1 | PREFIX rdf: 2 | PREFIX rdfs: 3 | PREFIX cube: 4 | PREFIX meta: 5 | PREFIX schema: 6 | 7 | meta:dimensionRelation a rdfs:Property; 8 | rdfs:subPropertyOf meta:relatesTo; 9 | rdfs:label "dimension relation"; 10 | rdfs:comment "A meta:dimensionRelation property is used to express the relation of this dimension in related to other dimension, examples are Deviation and StandardError"; 11 | . 12 | 13 | meta:Hierarchy a rdfs:Class; 14 | rdfs:label "Hierarchy"; 15 | rdfs:comment "A hierarchy is defined and can be named schema:name. This can help user interfaces to allow a selection in case of multiple hierarchies."; 16 | . 17 | 18 | meta:Relation a rdfs:Class; 19 | rdfs:label "Relation"; 20 | rdfs:comment "A meta:Relation resource is used to express the relation or hiarchy between different dimensions, the nature of the relationship is determined by the properties used. A meta:Relation is linked to an observation through a meta:relation property. "; 21 | . 22 | 23 | meta:SharedDimension a rdfs:Class; 24 | rdfs:label "Shared Dimension"; 25 | rdfs:comment "A schema:DefinedTermSet which holds the Resources used for a shared dimension." 26 | . 27 | 28 | meta:dataKind a rdf:Property; 29 | rdfs:label "data Kind"; 30 | rdfs:comment "The kind or variety of the data in a dimension. Often schema:GeoCoordinates and schema:GeoShape for Spatial and time:GeneralTimeDescription for Temporal is used."; 31 | . 32 | 33 | meta:hierarchyRoot a rdf:Property; 34 | rdfs:label "hierarchy root"; 35 | rdfs:comment "This property is mandatory and defines one or multiple root concepts. It is the starting point of the hierarchy which is then defined through a cascade of levels where the use of shacl:path is connecting the concepts. The simplest case is only two levels, the root level and how they are connected to the observations in the dimension. If there are multiple levels they are nested with meta:nextInHierarchy."; 36 | . 37 | 38 | meta:inHierarchy a rdf:Property; 39 | rdfs:label "in hierarchy"; 40 | rdfs:comment "This property is used on a Dimension Constraint to express a hierarchy implemented in such. It is possible to add multiple different hierarchies on one dimension. A hierarchy must have at least one meta:hierarchyRoot."; 41 | . 42 | 43 | meta:nextInHierarchy a rdf:Property; 44 | rdfs:label "next in hierarchy"; 45 | rdfs:comment "With meta:nextInHierarchy it is possible to "; 46 | . 47 | 48 | meta:relatesTo a rdf:Property; 49 | rdfs:range meta:Relation; 50 | rdfs:label "relates to"; 51 | rdfs:comment "This property is used on a Dimension Constraint to express a relation with other properties through a meta:Relation instance, the nature of this relationship is determined by the properties used on the instance. "; 52 | . 53 | 54 | meta:applicationIgnores a rdf:Property; 55 | rdfs:label "Ignored by Application"; 56 | rdfs:comment "This property is used on a Dimension Constraint to be ignored by application specified. (It shall use the same objects as used on `schema:workExample`.)"; 57 | . 58 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/invalid.annotation-tooManyValues.ttl: -------------------------------------------------------------------------------- 1 | PREFIX ex: 2 | PREFIX dcterms: 3 | @prefix relation: . 4 | @prefix meta: . 5 | @prefix rdf: . 6 | @prefix cube: . 7 | @prefix observation: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | @prefix schema: . 11 | @base . 12 | 13 | a cube:Cube ; 14 | cube:observationConstraint ; 15 | cube:observationSet . 16 | 17 | cube:observation . 18 | 19 | a cube:Observation ; 20 | cube:observedBy ; 21 | 4.9 ; 22 | ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "measure" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | meta:annotation 51 | [ 52 | a meta:Limit ; 53 | schema:name "Target 2020+" ; 54 | schema:minValue 10 ; 55 | schema:minValue 20 ; 56 | meta:annotationContext 57 | [ 58 | sh:path ; 59 | sh:minInclusive ; 60 | ] ; 61 | ], 62 | [ 63 | a meta:Limit ; 64 | schema:name "Target 2025+" ; 65 | schema:maxValue 10 ; 66 | schema:maxValue 20 ; 67 | meta:annotationContext 68 | [ 69 | sh:path ; 70 | sh:minInclusive ; 71 | ] ; 72 | ] ; 73 | ] ; 74 | sh:property 75 | [ 76 | a cube:KeyDimension ; 77 | sh:path ; 78 | schema:name "year" ; 79 | sh:minCount 1 ; 80 | sh:maxCount 1 ; 81 | sh:nodeKind sh:IRI ; 82 | ] ; 83 | sh:property 84 | [ 85 | a cube:KeyDimension ; 86 | sh:path ; 87 | schema:name "station" ; 88 | sh:minCount 1 ; 89 | sh:maxCount 1 ; 90 | sh:nodeKind sh:IRI ; 91 | ] ; 92 | . 93 | -------------------------------------------------------------------------------- /documentation/constraints.md: -------------------------------------------------------------------------------- 1 | # Cube Schema: Constraints 2 | 3 | From a pure publishing point of view and according to the [Open World Model](http://linked-data-training.zazuko.com/Ontologies/index.html#14), publishing observations using the core _Cube Schema_ is enough. However, in reality, one might want to use the data for other purposes as well, like visualizing it in web applications and other publications. To be useful, such tools might require additional metadata and cubes that adhere to certain constraints. 4 | 5 | _Cube Schema_ supports attaching a "constraint" to a cube. The constraints themselves are expressed using the [[[shacl]]] 6 | 7 | Providing constraints for a cube facilitates the documentation, interpretation, and validation of the cube for tooling and libraries. There is only one constraint per cube allowed, this results in a very low overhead for the documentation, the cube and observations do not need any documentation on the data level. 8 | 9 | 10 | 11 | It is up to the consumer of the data to decide how the constraint is used. If provided, it should be possible to validate the observations in the cube with it. 12 | 13 | ## Constraints 14 | 15 | ### Cube Constraints {#cubeconstraints} 16 | 17 | A [cube:Constraint](#Constraint) is also a `sh:NodeShape`. [[[shacl]]] is used to restrict the cube to a particular structure. The Constraint presented in this section can be used to validate all `Observation`s in the cube. 18 | 19 | If additional restrictions are needed, additional restrictions expressed as [[[shacl]]] can be provided. 20 | 21 | The following snippet defines a new constraint, it applies to all `cube:Observation`: 22 | 23 | 36 | 37 | ### Dimension Constraints {#dimensionconstraints} 38 | 39 | Dimension Constraints are linked to Cube Constraints through the `sh:property` property, the Dimension constraints uses the [[[shacl]]] vocabulary to express the constraints for the specific dimension. 40 | 41 | #### sh:path 42 | 43 | The dimension/property is referenced using `sh:path`. The value of the path must be a single value and not an RDF list. 44 | 45 | #### additional constraints 46 | Additional constraints can be added according to the SHACL specification, for example, data types, min/max values, etc. 47 | The following snippet defines a dimension (property) `dc:date` with a literal value (`xsd:dateTime`): 48 | 49 | 61 | 62 | #### Usage of code lists 63 | 64 | Dimensions that point to objects like code lists (i.e taxonomies represented in vocabularies like [[[skos-primer]]]) can be expressed as well: 65 | 66 | 78 | 79 | Dimensions can have further types, which are not defined by this vocabulary to support other Dimensions (e.g. Precision, Statistical Measures) or for additional Attributes to filter on, which are not part of the key to defining a [`cube:KeyDimension`](#KeyDimension). 80 | 81 | -------------------------------------------------------------------------------- /test/standalone-constraint-constraint/valid.annotation.ttl: -------------------------------------------------------------------------------- 1 | PREFIX ex: 2 | PREFIX dcterms: 3 | @prefix relation: . 4 | @prefix meta: . 5 | @prefix rdf: . 6 | @prefix cube: . 7 | @prefix observation: . 8 | @prefix sh: . 9 | @prefix xsd: . 10 | @prefix schema: . 11 | @base . 12 | 13 | a cube:Cube ; 14 | cube:observationConstraint ; 15 | cube:observationSet . 16 | 17 | cube:observation . 18 | 19 | a cube:Observation ; 20 | cube:observedBy ; 21 | 4.9 ; 22 | ; 23 | . 24 | 25 | a cube:Constraint ; 26 | sh:targetClass cube:Observation ; 27 | sh:closed true ; 28 | sh:property 29 | [ 30 | sh:path rdf:type ; 31 | sh:nodeKind sh:IRI ; 32 | sh:minCount 1 ; 33 | sh:maxCount 1 34 | ] ; 35 | sh:property 36 | [ 37 | sh:path cube:observedBy ; ; 38 | sh:nodeKind sh:IRI ; 39 | sh:minCount 1 ; 40 | sh:maxCount 1 41 | ] ; 42 | sh:property 43 | [ 44 | a cube:MeasureDimension ; 45 | sh:datatype xsd:decimal ; 46 | sh:path ; 47 | schema:name "measure" ; 48 | sh:minCount 1 ; 49 | sh:maxCount 1 ; 50 | meta:annotation 51 | [ 52 | a meta:Limit ; 53 | schema:maxValue 95 ; 54 | schema:name "Target 2020" ; 55 | meta:annotationContext 56 | [ 57 | sh:path ; 58 | sh:hasValue ; 59 | ] ; 60 | ] , 61 | [ 62 | a meta:Limit ; 63 | schema:maxValue 97 ; 64 | schema:name "Target 2025+" ; 65 | meta:annotationContext 66 | [ 67 | sh:path ; 68 | sh:minInclusive ; 69 | ] , 70 | [ 71 | sh:path ; 72 | sh:in ( ex:stationX ex:stationY ) ; 73 | ] ; 74 | ] , 75 | [ 76 | a meta:Limit ; 77 | schema:maxValue 90 ; 78 | schema:minValue 80 ; 79 | schema:name "Accepted range, pre 2020 for station X" ; 80 | meta:annotationContext 81 | [ 82 | sh:path ; 83 | sh:maxExclusive "2020"^^xsd:gYear ; 84 | ] , 85 | [ 86 | sh:path ; 87 | sh:hasValue ex:stationX ; 88 | ] ; 89 | ] ; 90 | ] ; 91 | sh:property 92 | [ 93 | a cube:KeyDimension ; 94 | sh:path ; 95 | schema:name "year" ; 96 | sh:minCount 1 ; 97 | sh:maxCount 1 ; 98 | sh:nodeKind sh:IRI ; 99 | ] ; 100 | sh:property 101 | [ 102 | a cube:KeyDimension ; 103 | sh:path ; 104 | schema:name "station" ; 105 | sh:minCount 1 ; 106 | sh:maxCount 1 ; 107 | sh:nodeKind sh:IRI ; 108 | ] ; 109 | . 110 | -------------------------------------------------------------------------------- /trifid/config-base.json: -------------------------------------------------------------------------------- 1 | { 2 | "listener": { 3 | "port": 8080 4 | }, 5 | "express": { 6 | "trust proxy": "loopback", 7 | "x-powered-by": null 8 | }, 9 | "patchHeaders": { 10 | "root": { 11 | "static": { 12 | "Access-Control-Allow-Origin": "*", 13 | "Cache-Control": "public, max-age=120", 14 | "Vary": "Accept" 15 | } 16 | } 17 | }, 18 | "staticFiles": { 19 | "trifidFiles": { 20 | "path": "/", 21 | "folder": "cwd:public" 22 | }, 23 | "rendererFiles": { 24 | "path": "/", 25 | "folder": "cwd:node_modules/trifid-renderer-simple/public" 26 | } 27 | }, 28 | "mediaTypeUrl": { 29 | "root": { 30 | "formats": { 31 | "json": "application/json", 32 | "jsonld": "application/ld+json", 33 | "nt": "application/n-triples", 34 | "ttl": "text/turtle", 35 | "xml": "application/rdf+xml" 36 | } 37 | } 38 | }, 39 | "rewrite": { 40 | "root": { 41 | "mediaTypes": [ 42 | "application/html", 43 | "application/json", 44 | "application/ld+json", 45 | "application/n-triples", 46 | "application/rdf+xml", 47 | "application/xhtml+xml", 48 | "text/html", 49 | "text/turtle" 50 | ], 51 | "rewriteContent": true, 52 | "rewriteHeaders": true 53 | } 54 | }, 55 | "renderer": { 56 | "root": { 57 | "module": "trifid-renderer-simple", 58 | "template": "trifid:views/index.html", 59 | "templateError": "trifid:views/error.html", 60 | "alternativeMediaTypes": [ 61 | "application/ld+json", 62 | "application/n-triples", 63 | "application/rdf+xml", 64 | "text/turtle" 65 | ] 66 | } 67 | }, 68 | "staticViews": { 69 | "/": "trifid:views/home.html", 70 | "/health": "trifid:views/health.html" 71 | }, 72 | "breakDown": { 73 | "rewrite": {}, 74 | "rewrite.root": {}, 75 | "rewrite.root.url": "datasetBaseUrl" 76 | }, 77 | "plugins": { 78 | "templateEngine": { 79 | "priority": 10, 80 | "module": "trifid-plugin-cotton-candy" 81 | }, 82 | "requestLogger": { 83 | "priority": 20, 84 | "module": "trifid-core:./plugins/middleware", 85 | "middleware": "morgan", 86 | "params": [ 87 | "combined" 88 | ] 89 | }, 90 | "patchHeaders": { 91 | "priority": 40, 92 | "module": "trifid-core:./plugins/middleware", 93 | "middleware": "patch-headers" 94 | }, 95 | "redirects": { 96 | "priority": 50, 97 | "module": "trifid-core:./plugins/redirects" 98 | }, 99 | "staticFiles": { 100 | "priority": 60, 101 | "module": "trifid-core:./plugins/static-files" 102 | }, 103 | "mediaTypeUrl": { 104 | "priority": 70, 105 | "module": "trifid-core:./plugins/middleware", 106 | "middleware": "format-to-accept" 107 | }, 108 | "rewrite": { 109 | "priority": 80, 110 | "module": "trifid-core:./plugins/middleware", 111 | "middleware": "camouflage-rewrite" 112 | }, 113 | "iri": { 114 | "priority": 90, 115 | "module": "trifid-core:./plugins/iri" 116 | }, 117 | "locals": { 118 | "priority": 100, 119 | "module": "trifid-core:./plugins/locals" 120 | }, 121 | "markdown": { 122 | "priority": 110, 123 | "module": "trifid-plugin-markdown" 124 | }, 125 | "staticViews": { 126 | "priority": 120, 127 | "module": "trifid-core:./plugins/static-views" 128 | }, 129 | "renderer": { 130 | "priority": 130, 131 | "module": "trifid-plugin-renderer" 132 | }, 133 | "hydraBox": { 134 | "priority": 140, 135 | "module": "trifid-plugin-hydra-box" 136 | }, 137 | "handler": { 138 | "priority": 150, 139 | "module": "trifid-core:./plugins/handler" 140 | }, 141 | "headers-fix": { 142 | "priority": 160, 143 | "module": "trifid-core:./plugins/headers-fix" 144 | }, 145 | "error-handler": { 146 | "priority": 170, 147 | "module": "trifid-core:./plugins/error-handler" 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cube Schema 2 | 3 | In this repository we develop the *Cube Schema* model. 4 | 5 | `@prefix cube: .` 6 | 7 | DRAFT: https://zazuko.github.io/cube-link/ 8 | 9 | ## Validation shapes 10 | 11 | The [validation](validation) directory contains various SHACL Shapes which can be used to ensure the correctness of datasets, cubes, hierarchies, and other. 12 | 13 | They can be retrieved from the web using a URI in the form of `https://cube.link/{VERSION}/shape/{PROFILE}`, where the `{PROFILE}` variable is replaced with any of the shape documents (without `.ttl`) and the `{VERSION}` variable is replaced with any [tag name](https://github.com/zazuko/cube-link/tags) or the word `latest`. 14 | It is recommended to always use a specific version to avoid breaking changes. 15 | 16 | For example, to get version 0.0.4 of `standalone-cube-constraint.ttl`, fetch https://cube.link/v0.0.4/shape/standalone-cube-constraint . 17 | 18 | Otherwise, to get the latest version, fetch https://cube.link/latest/shape/standalone-cube-constraint instead. 19 | 20 | Finally, it is possible to request shapes from a branch or specific commit by building the URI as `/ref/{REF}/shape/...`. 21 | For example, to get the `standalone-cube-constraint` shape from the `main` branch, fetch https://cube.link/ref/main/shape/standalone-cube-constraint and to get it from the commit `a1b2c3d4e5f6`, fetch https://cube.link/ref/a1b2c3d4e5f6/shape/standalone-cube-constraint . 22 | 23 | ### Published profiles 24 | 25 | | Profile | Description | 26 | |-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------| 27 | | [standalone-cube-constraint](validation/standalone-cube-constraint.ttl) | Standard cube profile with minimal metadata | 28 | | [standalone-constraint-constraint](validation/standalone-constraint-constraint.ttl) | Minimal dimensions metadata. Included in `standalone-cube-constraint` | 29 | | [profile-opendataswiss](validation/profile-opendataswiss.ttl) | Cube metadata profile which follows the [Opendata.swiss Handbook](https://handbook.opendata.swiss/). Extends `standalone-cube-constraint` | 30 | | [profile-opendataswiss-lindas](validation/profile-opendataswiss-lindas.ttl) | Cube metadata for cubes published to Opendata.swiss from Lindas | 31 | | [profile-visualize](validation/profile-visualize.ttl) | Cube metadata for cubes published to [Visualize](https://visualize.admin.ch/) | 32 | | [basic-cube-constraint](validation/basic-cube-constraint.ttl) | Minimum cube. This typically isn't used directly | 33 | 34 | ## How to Contribute 35 | 36 | Please open [Issues](https://github.com/zazuko/cube-link/issues) on this repository or provide PRs for contributions. 37 | 38 | ## Testing 39 | 40 | Automatic tests exist to validate cube constraints against maintained profiles, as well as tests 41 | checking the observation against given cube constraints. 42 | 43 | ### Profile tests 44 | 45 | ```bash 46 | ./test/check-metadata.sh --profile=$PROFILE 47 | ``` 48 | 49 | `$PROFILE` must be the name of one of the profiles in the `validation` directory (without extension). 50 | 51 | Test cases are turtle file under `test/$PROFILE` directory. 52 | 53 | It is also possible to run only a subset of tests by providing a `--filter` argument. This argument 54 | is a regular expression that is matched against the file name. For example, to run only `basic-cube-constraint` 55 | tests which include the word "undefined": 56 | 57 | ```bash 58 | ./test/check-metadata.sh --profile=basic-cube-constraint --filter=undefined 59 | ``` 60 | 61 | ### Observation tests 62 | 63 | ```bash 64 | ./test/check-observations.sh 65 | ``` 66 | 67 | Test cases are turtle file under `test/observations` directory. 68 | 69 | This script also supports a `--filter` argument. 70 | 71 | Both scripts allow a `--approved` flag to force-approve the current output as valid in case of differences. 72 | --------------------------------------------------------------------------------