Skip to content
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

Describing operations and templates with SHACL #17

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tpluscode
Copy link
Collaborator

In this PR I propose how SHACL Shapes can augment the API descriptions

Of operation payload, by replacing the value of hydra:expects with a Shape. The hydra:returns annotation could also be extended with a Shape by analogy but I have not considered such a scenario yet.

Of IRI Templates by attaching Shape to the IriTemplate and without changing anything else about the Core usage.


Both proposed usages on SHACL with Hydra Core do not replace any terms and only extend the standard descriptions as we have them now. This way a client which does not understand SHACL will still be able to use the semantics of Hydra Core.

@tpluscode tpluscode requested review from alien-mcl and a team June 17, 2020 07:22
},
"@id": "/api",
"@type": "hydra:ApiDocumentation",
"requires": "http://www.w3.org/ns/hydra/shacl"
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

No strong opinion on the hydra:requires term and its semantics.

Alternatively I thought hydra:uses or hydra:imports

Copy link
Member

Choose a reason for hiding this comment

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

I think better approach would be just to point to the SHACL's namespace, http://www.w3.org/ns/shacl#

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe 🤔

As seen below, my intention was for http://www.w3.org/ns/hydra/shacl to mean "SHACL extensions" and itself would become a namespace for additional terms

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, I remember now. I was thinking that maybe the requirements could be more fine-grained like

<> hydra:requires hashi:OperationExpects, hashi:IriTemplate

But coming back to my first answer still. The meaning is that "the API requires SHACL extension". Which is slightly more specific than just SHACL

Copy link
Member

Choose a reason for hiding this comment

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

I'm not convinced it's good direction. I think hydra should be extended in places where it does not provide any tools - replacing them is not a good move. It's better to create a separate spec.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think hydra should be extended in places where it does not provide any tools - replacing them is not a good move

What do you mean by that? I do propose a separate spec, auxiliary to core

-http://www.w3.org/ns/hydra/core#
+http://www.w3.org/ns/hydra/shacl#

Copy link
Member

@alien-mcl alien-mcl Jun 19, 2020

Choose a reason for hiding this comment

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

I don't like an idea where terms built in hydra would be replaced with some custom ones. In your example, hashi:IriTemplate would probably replace hydra:IriTemplate. I think it's not a good approach

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Oh, no, I do not propose to replace anything.

I only wanted to propose a more fine-grained choice of which parts of the API are described with SHACL. hashi:IriTemplate indeed may have been an unfortunate choice

Copy link
Member

Choose a reason for hiding this comment

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

hashi:IriTemplate indeed may have been an unfortunate choice

Indeed - unfortunate. Could we come with a better one?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ugh, is that really necessary? It's not even mentioned in the pull request.

For the time being let's assume that only HASHI as a whole can be required, imported or used. However we choose.

