ODP: Hydra<>SHACL integration

Hi Dietrich

I think the best approach would be to apply Shacl to ... your operation. I'd go with this:

{ ...
  "@id": "http://localhost:8080/webapp/hypermedia-api/events/1",
  "hydra:operation": [
  {
    "hydra:method": "PUT",
    "hydra:expects":
    {
      "@id": "Event",
      "hydra:supportedProperty": [
      {
        "hydra:property": "eventStatus",
        "hydra:required": true,
      }]
    }
  }],
  "sh:nodeShape": {
    "@type": "sh:Shape",
    "sh:property" : {
      "sh:predicate": "hydra:expects",
      "sh:allowedValues" : {
        "@list": [
          "schema:EventCancelled",
          "schema:EventPostPoned"
        ]
       }
      }
   }
}

In this case your operation is an instance with Iri assigned, thus it's valid for sh:nodeShape.

BTW, it looks you incorrectly stated a @type: Event. I think it should be @id: Event. This way Hydra, where hydra:expects predicate expects a hydra:Class, will be OK with reasoners. Otherwise a resource of type Event ([] a schema:Event) would end up with being a hydra:Class (correct me if I'm wrong).

Regards

Karol Szczepański


Od: Dietrich Schulten
Wysłano: niedziela, 20 września 2015 14:05
Do: Hydra
Temat: Hydra<>SHACL integration


Hi,

I am looking into SHACL[1] with Hydra.

In SHACL one can describe a set of property constraints for instances.

ex:AllowedValuesExampleShape
 a sh:Shape ;
 sh:property [
  sh:predicate schema:eventStatus ;
  sh:allowedValues ( schema:EventCancelled,
                  schema:EventScheduled, schema:EventPostPoned ) ;
 ]

If I understand the SHACL spec draft[2] correctly, this shape can be
applied to a scope:

1. by an individuum which adopts the shape via a sh:nodeShape property
whose value must be an IRI such as ex:AllowedValuesExampleShape, stating
that this individual satisfies AllowedValuesExampleShape.

2. by the shape which can apply itself to an rdfs:class via
sh:scopeClass, which says that every single individuum of that
rdfs:class must satisfy the shape

3. by the shape which can define "scope selectors" for subjects having a
certain predicate, or objects of a certain predicate, or for all
subjects or objects in a given graph


In Hydra we say that a method expects a certain type and we can make
statements about its properties, e.g. below I say that the
schema:eventStatus is a required property for a PUT request.

{
  "@context": {
    "@vocab": "http://schema.org/",
    "hydra": "http://www.w3.org/ns/hydra/core#"
  },
  "@id": "http://localhost:8080/webapp/hypermedia-api/events/1",
  "hydra:operation": [
  {
    "hydra:method": "PUT",
    "hydra:expects":
    {
      "@type": "Event",
      "hydra:supportedProperty": [
      {
        "hydra:property": "eventStatus",
        "hydra:required": true
      }]
    }
  },
  {
    "hydra:method": "DELETE"
  }]
}

How do I constrain the allowed values for eventStatus with SHACL in the
context of a Hydra response? Can I simply add sh:allowedValues as shown
below?

{
  "@context":
  {
    "@vocab": "http://schema.org/",
    "hydra": "http://www.w3.org/ns/hydra/core#",
    "sh": "http://www.w3.org/ns/shacl#"
  },
  "@id": "http://localhost:8080/webapp/hypermedia-api/events/1",
  ... event properties ...
  "hydra:operation": [
  {
    "hydra:method": "PUT",
    "hydra:expects":
    {
      "@type": "Event",
      "hydra:supportedProperty":
      {
        "hydra:property": "eventStatus",
        "hydra:required": true,
        "sh:allowedValues" : {
          "@list": [ // SHACL requires this to be an rdf:List
            "schema:EventCancelled",
            "schema:EventPostPoned"
          ]
        }
      }
    }
  },
  {
    "hydra:method": "DELETE"
  }]
}

By using sh:allowedValues I am saying that the value of
hydra:supportedProperty is not only a hydra:SupportedProperty, but also
a sh:PropertyConstraint. Does that make hydra:supportedProperty an alias
of sh:property by inference? If so, I guess that the value of
hydra:expects is now not only an Event, but also a sh:Shape.

So I am really saying that one should send a sh:Shape as request body of
the PUT - which is not what I mean to say. What I want to say is that
the client may cancel or postpone the event. For this it should send an
Event with the appropriate eventStatus value.

The following seems better, but it pushes the envelope quite a bit
because the SHACL spec specifically says that the value of sh:nodeShape
must be an IRI and the subject of sh:nodeShape must be an individual. I
took the freedom to inline the nodeShape below:

{ ...
  "@id": "http://localhost:8080/webapp/hypermedia-api/events/1",
  "hydra:operation": [
  {
    "hydra:method": "PUT",
    "hydra:expects":
    {
      "@type": "Event",
      "sh:nodeShape": {
          "@type": "sh:Shape",
          "sh:property" : {
            "sh:predicate": "eventStatus",
            "sh:allowedValues" : {
              "@list": [
                "schema:EventCancelled",
                "schema:EventPostPoned"
              ]
            }
          }
        }
      "hydra:supportedProperty": [
      {
        "hydra:property": "eventStatus",
        "hydra:required": true,
      }]
    }
  }]
}

What are your thoughts how Hydra could or should integrate with Hydra?

If an inline nodeShape is a good fit, should we raise an issue with the
SHACL group to see if they can allow inline node shapes?

To me, the nodeShape scope (1.) seems to fit somewhat better than the
other scopes (2., 3.). Usually I want to constrain a request body for a
particular ReST resource, maybe even in a particular status of the
resource - but I do not want to constrain an entire class I might not
even own.

There is a second case where I think it makes sense to constrain values:
IriTemplateMapping. Similar questions arise there.


Best regards,
Dietrich

[1] https://www.w3.org/2014/data-shapes/wiki/Main_Page
[2] http://w3c.github.io/data-shapes/shacl/

Received on Sunday, 20 September 2015 18:04:52 UTC