- From: Peter F. Patel-Schneider <pfpschneider@gmail.com>
- Date: Thu, 2 Jun 2016 14:19:52 -0700
- To: RDF Data Shapes Working Group <public-data-shapes-wg@w3.org>
To think about how a constraint component works universally, it is sufficient to think about value nodes, which are already defined at the beginning of Section 4. So, sh:hasValue is then just that a value node is the given node and sh:equals is just that the set of value nodes is the same as the set of values for the focus node for the other property and sh:closed is just that every value node has no values for disallowed properties and sh:minCount is just that there are at least n value nodes. Looking at https://github.com/TopQuadrant/shacl the changes to permit core constraint components to be used universally appear to be as follows: 1/ Ensure that sh:context has all three relevant values for each constraint component. (Of course then sh:context becomes irrelevant and can be removed.) 2/ For the constraint component for: sh:closed add sh:propertyValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Predicate {?unallowed} is not allowed on {?subject} (closed shape)" ; sh:sparql """ SELECT ?this (?val AS ?subject) ?unallowed ?object WHERE { { FILTER ($closed) . } $this $predicate ?val . ?val ?unallowed ?object . FILTER (NOT EXISTS { GRAPH $shapesGraph { $currentShape sh:property/sh:predicate ?unallowed . } } && (!bound($ignoredProperties) || NOT EXISTS { GRAPH $shapesGraph { $ignoredProperties rdf:rest*/rdf:first ?unallowed . } })) } """ ; Similar for inverse property constraint. sh:closed should also be implementable using the simple form (like sh:datatype and sh:minExclusive are). sh:datatype add dash:hasDatatype as a value for sh:inversePropertyValidator sh:datatypeIn add dash:hasDatatypeIn as a value for sh:inversePropertyValidator sh:hasValue add sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Node is not value {$hasValue}" ; sh:sparql """ SELECT $this WHERE { FILTER { NOT sameTerm($this,$hasValue) } } """ ; ] ; sh:disjoint add sh:inversePropertyValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Inverse of property must not share any values with {$disjoint}" ; sh:sparql """ SELECT $this ($this AS ?object) $predicate ?subject WHERE { ?subject $predicate $this . ?subject $disjoint $this . } """ ; ] ; sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Node must not be a value of {$disjoint}" ; sh:sparql """ SELECT $this WHERE { $this $disjoint ?this . } """ ; ] ; sh:equals add sh:inversePropertyValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Inverse of property must have same values as {$equals}" ; sh:sparql """ SELECT $this ($this AS ?object) $predicate ?subject WHERE { { ?subject $predicate $this . FILTER NOT EXISTS { ?subject $equals $this . } } UNION { ?subject $equals $this . FILTER NOT EXISTS { ?subject $predicate $this . } } } """ ; ] ; sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Node must be a value of {$equals}" ; sh:sparql """ SELECT $this WHERE { FILTER NOT EXISTS { $this $disjoint $this } } """ ; ] ; sh:lessThan add sh:InversePropertyValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Inverse property value is not < value of {$lessThan}" ; sh:sparql """ SELECT $this ($this AS ?object) $predicate ?subject WHERE { ?subject $predicate $this . $this $lessThan ?object2 . FILTER (!(?subject < ?object2)) . } """ ; ] ; sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Node is not < value of {$lessThan}" ; sh:sparql """ SELECT $this WHERE { $this $lessThan ?object2 . FILTER (!(?this < ?object2)) . } """ ; ] ; sh:lessThanOrEquals similar sh:minCount add sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Node is precisely one value, not {$minCount}" ; sh:sparql """ SELECT $this WHERE { FILTER ( 1 >= $minCount) . } """ ; ] ; sh:maxCount similar sh:maxExclusive add dash:hasMaxExclusive as a value for sh:inversePropertyValidator sh:maxInclusive add dash:hasMaxInclusive as a value for sh:inversePropertyValidator sh:minExclusive add dash:hasMinExclusive as a value for sh:inversePropertyValidator sh:minInclusive add dash:hasMinInclusive as a value for sh:inversePropertyValidator sh:uniqueLang add sh:inversePropertyValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "Language {?lang} used more than once" ; sh:sparql """ SELECT DISTINCT $this ($this AS ?object) $predicate ?lang WHERE { { FILTER ($uniqueLang) . } ?value $predicate $this . BIND (lang(?value) AS ?lang) . FILTER (bound(?lang) && ?lang != \"\") . FILTER EXISTS { $this $predicate ?otherValue . FILTER (?otherValue != ?value && ?lang = lang(?otherValue)) . } } """ ; ] ; sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:message "A language used more than once on node" ; sh:sparql """ SELECT $this WHERE { FILTER ( 1 = 0 ) } """ ; ] ; sh:qualifiedMinCount add sh:nodeValidator [ rdf:type sh:SPARQLSelectValidator ; sh:sparql """ SELECT $this ($this AS ?subject) $predicate ?count ?failure WHERE { BIND (sh:hasShape(?subject, $valueShape, $shapesGraph) AS ?hasShape) . BIND (!bound(?hasShape) AS ?failure) . FILTER IF(?failure, true, ?count > IF(?hasShape,1,0)) } """ ; ] ; sh:qualifiedMaxCount similar Note that none of these are difficult to do, particularly when looking at the another validator for the same component. This should be true for any constraint component that can be described as working on the value nodes. I think that all constraint components should be describable this way. peter
Received on Thursday, 2 June 2016 21:20:23 UTC