w3c / wot-thing-description

Web of Things (WoT) Thing Description
http://w3c.github.io/wot-thing-description/
Other
131 stars 63 forks source link

uriVariables with multiple forms #1083

Open relu91 opened 3 years ago

relu91 commented 3 years ago

This issue is coming from a possible refactoring of the example Thing Description Directory TD provided in the Discovery document. In particular, it was proposed to model all different search methods as filters of a property affordance called things. See the concrete (simplified) example below:

{
  properties: {
     "things":  {
           "@type": "ThingListProperty",
            "uriVariables": {
                "id": {
                    "@type": "ThingID",
                    "type": "string",
                    "format": "iri-reference"
                },
                "jsonpath": {
                    "@type": "JSONPathExpression",
                    "type": "string"
                },
                "xpath": {
                    "@type": "XPathExpression",
                    "type": "string"
                },
                "query": {
                    "@type": "SPARQLQuery",
                    "type": "string"
                }
            },
            "forms": [
                {
                    "href": "/things/{id}"
                },
                {
                    "href": "/things?jsonpath={jsonpath}",
                },
                {
                    "href": "/things?xpath={xpath}",
                },
                {
                    "href": "/things?query={query}",
                }
            ]
        }
  }
}

As you can see the different uriVariables can be used only in one particular form as if they make sense only if used together with the right form. Notice that here splitting the things in multiple properties affordances does not really make sense.

Should we prescribe that a client can choose the right form using the input as a hint? or is it already been described in the spec?

References

egekorkan commented 3 years ago

Should we prescribe that a client can choose the right form using the input as a hint? or is it already been described in the spec?

I think you mean uriVariables as a hint. Anyways, I think this kind of an explanation needs to be added to the spec. Something that says that "multiple forms can satisfy the operation (readproperty, subscribeevent, etc.) targeted by the Consumer. In this case, the Consumer should choose a form based on the way the Consumer operates such as the protocols or contentType it supports, choice of security mechanism or other mechanisms such as uri templating"

I couldn't find a better way to say " the way the Consumer operates " :/

benfrancis commented 3 years ago

