Skip to content

#300: Added support for RDF 1.2 triple terms #368

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: gh-pages
Choose a base branch
from
Open

Conversation

bergos
Copy link
Contributor

@bergos bergos commented Apr 21, 2025

This PR adds support for RDF 1.2 triple terms, as discussed in #300.

Since this is the first RDF 1.2 feature PR, I want to discuss in the next meeting how to handle RDF 1.2 features before merging it.

Closes #300

<h4>sh:reifiableBy, sh:reificationRequired</h4>
<p>
<code>sh:reifiableBy</code> can be used to link a <a>property shape</a> with one or more <a>node shapes</a>.
Any reified statement must conform to these node shapes.
Copy link
Contributor

@afs afs Apr 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{| |} is surface syntax for the triples.

I think SHACL needs to define validation for the basic forms then work up from there. This PR seems to be for an annotation usage pattern but that isn't the only way to use RDF 1.2.

Starting with:

ex:ValidResource1
  ex:propertyA "valid" {|
      ex:propertyB true ;
  |} .

{| |} is syntax to both reify a triple and provide triple about the reification. It is only syntax and is not retained in the RDF graph.

ex:ValidResource1  ex:propertyA  "valid" .
<< ex:ValidResource1 ex:propertyA "valid" >> ex:propertyB  true .

and << >> (an occurence - a use of a triple term) is in turn surface syntax for rdf:reifies
so the whole thing three triples:

ex:ValidResource1  ex:propertyA  "valid" .
_:b0    rdf:reifies   <<( ex:ValidResource1 ex:propertyA "valid" )>>;
        ex:propertyB  true .

<<( ... )>> is a triple term.

I think the intent is to apply a shape to the structure and also the triples insided {| |}.
Is that right?

Only Turtle/TriG have this annotation syntax.

Data does not have to use {| |} and it does not exist graph / triple store.

Sometimes, there may not be an asserted triple:

<< :s :p :o ~ _:reif1 >> :added "2025-04-01" .
<< :s :p :o ~ _:reif1 >> :deleted "2025-05-01" .

which is 3 triples:

_:b0    rdf:reifies  <<( :s :p :o )>>;
        :added       "2025-04-01" .
        rdf:reifies  <<( :s :p :o )>>; ## Duplicate - same as the first triple.
        :deleted     "2025-05-01" .

Note the shared blank node.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's for the use case where an asserted triple can be used to traverse into the triple term. The text definition says that the reifier will become the focus node for that validation.

Based on the discussion in #300, I thought we don't need to cover the use case without asserted triples. Node Expressions, or SPARQL-based targets can be used for that use case.

<div class="def def-text">
<div class="def-header">TEXTUAL DEFINITION of sh:reificationRequired</div>
<div class="def-text-body" data-validator="ReificationRequired">
If <code>$reificationRequired</code> is set to <code>true</code>, a failure MUST be produced when there is no reified statement for the <a>triple term</a> <code>t</code> in the <a>data graph</a>.
Copy link
Contributor

@afs afs Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There can be zero or more groups of triples

## Reifier, no triple with that as subject
:s :p :o1 ~:r .  
## Same as :s :p :o1 ~:r  {} . 
## Two reifiers, each with triples.
:s :p :o2 {| ex:signedOffBy "A" |}
          {| ex:signedOffBy "B" |} .

In this example, reificationRequired is more count-like. This includes 0 -- the first example above -- here the reifier is allocated for later use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node Expressions, or SPARQL-based targets can be used for that use case.

How? SPARQL-based constraints can do many things but what would node expressions look like?

General observation: Pushing things onto node expressions may work technically but they aren't necessarily a friendly way to express things. If the WG decides to publish core as a REC ASAP, then core is then fixed and unchangeable. The WG needs to be certain that pushing out things out to phase2 actually ends up with the best outcome.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can handle that change in a separate PR. That's why I've moved the discussion back to the issue.

Copy link
Member

@TallTed TallTed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few changes, which I hope improve clarity and readability.

Co-authored-by: Ted Thibodeau Jr <[email protected]>
@afs
Copy link
Contributor

afs commented Apr 28, 2025

This PR is motivated to the annotation pattern/syntax in RDF 1.2 Turtle.

Annotation hides the reifier although the reifier can be explicitly given.

The property shape object of sh:reifiableBy is applied to asserted triples whose subject is the reifier.

sh:reifiableBy could instead be named sh:describedBy or sh:tripleDescribedBy or sh:annotatedBy.

With explicit reifier:

:s :p :o ~:r {| ex:signedOffBy "A" |}

then the name sh:reifiableBy could be used to get the reifier (node shape).

@TallTed
Copy link
Member

TallTed commented Apr 28, 2025

The property shape object of sh:reifiableBy is applied to asserted triples whose subject is the reifier.

sh:reifiableBy could instead be named sh:describedBy or sh:tripleDescribedBy or sh:annotatedBy.

I must be missing something somewhere. Why not sh:reifiedBy?

@HolgerKnublauch
Copy link
Contributor

@TallTed the name probably was copied from dash:reifiableBy. The reason is that reifiedBy would mean that reification is required, while reifableBy means that if a reification exists then it must have the given shape.

@TallTed
Copy link
Member

TallTed commented Apr 28, 2025

sh:reifableBy means that if a reification exists then it must have the given shape

Fair enough.

@afs
Copy link
Contributor

afs commented Apr 28, 2025

I think Ted has a point.

To get to the focus node for the annotations (data graph traversal), there must be a connection between the reifier (blank node or the :r above) and the current triple as a triple term. This is the rdf:reifies triple(s) with this focus triple as a triple term in the object position.

The annotation syntax checking resides in ex:ProvenanceShape.

The focus node of ex:ProvenanceShape is the reifier.
If it has no other constraints, it becomes a test for the existence of rdf:reifies.
(implicitly it has sh:property [ sh:path rdf:reifies ])

Suggestion: rename sh:reifiableBy as

sh:reifierShape -- "The [node shape] that a reifier for this triple must conform to."

ex:PersonShape-age
  a sh:PropertyShape ;
  sh:path ex:age ;
  sh:datatype xsd:integer ;
  sh:maxCount 1 ;
  sh:reifierShape ex:ProvenanceShape ;
  .
ex:ProvenanceShape
    sh:property [ 
      sh:path rdf:reifies ;
      sh:nodeKind sh:IRI ; ## e.g. requires the reifier to be an IRI
    ] ;
    sh:property [
      sh:path ex:author ;
      sh:nodeKind sh:IRI ;
      sh:maxCount 1 ;
    ] .
] .

There can be multiple reifiers, each with an annotation blocks in the syntax. I'm not sure what that is going to look like.

@bergos
Copy link
Contributor Author

bergos commented May 12, 2025

I've renamed sh:reifiableBy to sh:reifierShape. Also, "reified statement" has been replaced with "reifier" to match the RDF Concepts specification.

@afs
Did you mean the inverse of rdf:reifies?

ex:ProvenanceShape
    sh:property [ 
      sh:path rdf:reifies ; # inverse?
      sh:nodeKind sh:IRI ; ## e.g. requires the reifier to be an IRI
    ]
] .

@bergos
Copy link
Contributor Author

bergos commented May 31, 2025

@afs @TallTed @HolgerKnublauch Can you please review the latest changes?

<p>
<code>sh:reifierShape</code> can be used to link a <a>property shape</a> with one or more <a>node shapes</a>.
Any <a>reifier</a> must conform to these node shapes.
If a property shape contains a <code>sh:ReifierShapeConstraintComponent</code>, <code>sh:path</code> values are constrained to IRIs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The term "contains" is unclear here and I think it would be better to say "if a property shape has a value for sh:reifierShape...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also I believe this is a formal constraint and needs to be moved into a data-syntax-rule, i.e. under the parameter definition of sh:reifierShape.

<div class="def-text-body" data-validator="ReifierShape">
Let <code>t</code> be the <a>triple term</a> (<a>focus node</a>, <code>$path</code>, <a>value node</a>).
For each <a>reifier</a> for the <a>triple term</a> <code>t</code>, a failure MUST be produced if validating the <a>reifier</a> against the <a>node shape</a> <code>$reifierShape</code> with the <a>reifier</a> as <a>focus node</a> produces a <a>failure</a>.
Otherwise, if the <a>reifiers</a> of <code>t</code> do not conform to <code>$reifierShape</code>, there is a validation result with <code>t</code> as <code>sh:value</code>.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"if the reifiers" is unclear: do you mean any of them or all of them, some etc. Better write it like "For each reifier t that does not conform..."


sh:reifierShape
a rdf:Property ;
rdfs:label "reifiable by"@en ;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> "reifier shape"

@HolgerKnublauch
Copy link
Contributor

I have approved this for now, but I expect further changes will happen in follow-up tickets. It is important though to get this into the main branch to have a starting point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for RDF 1.2 triple terms
4 participants