w3c / wot-thing-description

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

Additional composition mechanism for Thing Models #1407

Open JKRhb opened 2 years ago

JKRhb commented 2 years ago

Dealing with the conversion between SDF and WoT, I noticed a while ago that translating between nested models in both specifications is somewhat challenging due to the fact that in WoT you can only use links. This makes it difficult to work with a results from an SDF to WoT conversion, as submodels/subthings need to be stored somewhere to be able to be referred to in links.

For example, in order to work with the TM in the current Example 57 (see an extract below) in memory and access its submodels, you would need to have them in the current working directory, as their links are pointing to ./Ventilation.tm.jsonld and ./LED.tm.jsonld, respectively.

{
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "@type": "tm:ThingModel",
    "title": "Smart Ventilator Thing Model",
    "links": [
      {
        "rel": "tm:submodel",
        "href": "./Ventilation.tm.jsonld",
        "type": "application/tm+json",
        "instanceName": "ventilation"
      },
      {
        "rel": "tm:submodel",
        "href": "./LED.tm.jsonld",
        "type": "application/tm+json",
        "instanceName": "led"
      }
    ]
    ...
  }

Similarly, if you want to convert a nested SDF model to WoT, you always need to store the submodels of reulting TMs somewhere, making it also difficult to implement web based converters, for instance.

In order to make working with TMs and their conversion easier, I therefore wanted to propose an alternative to the current mechanism by introducing a new field called tm:submodels that could be used to include a map of Thing Models. These submodels could be converted into links, either to export a Thing Model from a converter and during TM -> TD conversion. Therefore, the linking approach can still be used but would be more relevant for a different scenario, for example if you have single models in a directory structure that are waiting to be converted into TDs.

An adapted version of the example using this alternative approach above could look like the following:

{
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "@type": "tm:ThingModel",
    "title": "Smart Ventilator Thing Model",
    "tm:submodels": {
        "ventilation": {
            "@context": "https://www.w3.org/2022/wot/td/v1.1",
            "@type": "tm:ThingModel",
            "title": "Ventilator Thing Model",
            ...
            "tm:submodels": {
                "anotherLevelOfThingModelNesting": {
                    ...
                }
            }
        },
        "led": {
            "@context": "https://www.w3.org/2022/wot/td/v1.1",
            "@type": "tm:ThingModel",
            "title": "LED Thing Model",
            ...
        }
    },
    ...
  }

This seems to also still be a valid JSON LD document as you can override the @context in child objects (see https://json-ld.org/spec/latest/json-ld/#advanced-context-usage).

I know that this is probably a bit too late to still be included in this version of the specification, but I still wanted to make the suggestion as I think it addresses a hindrance when using WoT as a conversion target.

egekorkan commented 2 years ago

Call of 02.03:

@thjaeckle what do you think of this proposal?

JKRhb commented 2 years ago

I adjusted the title of the issue to make it more clear that this would be an additional approach for nested, not an alternative one 🙂

thjaeckle commented 2 years ago

I think that many of the benefits of ThingModels kind of get lost with this additional approach.

Mapped to the "object oriented world" (which I like to do in order to get my head around the ThingModel vs. ThingDescription concepts - a class as the analogy for a ThingModel and an instance of that class as the analogy for a ThingDescription) this would basically mean:

So in pseudo-code the "current approach" with linking would translate to e.g.:

class Lamp {
  boolean on;
}

class FloorLamp {
  Lamp spot1;
  Lamp spot1;
}

class TrafficLight {
  Lamp green;
  Lamp yellow;
  Lamp red;
}

And in pseudo-code the "additional approach" with inlining the submodels would translate to e.g.:

class FloorLamp {
  FloorLamp.Lamp spot1;
  FloorLamp.Lamp spot1;

  class Lamp {
    boolean on;
  }
}

class TrafficLight {
  TrafficLight.Lamp green;
  TrafficLight.Lamp yellow;
  TrafficLight.Lamp red;

  class Lamp {
    boolean on;
  }
}

Doing it that way this would mean:

So in my opinion this would be a really bad idea, however I do not know SDF models or nested SDF models and the problem this additional composition mechanism should solve.

What I think could make sense (if that helps for SDF model mapping or for Scripting) is to have something like an "effective ThingModel" (maybe declared by another "type") - which would resolve all of the tm:submodel links and inline those models into a representation of the TM which could look similar to the proposal. A tool could produce such "effective" ThingModels - but specifying it in a way to be an alternative to the "links" will probably lead to misuse.

JKRhb commented 2 years ago

What I think could make sense (if that helps for SDF model mapping or for Scripting) is to have something like an "effective ThingModel" (maybe declared by another "type") - which would resolve all of the tm:submodel links and inline those models into a representation of the TM which could look similar to the proposal. A tool could produce such "effective" ThingModels - but specifying it in a way to be an alternative to the "links" will probably lead to misuse.

That sounds like a good idea! As I wrote above, I think this nested approach would be useful for certain use cases such as conversion but you are right that the "end result" should still be in accordance with the linking approach.

Another alternative for expressing an "effective" model that would also allow the re-use of links could be using JSON pointers, like so for example:

{
  "baseModel": {
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "@type": "tm:ThingModel",
    "title": "Smart Ventilator Thing Model",
    "links": [
      {
        "rel": "tm:submodel",
        "href": "#/ventilation",
        "type": "application/tm+json",
        "instanceName": "ventilation"
      },
      {
        "rel": "tm:submodel",
        "href": "#/LED",
        "type": "application/tm+json",
        "instanceName": "led"
      }
    ]
  },
  "ventilation": {
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "@type": "tm:ThingModel",
    "title": "Ventilator Thing Model",
    "links": [
      {
        "rel": "tm:submodel",
        "href": "#/ventilationSubmodel",
        "type": "application/tm+json",
        "instanceName": "ventilationSubmodel"
      }
    ]
  },
  "LED": {
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "@type": "tm:ThingModel",
    "title": "LED Thing Model"
  },
  "ventilationSubmodel": {
    "@context": "https://www.w3.org/2022/wot/td/v1.1",
    "@type": "tm:ThingModel",
    "title": "Submodel of a Ventilator"
  }
}

This would also allow the direct translation of models into JSON files as the map keys could be used as file names (minus the .tm.jsonld). The only downside I would see here is that a hierachy of TMs isn't visible right away. And, of course, that this isn't a standalone Thing Model but rather a collection of TMs.

Edit: Maybe this could also simply be used internally by implementations for keeping submodels in memory and does not need to go into the specification itself.

sebastiankb commented 2 years ago

from today's TD call: