Почему SHSLpe.hasTargetNode API SHACL возвращает False для целевого класса?
В ходе попытки выборочного вызова форм / правил при утверждении классов я работаю со следующим примером определения форм (в TTL):
# baseURI: http://example.org/familyShapes
# imports: http://datashapes.org/dash
# prefix: familyShapes
@prefix dash: <http://datashapes.org/dash#> .
@prefix familyShapes: <http://example.org/familyShapes#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
<http://example.org/familyShapes>
rdf:type owl:Ontology ;
owl:imports <http://datashapes.org/dash> ;
.
familyShapes:FemaleShape
rdf:type sh:NodeShape ;
rdfs:label "Female shape" ;
sh:property [
sh:path familyShapes:gender ;
sh:hasValue familyShapes:female ;
] ;
.
familyShapes:Gender
rdf:type rdfs:Class ;
rdfs:label "Gender" ;
rdfs:subClassOf rdfs:Resource ;
.
familyShapes:GrandpaRuleShape
rdf:type sh:NodeShape ;
rdfs:label "Grandpa rule shape" ;
sh:rule [
rdf:type sh:SPARQLRule ;
rdfs:comment "Shape to infer grandpa/grandchild relationship" ;
rdfs:label "Infer grandpas and grandchildren" ;
sh:construct """
PREFIX familyShapes: <http://example.org/familyShapes#>
CONSTRUCT {
?child familyShapes:grandPa $this .
$this familyShapes:grandChild ?child .
}
WHERE {
{
?child familyShapes:mother ?mom .
?mom familyShapes:father $this .
}
UNION
{
?child familyShapes:father ?dad .
?dad familyShapes:father $this .
}
}
""" ;
sh:order 10 ;
] ;
sh:targetClass familyShapes:Person ;
.
familyShapes:MaleShape
rdf:type sh:NodeShape ;
rdfs:label "Male shape" ;
sh:property [
sh:path familyShapes:gender ;
sh:hasValue familyShapes:male ;
] ;
.
familyShapes:Person
rdf:type rdfs:Class ;
rdf:type sh:NodeShape ;
rdfs:label "Person" ;
rdfs:subClassOf rdfs:Resource ;
sh:property [
rdf:type sh:PropertyShape ;
sh:path familyShapes:father ;
sh:class familyShapes:Person ;
sh:description "A Person's father." ;
sh:maxCount 1 ;
sh:name "father" ;
sh:node familyShapes:MaleShape ;
sh:nodeKind sh:IRI ;
sh:sparql [
sh:message "A person cannot be a father to that same person." ;
sh:select """PREFIX familyShapes: <http://example.org/familyShapes#>
SELECT $this
WHERE {
$this familyShapes:father $this .
}""" ;
] ;
] ;
sh:property [
rdf:type sh:PropertyShape ;
sh:path familyShapes:firstName ;
sh:datatype xsd:string ;
sh:description "A Person's first name (aka given name)." ;
sh:minCount 1 ;
sh:name "first name" ;
] ;
sh:property [
rdf:type sh:PropertyShape ;
sh:path familyShapes:gender ;
sh:class familyShapes:Gender ;
sh:description "A Person's gender." ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:name "gender" ;
] ;
sh:property [
rdf:type sh:PropertyShape ;
sh:path familyShapes:lastName ;
sh:datatype xsd:string ;
sh:description "A Person's last name (aka family name)." ;
sh:maxCount 1 ;
sh:minCount 1 ;
sh:name "last name" ;
] ;
sh:property [
rdf:type sh:PropertyShape ;
sh:path familyShapes:mother ;
sh:class familyShapes:Person ;
sh:description "A Person's mother." ;
sh:maxCount 1 ;
sh:name "mother" ;
sh:node familyShapes:FemaleShape ;
sh:nodeKind sh:IRI ;
sh:sparql [
rdfs:comment "A person cannot be that same person's mother." ;
sh:message "A person cannot be that same person's mother." ;
sh:select """PREFIX familyShapes: <http://example.org/familyShapes#>
SELECT $this
WHERE {
$this familyShapes:mother $this .
}""" ;
] ;
] ;
sh:rule [
rdf:type sh:SPARQLRule ;
rdfs:label "Infer grandmas and grandchildren" ;
sh:construct """PREFIX familyShapes: <http://example.org/familyShapes#>
CONSTRUCT {
?child familyShapes:grandMa $this .
$this familyShapes:grandChild ?child .
}
WHERE {
{
?child familyShapes:mother ?mom .
?mom familyShapes:mother $this .
}
UNION
{
?child familyShapes:father ?dad .
?dad familyShapes:mother $this .
}
}
""" ;
] ;
.
familyShapes:female
rdf:type familyShapes:Gender ;
rdfs:label "female" ;
.
familyShapes:firstName
rdf:type rdf:Property ;
rdfs:comment "A Person's first name (aka given name)." ;
rdfs:label "first name" ;
.
familyShapes:grandChild
rdf:type owl:ObjectProperty ;
rdfs:domain familyShapes:Person ;
rdfs:label "grand child" ;
rdfs:range familyShapes:Person ;
.
familyShapes:grandMa
rdf:type owl:ObjectProperty ;
rdfs:domain familyShapes:Person ;
rdfs:label "grand ma" ;
rdfs:range familyShapes:Person ;
.
familyShapes:grandPa
rdf:type owl:ObjectProperty ;
rdfs:domain familyShapes:Person ;
rdfs:label "grand pa" ;
rdfs:range familyShapes:Person ;
.
familyShapes:male
rdf:type familyShapes:Gender ;
rdfs:label "male" ;
.
familyShapes:mother
rdf:type rdf:Property ;
rdfs:comment "A Person's mother." ;
rdfs:label "mother" ;
.
Я сосредоточен в это время на familyShapes:GrandpaRuleShape
форма (начиная со строки 30), которая, как мне кажется, в строке 58 нацелена на familyShapes:Person
учебный класс.
API SHACL RuleUtil.getShapesWithTargetNode
Метод возвращает пустой список, который не является ожидаемым результатом, поэтому я создал временную локальную копию RuleUtil.getShapesWithTargetNode
метод, как показано ниже, чтобы помочь мне отладить мой собственный код.
private static List<Shape> getShapesWithTargetNode(RDFNode focusNode, ShapesGraph shapesGraph) {
// TODO: Not a particularly smart algorithm - walks all shapes that have rules
List<Shape> shapes = new ArrayList<>();
for(Shape shape : shapesGraph.getRootShapes()) {
SHShape sr = shape.getShapeResource();
boolean shapeHasRule = sr.hasProperty(SH.rule);
boolean shapeFocused = sr.hasTargetNode(focusNode);
if(shapeHasRule && shapeFocused) {
shapes.add(shape);
}
}
return shapes;
}
Я остановил выполнение в отладчике в этом методе с focusNode
знак равноhttp://example.org/familyShapes#Person
и shapeGraph, представляющий файл фигур выше. Точка останова находится в условном цикле for после того, как два логических значения были назначены. Первое значение shape
является familyShapes:GrandpaRuleShape
, Тем не менее, логическое shapeFocused
является false
, Логическое значение shapeHasRule
является true
как и ожидалось.
Я ожидал, что shapeFocused
было бы true
на этом этапе исполнения. На более высоком уровне я ожидал, что этот метод вернет список, по крайней мере, содержащий форму дедушки, но он вернется пустым. Я думаю, что я должен неправильно настроить вызов этого метода, но я не уверен, что делаю неправильно. Какие-либо предложения?
1 ответ
Я думаю, что это работает правильно. Person - это класс, а форма правила имеет вид sh:targetClass Person. Это означает, что узлы фокуса / цели являются экземплярами этого класса. Если вы вызываете функцию с конкретным экземпляром Person, она должна работать.