"supportedOperation": {
"@type": "schema:CreateAction",
"method": "POST",
"expects": ["mov:Movie", "mov:NewMovieShape"]
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Keeps "mov:Movie" to keep backwards compatibility

Copy link
Member

Choose a reason for hiding this comment

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

This part is kind of tricky. What does the set means: is it a union or alternative?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Union, obviously. Nothing tricky. Read it like:

The operation expects mov:Movie which should conform to mov:NewMovieShape

Copy link
Member

Choose a reason for hiding this comment

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

In this very case it may be obvious, but in general it's not. Imagine a case when an operation expects i.e. good or service (which are in many cases disjoined classes). Intent was to tell the client that the operation (basket?) expects a resource of one of those types - resource being both of the classes would violate the vocabulary)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't see how this is relevant. Hydra Core would need to provide a way for alternatives just like OWL and SHACL do. Otherwise a set of objects is a union just like I would expect it anywhere else

Copy link
Member

Choose a reason for hiding this comment

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

Maybe it's not directly related to possible extensions, but I expect questions in this (and similar) situations.

Copy link
Member

Choose a reason for hiding this comment

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

Otherwise a set of objects is a union just like I would expect it anywhere else

It's not that straight forward. From pure RDF perspective it's a set of values and there is nothing supporting a statement a resource should be of all of the provided values. I'd actually prefer 'one of the possible values' rather than 'all of them'. I believe we need to specify it in the spec to avoid discrepancies.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Please don't make me look up deep in some RDF specs but I'm pretty sure that the semantics would be precisely that. If you have multiple objects of a property, then they form a set.

This is how OWL works and also how SHACL works. Hence the provide owl:oneOf and sh:or respectively to explicitly describe alternative choices without ambiguity.

If that is not enough, let's look at rdf:type. <Karol> rdf:type schema:Person, foaf:Person means that that resource has both of those types, not one of the possible values. Trying to apply different semantics to expects would IMO violate the principle of least astonishment.

{
"@context": {
"hydra": "http://www.w3.org/ns/hydra/core#",
"requires": { "@id": "hydra:requires", "@type": "@id" }
Copy link
Member

Choose a reason for hiding this comment

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

I'd rather reuse hydra:required.

},
"@id": "/api",
"@type": "hydra:ApiDocumentation",
"requires": "http://www.w3.org/ns/hydra/shacl"
Copy link
Member

Choose a reason for hiding this comment

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

I think better approach would be just to point to the SHACL's namespace, http://www.w3.org/ns/shacl#

"supportedOperation": {
"@type": "schema:CreateAction",
"method": "POST",
"expects": ["mov:Movie", "mov:NewMovieShape"]
Copy link
Member

Choose a reason for hiding this comment

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

This part is kind of tricky. What does the set means: is it a union or alternative?

api-documentation/shacl.md Show resolved Hide resolved
api-documentation/shacl.md Show resolved Hide resolved
+ "rdfs:label": "Search movies collection",
+ "sh:property": [{
+ "sh:path": "schema:genre",
+ "sh:name": "Genre",
Copy link
Member

Choose a reason for hiding this comment

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

I believe sh:name can be replaced with either hydra:title or just `rdfs:label'

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hydra:title has no meaning in SHACL context

sh:name is SHACL's method for annotating PropertyShape

I know it's weird but decided that way because rdfs:label would effectively annotate the Shape where the intention is to indirectly annotate the property 🤷

Copy link
Member

Choose a reason for hiding this comment

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

Ok, but which label client should use i.e. to build an UI?

Copy link
Collaborator Author

@tpluscode tpluscode Jun 18, 2020

Choose a reason for hiding this comment

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

Of what choice? There is only one label here (sh:name) 🙂

Copy link
Member

Choose a reason for hiding this comment

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

IriTemplate can accept hydra:title, which is prefered in context of hydra. If not provided, supported property can also have one.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I would consider a Shape as separate concerns.

So, the API describes its hypermedia with a Shape. That Shape can be then passed to a component which understand SHACL to build the UI for example and run validation. That SHACL-specific component would not be aware of Hydra though, hence I stick to only terms defined in SHACL.

The Shape is its own independent description which a Hydra client can take advantage of

+ }],
+ "hashi:shape": {
+ "@type": "sh:Shape",
+ "rdfs:label": "Search movies collection",
Copy link
Member

Choose a reason for hiding this comment

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

I think rdfs:description fits better to the text provided.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Quite irrelevant but what would you have as the label then?

Copy link
Member

Choose a reason for hiding this comment

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

Something shorter I think. Just search to feed a button?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That is rather minuscule

"property": "schema:genre"
- }]
+ }],
+ "hashi:shape": {
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand this relation. Resource <movies> is in relation <hashi:shape> with some blank node resource. How does it tell the client that values for schema:genre can be used from the given set? What if schema:genre defines already a set somewhere else (i.e. API documentation).

Copy link
Collaborator Author

@tpluscode tpluscode Jun 17, 2020

Choose a reason for hiding this comment

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

Resource <movies> is in relation <hashi:shape>

Did I get the formatting wrong? It's the IriTemplate which has that relation

some blank node resource

sh:Shape 🙄

How does it tell the client that values for schema:genre can be used from the given set?

In turtle you would have

<movies> hydra:search [
  hydra:mapping [
    hydra:property schema:genre
  ] ;
  hashi:shape [
    sh:property [
      sh:path schema:genre ;
      sh:in ( "Comedy" "Drama" )
    ]
  ]
] .

To populate the template a resource is constructed which has the schema:genre property.
hydra:mapping informs the client how to map it to the template variables
hashi:shape provides information about the resource constraints

What if schema:genre defines already a set somewhere else (i.e. API documentation).

You're looking for something which is not there. I know not of an alternative way to define such a set other than SHACL. And even so, I think that those SHACL descriptions would be applied locally and trump one defined elsewhere

Copy link
Member

Choose a reason for hiding this comment

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

I think that those SHACL descriptions would be applied locally and trump one defined elsewhere

I'm not sure I understand. I believe these kind of descriptions could be applied both on API documentation and resource level. I imagine situation where an API documentation says that property schema:genre in shape Movie can accept any value taken from the list. But a resource description gives another list. How those are related to each other?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Again, it's a little bit out of scope of this constrained example. Sure, the sh:property could somehow reference a shared list of elements, defined in the API Documentation. Sounds like a good idea.

In the first version of an actual HASHI spec I would also define a way to refer to a hydra:Collection so that the choices can be loaded from the API itself.

Either case however goes beyond what I want to propose here, which is extending the IRI Template definition with a Shape by the use of hashi:shape property

@tpluscode tpluscode requested a review from alien-mcl June 17, 2020 21:31
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.

2 participants