Re: ISSUE-135: Proposed changes to implement syntax simplification

I have meanwhile had a bit more time for this topic and here is my 
updated proposal (which is also much simpler than before).

Several WG members supported the idea of allowing constraints to be used 
as values in places such as sh:or. I was asked to make some specific 
suggestions on what would need to be changed in the spec, so that the 
following syntax options would behave identically. (Both scenarios state 
that the values of schema:address must be string literals or instances 
of schema:Address):

a) Currently supported: sh:or can only be used with sh:NodeConstraints 
and operands of sh:or must be shapes

ex:MyShape
     a sh:Shape ;
     sh:constraint [
         sh:or (
             [ a sh:Shape ;
                 sh:property [
                     sh:predicate schema:address ;
                     sh:datatype xsd:string ;
                 ] ;
             ]
             [ a sh:Shape ;
                 sh:property [
                     sh:predicate schema:address ;
                     sh:class schema:Address ;
                 ] ;
             ]
         )
     ]

which lacks on multiple fronts - it is too verbose and also forces 
repetition of the predicate.

b) Proposed: generalize sh:or and values of sh:or may be sh:NodeConstraints:

ex:MyShape
     a sh:Shape ;
     sh:property [
         sh:predicate schema:address ;
         sh:or (
             [ sh:datatype xsd:string ]
             [ sh:class schema:Address ]
         )
     ]

In this proposal, the members of the sh:or List may be 
sh:NodeConstraints or sh:Shapes.

Required changes (all incremental to current spec):

1) Rename sh:hasShape from sh:hasShape(?node, ?shape, ?shapesGraph) to

     sh:validateNode(?node, ?shapeOrConstraint, ?shapesGraph)

The algorithm would be changed to

a) if ?shapeOrConstraint rdf:type sh:Shape, then behave as currently
b) otherwise, assume rdf:type sh:NodeConstraint
c) report failure if the node has rdf:type that is neither sh:Shape nor 
sh:NodeConstraint.

The name sh:validateNode is better than sh:hasShape because it may also 
return unbound. I have no strong opinion whether we should assume 
sh:Shape or sh:NodeConstraint as default here - it really depends on 
what case we consider more frequent and what kind of syntactic sugar we 
want to provide.

2) Generalize sh:or to also have contexts: sh:PropertyConstraint and 
sh:InversePropertyConstraint. The validators are almost identical to the 
current one, simply calling sh:validateNode on each value.

The same approach would work for sh:and and sh:not. I guess also for 
sh:valueShape if that's desirable.

Regards,
Holger


On 5/05/2016 22:21, Holger Knublauch wrote:
> Too quick: I believe there is a glitch in the algorithm below and I 
> need to think more about the implementation details. As stated it 
> would walk the properties of a property value, which is incorrect. 
> Maybe the list values need to be interpreted as sh:NodeConstraints 
> only. Please ignore for now.
>
> Holger
>
>
> On 5/05/2016 12:49, Holger Knublauch wrote:
>> Several WG members supported the idea of allowing constraints to be 
>> used as values in places such as sh:or. I was asked to make some 
>> specific suggestions on what would need to be changed in the spec, so 
>> that the following syntax options would behave identically. (Both 
>> scenarios state that the values of schema:address must be string 
>> literals or instances of schema:Address):
>>
>> a) Currently supported: sh:or can only be used with 
>> sh:NodeConstraints and operands of sh:or must be shapes
>>
>> ex:MyShape
>>     a sh:Shape ;
>>     sh:constraint [
>>         sh:or (
>>             [ a sh:Shape ;
>>                 sh:property [
>>                     sh:predicate schema:address ;
>>                     sh:datatype xsd:string ;
>>                 ] ;
>>             ]
>>             [ a sh:Shape ;
>>                 sh:property [
>>                     sh:predicate schema:address ;
>>                     sh:class schema:Address ;
>>                 ] ;
>>             ]
>>         )
>>     ]
>>
>> which lacks on multiple fronts - it is too verbose and also forces 
>> repetition of the predicate.
>>
>> b) Proposed: generalize sh:or and values of sh:or may be constraints 
>> of the same kind as the surrounding constraint.
>>
>> ex:MyShape
>>     a sh:Shape ;
>>     sh:property [
>>         sh:predicate schema:address ;
>>         sh:or (
>>             [ sh:datatype xsd:string ]
>>             [ sh:class schema:Address ]
>>         )
>>     ]
>>
>> In this proposal, the members of the sh:or List may be 
>> sh:PropertyConstraints if sh:or is used within a sh:PropertyConstraint.
>>
>> Required changes (all incremental to current spec):
>>
>> 1) Generalize sh:hasShape from sh:hasShape(?node, ?shape, 
>> ?shapesGraph) to
>>
>>     sh:validateNode(?node, ?shapeOrConstraint, ?shapesGraph, 
>> ?defaultConstraintType, ?defaultPredicate)
>>
>> The two arguments at the end are optional, and are used to complement 
>> the provided ?shapeOrConstraint unless it is a sh:Shape. Legal values 
>> for ?defaultConstraintType would be sh:PropertyConstraint, 
>> sh:InversePropertyConstraint and sh:NodeConstraint. ?defaultPredicate 
>> is only supported if ?defaultConstraintType is given and != 
>> sh:NodeConstraint.
>>
>> The algorithm would be
>>
>> a) if ?shapeOrConstraint rdf:type sh:Shape, then behave as currently
>> b) otherwise, assume ?defaultConstraintType (unless the node has an 
>> rdf:type)
>>     and assume ?defaultPredicate for sh:predicate.
>> c) report failure if the node has rdf:type that is neither sh:Shape 
>> nor ?defaultConstraintType.
>>
>> While this function isn't pretty it's mostly used internally anyway 
>> and may therefore be regarded as an implementation detail. The name 
>> sh:validateNode is better than sh:hasShape because it may also return 
>> unbound.
>>
>> 2) Generalize sh:or to also have contexts: sh:PropertyConstraint and 
>> sh:InversePropertyConstraint
>>
>> 3) Add a sh:propertyValidator to sh:OrConstraint similar to what we 
>> have as sh:nodeValidator, but with the sh:validateNode function:
>>
>> SELECT $this ?failure ...
>> WHERE {
>>    {
>>   $this $predicate ?value .
>>  }
>>   {
>>   SELECT (SUM(?s) AS ?count)
>>   WHERE {
>>    GRAPH $shapesGraph {
>>     $or rdf:rest*/rdf:first ?shape .
>>    }
>>    BIND (sh:validateNode(?value, ?shape, $shapesGraph, sh:PropertyConstraint, $predicate) AS ?valid) .
>>    BIND (IF(bound(?valid), IF(?valid, 1, 0), 'error') AS ?s) .
>>   }
>>  }
>>  BIND (!bound(?count) AS ?failure) .
>>  FILTER IF(?failure, true, ?count = 0) .
>> }
>>
>> and similar for sh:inversePropertyValidator. The same approach would 
>> work for sh:and and sh:not. I guess also for sh:valueShape if that's 
>> desirable.
>>
>> Regards,
>> Holger
>>
>

Received on Monday, 9 May 2016 06:43:57 UTC