The Directory Service API is a bit of a special case because we have a concrete specification which can describe the details of how to interact with this complex property (based on either the names of the URI variables or using the semantic annotations provided in the above example, see https://github.com/w3c/wot-discovery/issues/144). A consumer which didn't implement that spec would have no chance of figuring out what all those URI variables are for.

Suggesting that consumers differentiate between forms based on URI variables assumes that the consumer has prior knowledge of the device and is expecting a particular URI variable name, which will not be the case for Thing Descriptions in general. It might be possible for a consumer to generate a very generic user interface for such a device (e.g. with a separate HTML form for each Form, with text boxes which accept a string labelled by variable name or title if provided, which can be mapped onto the URI variables). But for a non-human consumer of the API it would be essential to use semantic annotations which denote conformance to a capability schema, defined in an external common schema repository (like iotschema.org).

I therefore suggest that the recommendation should be to use semantic annotations to help consumers differentiate between different forms for the same interaction affordance, given developers are free to use whatever URI variable names they like in forms.

relu91 commented 3 years ago

The Directory Service API is a bit of a special case because we have a concrete specification which can describe the details of how to interact with this complex property (based on either the names of the URI variables or using the semantic annotations provided in the above example, see w3c/wot-discovery#144). A consumer which didn't implement that spec would have no chance of figuring out what all those URI variables are for.

Yes, that's why I opened this issue, with TDD we can describe the intended behavior in prose, but not for a generic TD (not in the current spec at least).

I therefore suggest that the recommendation should be to use semantic annotations to help consumers differentiate between different forms for the same interaction affordance, given developers are free to use whatever URI variable names they like in forms.

Yeah, semantic annotations would help but they kinda work for a specific use case (i.e., the consumer knows that the form tagged with myformtype needs myvar as a convention). I'd rather have a generic mechanism, maybe again exploiting the @type keyword? ( semantically speaking does not really make sense):

{
  properties: {
     "things":  {
           "@type": "ThingListProperty",
            "uriVariables": {
                "id": {
                    "@type": "ThingID",
                    "type": "string",
                    "format": "iri-reference"
                },
                "jsonpath": {
                    "@type": "JSONPathExpression",
                    "type": "string"
                }
            },
            "forms": [
                {
                    "href": "/things/{id}"
                },
                {
                    "href": "/things?jsonpath={jsonpath}",
                     "@type": "JSONPathExpression", // <-- I don't like it at all
                     "useVariables": "JSONPathExpression" // or again using a field to indicate the association
                }
            ]
        }
  }
}

Still, all of this feels pretty hackish and I don't have a better proposal rather than what @egekorkan is proposing OR discouraging people to use forms that have different purposes in the same affordance -> just split your affordances.

benfrancis commented 3 years ago

OR discouraging people to use forms that have different purposes in the same affordance -> just split your affordances.

This is probably good advice in general.

The reason we combined these different interactions in the Directory Service API is because the property represents a collection of resources, and there's no obvious way to model a collection in a Thing Description (we have the same problem with action queues, where we're having to invent a whole new set of vocabulary in #302).

mmccool commented 3 years ago

OR we could just go back to using different interactions (with different URLs, making them easy to distinguish), and make queries actions. This is consistent with input and output data models being different, and anyway we have to separate out the SPARQL endpoint for reasons, and making the "modularity" consistent for different query types would be nicer.

In general, assuming a "consumer" is smart enough to "figure things out" concerns me. Why make things hard on the implementor?

benfrancis commented 3 years ago

@mmccool wrote:

we could just go back to using different interactions (with different URLs, making them easy to distinguish), and make queries actions.

Are you of the opinion that it's good practice for actions to be used in cases where state is not being modified? It's still not clear from the specification when it's appropriate to use an action vs. a property (see #1020). I suggest we need a consensus on the best practice there, before specifying a normative example Thing Description (or Thing Model) which uses actions for read operations.

But regardless, this issue is not specifically about the Directory Service API in the discovery specification, it's about Thing Descriptions in general. There's also currently no guidance about interactions providing multiple forms which differ only by the URI variables being used. Solving only for the Directory Service API is dodging the more general issue.

In the general case (and in the specific case of the Directory Service API) I suggest the best practice should be to provide the consumer with semantic annotations on URI variable definitions which describe their semantic meaning (using an externally defined schema), because there's not enough information in the Thing Description alone to know how to use them.

In general, assuming a "consumer" is smart enough to "figure things out" concerns me. Why make things hard on the implementor?

FWIW this is the argument I've been making about declarative protocol bindings in Thing Descriptions all along and is why there's a need for concrete APIs defined in profiles, and capability schemas for domain specific metadata. This is a general problem, not something specific to the Directory Service API where things are actually already easier since there is a concrete specification.

benfrancis commented 3 years ago

@relu91 wrote:

semantic annotations would help but they kinda work for a specific use case (i.e., the consumer knows that the form tagged with myformtype needs myvar as a convention). I'd rather have a generic mechanism, maybe again exploiting the @type keyword?

I would have thought that in this example, adding the "@type": "JSONPathExpression" annotation to the URI variable alone should be enough information, if the schema can then define that a ThingListProperty may have a form which accepts a JSONPathExpression as a URI variable in order to filter the output. The former tells the consumer which property to use to fetch a list of things and the latter tells it which URI variable to use to filter the output using a JSONPath expression.

Or am I missing something?

egekorkan commented 3 years ago

@mmccool wrote:

This is consistent with input and output data models being different, and anyway

I think this is not the correct way to find mapping for an interaction. We should first think of the meaning of the interaction before thinking of how to represent it in a TD. I understand why you went for that direction, I used to like having outputData in properties (https://www.w3.org/TR/2017/WD-wot-thing-description-20170914/#property). It would be a breaking change but I would like to have input and output for properties which would solve this problem without breaking the meaning behind what an action is.

lu-zero commented 8 months ago

This is another item for the DataMapping use-case.