- From: Holger Knublauch <holger@topquadrant.com>
- Date: Fri, 05 Jun 2015 10:54:34 +1000
- To: RDF Data Shapes Working Group <public-data-shapes-wg@w3.org>
- Message-ID: <5570F34A.1000401@topquadrant.com>
Not sure if it helps, but attached is a simplified graphical workflow for how this proposal would work. Holger On 6/5/2015 9:29, Holger Knublauch wrote: > On 6/5/2015 8:54, Peter F. Patel-Schneider wrote: >> -----BEGIN PGP SIGNED MESSAGE----- >> Hash: SHA256 >> >> There were already separate scopes for individual-based scoping and >> class-based scoping. > > Yes, my proposal is to keep sh:scopeClass and sh:nodeShape as > syntactic sugar for the frequently needed cases that they cover. > >> Do you mean that there should now be a new kind of >> template for scopes, and new special scopes, all separate from >> constraints? > > Yes, because scopes and shapes are very different concepts. Scopes > produce focus nodes, while constraints validate given focus nodes. > >> >> Constraints are already available, and can do double duty as scopes. >> Why >> not use them for determining the scope of a shape particularly as you >> then >> actually do use them for this purpose, but as filters. I don't see >> what the >> point is of adding all this extra stuff. > > Because they cannot always do double duty, as we had discussed here at > length. This is due to the way that they are implemented. A constraint > produces violation instances, but what we need are focus nodes. In > other words, constraints look for the counter examples, while we would > need the opposite direction to find all nodes that actually fit. > > I am surprised about your feedback, because your own proposal had > exactly the same concept, in form of sh:sparqlScope. In your own > example, you use it to return all instance of ex:Person: > > [ rdf:type sh:Constraint ; > sh:severity sh:fatalError ; > sh:report "SELECT ?person" ; > sh:sparqlScope "?person rdf:type <http://example.org/Person>" ; > sh:sparqlShape > """FILTER NOT EXISTS { ?person ex:offspring ?offspring . > FILTER NOT EXISTS { ?offspring rdf:type ex:Person . } }""" > ] . > > If this scope were a constraint, then it would be formulated in the > opposite direction "report an error if this is not an instance of > ex:Person". > > All I have done is generalize your approach to allow sparqlScope to > also be a template, and I have moved your sh:shapeScope into > sh:filterShape. This solves the problem with your approach, that some > constraints simply do not bind ?this. Your work-around was to inject > some magic to bind ?this with all instances of rdfs:Resource, so but > even this hack now can have an official solution: > > sh:ShapeScope > a sh:ScopeTemplate > sh:argument [ > sh:predicate sh:shape ; # becomes ?shape in the query > sh:valueType sh:Shape ; > rdfs:comment "The shape that all focus nodes must have" > ] ; > sh:sparql """ > SELECT ?this > WHERE { > ?this a rdfs:Resource . > FILTER sh:hasShape(?this, ?shape) > } > """ . > > And we side-step the question whether ?this should by default be all > subjects, all nodes, all instances, etc. We just define a generic > mechanism and let the model do the rest. Anyone can add their own > scoping template. > > As a bonus we don't have to look into complex SPARQL query analysis to > find out whether a query is binding ?this and similar unnecessary > complexity that few users will understand. > > Hope this makes sense, I can elaborate further. > > Holger > > >> >> peter >> >> >> On 06/03/2015 04:16 PM, Holger Knublauch wrote: >>> I thought more about the issue of generic scopes and filters and have >>> come up with a variation of Peter's design. Assuming we define >>> >>> - Scope: takes a graph as input and produces bindings for the focus >>> node >>> (?this) >>> >>> Graph -> focus nodes >>> >>> - Constraint: that takes a focus node as input and produces (violation) >>> results: >>> >>> focus nodes -> results >>> >>> I think we should make Scopes an explicit concept in SHACL's RDF >>> vocabulary, similar to how shapes are defined. There would be the >>> following class hierarchy: >>> >>> sh:Scope sh:NativeScope sh:TemplateScope >>> >>> And native scopes can have sh:sparql (or a JS body etc). Example >>> >>> # Applies to all subjects that have a skos:prefLabel ex:MyShape >>> sh:scope >>> [ a sh:NativeScope ; # Optional rdf:type triple sh:sparql """ SELECT >>> DISTINCT ?this WHERE { ?this skos:prefLabel ?any } """ ] ; >>> sh:constraint >>> [ a ex:UniqueLanguageConstraint ; ex:predicate skos:prefLabel ; ] . >>> >>> This (common) case above could be turned into a template >>> sh:PropertyScope: >>> >>> ex:MyShape sh:scope [ a sh:PropertyScope ; sh:predicate >>> skos:prefLabel . >>> ] ; sh:constraint [ a ex:UniqueLanguageConstraint ; ex:predicate >>> skos:prefLabel ; ] . >>> >>> and we could provide a small collection of frequently needed scopes, >>> e.g. >>> >>> - all nodes in a graph - all subjects - all nodes with any rdf:type >>> - all >>> IRI nodes from a given namespace >>> >>> Systems that don't speak SPARQL would rely on the hard-coded IRIs from >>> the core vocabulary, such as sh:PropertyScope. >>> >>> We could now also formally define the scope behind sh:scopeClass (and >>> sh:nodeShape): >>> >>> sh:ClassScope a sh:TemplateScope ; sh:argument [ sh:predicate >>> sh:class ; >>> # Becomes ?class sh:valueType rdfs:Class ; ] ; sh:sparql """ SELECT >>> ?this WHERE { ?type rdfs:subClassOf* ?class . ?this a ?type . } """ . >>> >>> In addition to these scopes, I suggest we turn sh:scopeShape into >>> sh:filterShape, and use these filters as pre-conditions that are >>> evaluated for a given set of focus nodes. The workflow then becomes: >>> >>> - sh:scope produces bindings for ?this - sh:filterShape filters out the >>> values of ?this that do not match the given shape - the actual >>> constraints are evaluated >>> >>> I believe this design provides the flexibility of a generic scoping >>> mechanism (as suggested in Peter's design) without getting into the >>> complexity of having to analyze SPARQL syntax or rely on hacks with >>> rdfs:Resource, while having a user-friendly syntax. The fact that we >>> separate sh:Scope from sh:Shape means that we can enforce different, >>> explicit semantics on scopes. For example we could allow a sh:Scope to >>> encapsulate another SPARQL query that tests whether a given ?this is in >>> scope, i.e. the inverse direction of the SELECT query, to optimize >>> performance. >>> >>> Thanks, Holger >>> >>> >> -----BEGIN PGP SIGNATURE----- >> Version: GnuPG v2 >> >> iQEcBAEBCAAGBQJVcNcvAAoJECjN6+QThfjzi28H/3x3+0mmUmrKvEkbxuQ4Vp4a >> 1E65QIwcZuWhmocT+nHwtPT9Bb0nCMA4D+lsCfwGCp671dhoFmrHAAERe/xDKbSL >> IJ1vRkstNA0Y+QKS29M2eKtICbO+R8z3ez6xlUNUA7yY0TfE4W1zB2nHh/wzJFyY >> VM9KHhyQV7ZA+c5hdbai163rGOcFu7Mr54LsUiF2nZ5kAlgtZnJfn45Ewfip+kIO >> a5zBlyqDY5T+GvgSEvFi1u+V0RjZPVnvApxT/oRbepLOu+EintFttH8IpB4T+HBB >> yv/kyUGNH4lxNrsYVyAEzYmMi6KIUHuQEiI2VfB4tYRwLJwA7+VsECsRcRtjR/A= >> =0+/m >> -----END PGP SIGNATURE----- >
Attachments
- image/png attachment: SHACL-Validation-Process.png
Received on Friday, 5 June 2015 00:56:57 UTC