[ISSUE-62] A clean proposal with sh:Scope

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

Received on Wednesday, 3 June 2015 23:18:28 UTC