But I don't get :country as a classSubject unless I do ?start rdfs:subClassOf* ?end . in the first helper function (note the star).
But if I do that the length function doesn't work. All lengths are set to 1.
So question:
a) Can I include the starting class in this chain with the length calculation intact?
b) If it's not possible, is there a way of adding it by UNION/Values to an outer query that uses this?
and got the expected result. :country cannot be a classSubject because it's not a super class of anything. It's not a classSubject in your desired response either. Am I missing something?
prefix sqs: <tag:stardog:api:sqs:>
SELECT ?start ?classSubject ?depth ?property ?datatype ?minCount ?maxCount ?class {
# Is there any SHACL shape with class as target?
# And does that SHACL container have any Property shape objects?
?nodeShape sh:targetClass ?classSubject;
sh:property ?propertyShape .
# What property is the PropertyShape targeting?
?propertyShape sh:path ?property .
# What specific SHACL constraints are defined for that property?
OPTIONAL { ?propertyShape sh:minCount ?minCount . }
OPTIONAL { ?propertyShape sh:maxCount ?maxCount . }
OPTIONAL { ?propertyShape sh:class ?class . }
# Start of subquery – runs first to narrow down classes of relevance for shape inheritance
{
# What are the parent classes?
# And what is the distance from the classSubject
# to the top of the class chain (:meta_root)
SELECT ?start ?classSubject ?depth {
service <query://GetClassDistance> {
[] sqs:vars ?path ; sqs:var:start ?start ; sqs:var:end ?classSubject ; sqs:var:length ?depth .
}
# Which classes do we want shape for?
FILTER(?start IN (:country))
}
}
# Which properties do we want shape for?
#FILTER(?property in (:p_wikidata_id))
}
Oh I see. Right, you cannot really force a path query to return paths of zero length.
Here's one workaround, modify your GetClassDistance as follows:
prefix sqs: <tag:stardog:api:sqs:>
SELECT ?start ?end ?length {
{
service <query://GetClassPath> {
[] sqs:vars ?path ; sqs:var:start ?start ; sqs:var:end ?end .
}
bind (stardog:length(?path) as ?length)
}
union {
?start a owl:Class
bind(?start as ?end)
bind(0 as ?length)
}
}
and make sure each class has a declaration axiom, eg. :country a owl:Class (they need to be there anyway according to the OWL spec but this workaround relies on them explicitly).