eclipse-rdf4j / rdf4j

Eclipse RDF4J: scalable RDF for Java
https://rdf4j.org/
BSD 3-Clause "New" or "Revised" License
359 stars 161 forks source link

rdfs:subclassOf in SHACL graph is ignored #2577

Closed EmmanuelOga closed 3 years ago

EmmanuelOga commented 3 years ago

Hello, I'm using the SHACL validator as documented here with RDF4J version 3.4.0.

I'm using the schema.org shapes available here.

I have these triples:

@base <https://emmanueloga.com/> .
@prefix : <https://emmanueloga.com/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rf: <https://eoga.dev/rainbowfish#> .
@prefix schema: <http://schema.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

<me>
    a schema:Person ;
    schema:name "Emmanuel Oga" ;
    schema:familyName "Oga" ;
    schema:givenName "Emmanuel" ;
    schema:jobTitle "Software Engineer" ;
    schema:knowsLanguage "en-US", "es-ES" ;
    schema:homeLocation :home-location .

<home-location>
    # a schema:ContactPoint ;
    a schema:PostalAddress ;
    schema:addressLocality "San Francisco" ;
    schema:addressRegion "California" ;
    schema:addressCountry "United States" .

... for which RDF4J fails to validate schema:homeLocation (see validation report at the bottom). Note that I commented out a schema:ContactPoint on the data. If I use ContactPoint, the data validates fine. But since the schema.org shapes say:

schema:PostalAddress
  a rdfs:Class ;
  a sh:NodeShape ;
  rdfs:subClassOf schema:ContactPoint ;
  # ... more properties here ...

schema:Person-homeLocation
  a sh:PropertyShape ;
  sh:path schema:homeLocation ;
  sh:description "A contact location for a person's residence."^^rdf:HTML ;
  sh:name "homeLocation" ;
  sh:or (
      [
        sh:class schema:ContactPoint ;
      ]
      [
        sh:class schema:Place ;
      ]
    ) ;
.

... I suspect rdfs:subClassOf is not being considered. The documentation says "By default the ShaclSail supports the simple rdfs:subClassOf reasoning", and I verified this is enabled on my code (isRdfsSubClassReasoning returns true).

Maybe I'm misunderstanding how this is supposed to work? I was assuming since PostalAddress is defined a subclass of ContactPoint, I should be able to provide a PostalAddress where a ContactPoint is expected.

Thank you!

RD4J Validation Report:

@prefix : <https://emmanueloga.com/> .
@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 rf: <https://eoga.dev/rainbowfish#> .
@prefix schema: <http://schema.org/> .
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix fx: <https://eoga.dev/fishx#> .

_:node1ejqrsupkx1939 a sh:ValidationReport;
  sh:conforms false;
  <http://rdf4j.org/schema/rdf4j#truncated> false;
  sh:result _:node1ejqrsupkx1940 .

_:node1ejqrsupkx1940 a sh:ValidationResult;
  sh:focusNode :me;
  sh:sourceConstraintComponent sh:OrConstraintComponent;
  sh:sourceShape schema:Person-homeLocation;
  sh:resultPath schema:homeLocation;
  sh:detail _:node1ejqrsupkx1941 .

_:node1ejqrsupkx1941 a sh:ValidationResult;
  sh:focusNode :me;
  sh:sourceConstraintComponent sh:ClassConstraintComponent;
  sh:sourceShape _:node1ejqrsup0x1998;
  sh:resultPath schema:homeLocation;
  sh:value :home-location;
  sh:detail _:node1ejqrsupkx1942 .

_:node1ejqrsupkx1942 a sh:ValidationResult;
  sh:focusNode :me;
  sh:sourceConstraintComponent sh:ClassConstraintComponent;
  sh:sourceShape _:node1ejqrsup0x2000;
  sh:resultPath schema:homeLocation;
  sh:value :home-location .
hmottestad commented 3 years ago

@EmmanuelOga can you try adding the rdfs:subClassOf statements as part of your data instead of the shapes (eg. don't add it to the shacl graph)?

EmmanuelOga commented 3 years ago

@hmottestad that was exactly what was happening:

                try {
                    conn.add(shapes) // <<-- Adding this line solves the issue!
                    conn.add(shapes, RDF4J.SHACL_SHAPE_GRAPH)
                    conn.commit()
                    println("OK")
                } catch (exception: RepositoryException) { ... 

Not sure if there are any lessons that I should get from this... should I always commit the data to both the default graph and the shapes graph in the general case?

thx again

hmottestad commented 3 years ago

I think we will call this a bug. I should be retrieving rdfs:subClassOf statements from both the base sail and the SHACL graph.

hmottestad commented 3 years ago

@EmmanuelOga https://rdf4j.org/release-notes/3.4.3/