Closed rapw3k closed 3 years ago
Dear Raul,
great to see that we can get in touch here as well. In our projects, we appended parts of the ontology to the data graphs to inform the shacl validator about these additional properties.
Example (before):
geo:SubGeometry rdf:subClassOf geo:Geometry
[...] sh:path geo:hasGeometry; sh:class geo:Geometry
my:InstanceA [...] geo:SubGeometry
Example (after, adding the ontology content to the data graph):
geo:SubGeometry rdf:subClassOf geo:Geometry
[...] sh:path geo:hasGeometry; sh:class geo:Geometry
my:InstanceA [...] geo:SubGeometry . geo:SubGeometry rdf:subClassOf geo:Geometry
Hope this helps!
Thank you @JohannesLipp ! Yes, that works. However, this is not really practical. It would be much better that the validator would support at least class inferencing. Perhaps this would be some feature/extension for the future ? cu!
The validator (and the standard) does support subclass inferencing, based on rdfs:subClassOf triples found in the data graph. Without such triples there is no way for it to know that SubGeometry is a subclass of Geometry. Is your issue that you find adding those subClassOf triples impractical because they are only in the Ontology? What we do all the time is to use owl:imports, e.g.
ex:DataGraph owl:imports ex:Ontology
and then build a MultiUnion Graph in jena with all these graphs merged into a single virtual graph. This also means you can have
ex:ShapesGraph owl:imports ex:Ontology
which makes it easier to "attach" constraints to the classes.
Thanks @HolgerKnublauch; however that does not look so straightforward to me as you say. Perhaps I am missing something though.
In our case the data graph is encoded as a jsonld that points to the context derived from target ontology, see partial example below :
{
"@graph" : [ {
"@id" : "http://www.w3id.org/afarcloud/pCoord?lat=45.75&long=4.85",
"@type" : "Point",
"asWKT" : "POINT(45.75 4.85)"
},
{
"@id" : "http://www.w3id.org/afarcloud/poi?lat=45.75&long=4.85",
"@type" : "Feature",
"hasGeometry" : "http://www.w3id.org/afarcloud/pCoord?lat=45.75&long=4.85"
}, {
"@id" : "urn:afc:AS09:cropsManagement:TEC:soil:sen0022",
"@type" : [ "SoilSensor", "AfarcloudSensors" ]
}, {
"@id" : "urn:afc:AS09:sen0022:obs-1514810172",
"@type" : "Observation",
"hasFeatureOfInterest" : "http://www.w3id.org/afarcloud/poi?lat=45.75&long=4.85",
"hasResult" : "urn:afc:AS09:sen0022:obs-1514810172/q1",
"madeBySensor" : "urn:afc:AS09:cropsManagement:TEC:soil:sen0022",
"observedProperty" : "http://www.w3id.org/afarcloud/soil_temperature",
"resultTime" : "2018-01-01T12:36:12Z"
}, {
"@id" : "urn:afc:AS09:sen0022:obs-1514810172/q1",
"@type" : "QuantityValue",
"identifier" : "q1",
"numericValue" : "0.27121272683143616",
"unit" : "http://qudt.org/vocab/unit/DEG_C"
} ],
"@context" : [ "https://w3id.org/demeter/agri-context.jsonld", {
"qudt-unit" : "http://qudt.org/vocab/unit/"
} ]
}
Our SHACL is: https://raw.githubusercontent.com/rapw3k/DEMETER/master/models/SHACL/demeterAgriProfile-SHACL.ttl
The error validating the input with the SHACL is:
[ a sh:ValidationReport ;
sh:conforms false ;
sh:result [ a sh:ValidationResult ;
sh:focusNode <http://www.w3id.org/afarcloud/poi?lat=45.75&long=4.85> ;
sh:resultMessage "ClassConstraint[<http://www.opengis.net/ont/geosparql#Geometry>]: Expected class :<http://www.opengis.net/ont/geosparql#Geometry> for <http://www.w3id.org/afarcloud/pCoord?lat=45.75&long=4.85>" ;
sh:resultPath geo:hasGeometry ;
sh:resultSeverity sh:Violation ;
sh:sourceConstraintComponent sh:ClassConstraintComponent ;
sh:sourceShape <https://astrea.linkeddata.es/shapes#3f6891594ac2d163a004bec00f8db48a> ;
sh:value <http://www.w3id.org/afarcloud/pCoord?lat=45.75&long=4.85>
]
] .
I tried the following: 1.--- import in the SHACL the target ontology. Result: no change
@base <https://w3id.org/demeter/shacl> .
<https://w3id.org/demeter/shacl>
rdf:type owl:Ontology ;
owl:imports <https://w3id.org/demeter/crossDomain> .
2.--- I tried adding directly the statement in SHACL. Result: no change
sf:Point rdfs:subClassOf geo:Geometry .
3.--- I tried adding import statement in data graph, although not sure this is correct as we use context already. Result: no change
"http://www.w3.org/2002/07/owl#imports":[
{
"@id":"https://w3id.org/demeter/crossDomain"
}
]
4.--- I tried adding directly the statement in data graph. Result: it works. However as I said this is impractical.
{
"@id": "http://www.opengis.net/ont/sf#Point",
"http://www.w3.org/2000/01/rdf-schema#subClassOf": {"@id":"http://www.opengis.net/ont/geosparql#Geometry"}
}
Any idea, or something I am missing?
How do you invoke this? Just adding owl:imports statements by itself doesn't do anything unless the calling code also follows those graphs and knows where to find them.
I am not fluent in JSON-LD and it's too easy to get different triples than we believe. Could you cast this to Turtle so that we can be sure we are talking about the same data, namespaces etc?
In order to do the validation, I am using https://jena.apache.org/documentation/shacl/ . I also tried using the shacl playground tool https://shacl.org/playground/
Sure, the data graph in ttl would be:
@prefix ns0: <http://www.opengis.net/ont/geosparql#> .
@prefix dc: <http://purl.org/dc/terms/> .
@prefix ns1: <http://qudt.org/schema/qudt/> .
@prefix sosa: <http://www.w3.org/ns/sosa/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
<http://www.w3id.org/afarcloud/pCoord?lat=45.75&long=4.85>
ns0:asWKT "POINT(45.75 4.85)"^^ns0:wktLiteral ;
a <http://www.opengis.net/ont/sf#Point> .
<http://www.w3id.org/afarcloud/poi?lat=45.75&long=4.85>
ns0:hasGeometry <http://www.w3id.org/afarcloud/pCoord?lat=45.75&long=4.85> ;
a ns0:Feature .
<urn:afc:AS09:cropsManagement:TEC:soil:sen0022> a <https://json-ld.org/playground/AfarcloudSensors>, <https://json-ld.org/playground/SoilSensor> .
<urn:afc:AS09:sen0022:obs-1514810172/q1>
dc:identifier "q1" ;
ns1:numericValue "0.27121272683143616" ;
ns1:unit <http://qudt.org/vocab/unit/DEG_C> ;
a ns1:QuantityValue .
<urn:afc:AS09:sen0022:obs-1514810172>
a sosa:Observation ;
sosa:hasFeatureOfInterest <http://www.w3id.org/afarcloud/poi?lat=45.75&long=4.85> ;
sosa:hasResult <urn:afc:AS09:sen0022:obs-1514810172/q1> ;
sosa:madeBySensor <urn:afc:AS09:cropsManagement:TEC:soil:sen0022> ;
sosa:observedProperty <http://www.w3id.org/afarcloud/soil_temperature> ;
sosa:resultTime "2018-01-01T12:36:12Z"^^xsd:dateTime .
I tried adding the import like this:
@base <https://w3id.org/demeter/example> .
<https://w3id.org/demeter/example>
owl:imports <https://w3id.org/demeter/crossDomain> .
Sorry but this repo here is about the TopBraid SHACL API, not the one from Jena. I suggest asking the jena-users mailing list.
Hi, I am not very familiar yet with SHACL, so, I am trying to figure out if is possible, and if so, how, to define a shape constraint saying that the range of a property should be of type X AND any of its subclasses (rdf:subclassof*). FOr example, in shape below, how to say that the range of geo:hasGeometry is geo:Geometry and its subclasses ? thanks
https://astrea.linkeddata.es/shapes#3f6891594ac2d163a004bec00f8db48a a sh:PropertyShape ; sh:class geo:Geometry ; sh:nodeKind sh:IRIOrLiteral ; sh:path geo:hasGeometry .