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

DataResource with non-rdf DataRepresentation #476

Open
trueg opened this issue Jul 8, 2021 · 4 comments
Open

DataResource with non-rdf DataRepresentation #476

trueg opened this issue Jul 8, 2021 · 4 comments
Labels
enhancement ticket proposing an improvement, extension of exisitng or new features

Comments

@trueg
Copy link

trueg commented Jul 8, 2021

I am trying to describe a connector which provides a typical RESTful endpoint that returns JSON blobs.
Sadly I could not find a way to specify the schema, maybe I am missing something, the examples seem partially out-of-date and partially wrong.
Thus, in the spirit of starting a possible discussion let me provide an idea of how such a thing could be achieved:

Imagine the following resource with a bunch of IDEA tags:

{
      "@type": "ids:DataResource",
      "@id": "con:Resource1",
      "ids:shapesGraph": "IDEA: url where shapes for the idea:resourceType can be found",
      "idea:resourceType": "IDEA: url of the rdf class provided by the resource",
      "ids:representation": [
        {
          "@type": "ids:DataRepresentation",
          "@id": "con:Representation1",
          "ids:mediaType": {
            "@type": "ids:IANAMediaType",
            "@id": "https://www.iana.org/assignments/media-types/application/json"
          },
          "idea:schema": {
            "@type": "idea:JsonSchema",
            "@id": "con:HazardSchema",
            "idea:schemaFile": "harzards.json",
            "idea:schemaMapping": "IDEA: url pointing to the RML (RDF Mapping Language) mappings from json schema to idea:resourceType above"
          }
        }
      ]

Now as you can see the idea is to provide more than just the SHACL shapes as IMHO they are not sufficient to know what kind of data is returned. We also need the RDF class acting as the actual result type (idea:resourceType).
Given that we know which kind of class the ids:Resource will return, the SHACL shapes describe which properties are included.

The next step is to describe the ids:DataRepresentation which as mentioned before is not RDF, but plain JSON. We can use a json schema definition for that (idea:JsonSchema as a subclass of sth like idea:Schema with other sub-classes like idea:XmlSchema or whatever one needs).

Finally we need to map the json schema to the RDF class referenced on the resource. We can do that via an RML mapping.

With that we have the full round-trip from anything to RDF.

Thoughts? Does this make sense? At least partially? Does sth like this already exist in IDS and I merely missed it?

@HaydarAk
Copy link

Hi!

I am trying to describe a connector which provides a typical RESTful endpoint that returns JSON blobs.
Sadly I could not find a way to specify the schema, maybe I am missing something, the examples seem partially out-of-date and partially wrong.

We have two properties to define schemas / standards the content conforms to. The current model provides ids:contentStandard (for ids:DigitalContent and therefore also for ids:Resource ) and ids:representationStandard for ids:Representation. Both properties have IRIs as ranges, so one can point to the given schemas/standards.


We also need the RDF class acting as the actual result type (idea:resourceType).

What is the idea behind this property ?


In general, I like your idea with idea:schema. I have some thoughts / concerns regarding some parts.

  • "@type": "idea:JsonSchema" --> In recent updates, we mostly discarded the approach to model everything as classes / instnaces in the Information Model, if we cannot ensure that we have full coverage (e.g. by using standardized lists). I would rather not provide classes like JSONSchema, XMLSchema as hardcoded fields. There will be scenarios where someone will ask for additional schema / standard classes. The past showed that this is not easy to maintain. My approach would be to provide the upper class, such as ids:Schema, and allow people to extend this with custom subclasses or by using text fields as datatype properties to specify the type.

  • "idea:schemaMapping" --> how is that related to the idea:resourceType ?

@trueg
Copy link
Author

trueg commented Jul 13, 2021

Thank you very much for answering, Haydar,

I am trying to describe a connector which provides a typical RESTful endpoint that returns JSON blobs.
Sadly I could not find a way to specify the schema, maybe I am missing something, the examples seem partially out-of-date and partially wrong.

We have two properties to define schemas / standards the content conforms to. The current model provides ids:contentStandard (for ids:DigitalContent and therefore also for ids:Resource ) and ids:representationStandard for ids:Representation. Both properties have IRIs as ranges, so one can point to the given schemas/standards.

I think I missed those. Does that mean I could in theory use these to point to a specific class, let's say ex:UserAccount, a class representing a user account.

We also need the RDF class acting as the actual result type (idea:resourceType).

What is the idea behind this property ?

The idea was to link to a specific class like ex:UserAccount to define the data type an endpoint would return.

In general, I like your idea with idea:schema. I have some thoughts / concerns regarding some parts.

  • "@type": "idea:JsonSchema" --> In recent updates, we mostly discarded the approach to model everything as classes / instnaces in the Information Model, if we cannot ensure that we have full coverage (e.g. by using standardized lists). I would rather not provide classes like JSONSchema, XMLSchema as hardcoded fields. There will be scenarios where someone will ask for additional schema / standard classes. The past showed that this is not easy to maintain. My approach would be to provide the upper class, such as ids:Schema, and allow people to extend this with custom subclasses or by using text fields as datatype properties to specify the type.

I can understand that. My idea was to provide a way that mapping of data using different schemas can be automated. The example used a json schema as it is probably the most widely used plain-text serialization these days. Thus, the representation would include a standardized description of the actual schema.

Of course one could imagine maintaining these schema "standards" outside of the IDS like you said. One would have to see how this fits with the RML approach below.

Let's again use an example:

The endpoint returns JSON blobs which look something like:

{
  "username": "foobar",
  "firstName": "Foo",
  "lastName": "Bar",
  "email": "foo@bar.com"
}

Now I would like to be able to specify a mapping that allows the automatic conversion of such a json blob into an instance of ex:UserAccount. This is where your last question comes in:

  • "idea:schemaMapping" --> how is that related to the idea:resourceType ?

The idea:resourceType would be ex:UserAccount. The idea:schemaMapping would point to an RML mapping which converts the json blob we see above into an instance of ex:UserAccount, ie. the idea:resourceType (which might actually be ids:contentStandard, I am not entirely sure).

I hope these explanations helped in understanding my idea.

@clange
Copy link
Member

clange commented Jul 21, 2021

@trueg thank you for contributing these highly interesting ideas. Indeed there are some things we may have to implement. For now, let me shed a bit further light on what we already have. The current state is that the IDS RAM only prescribes an RDF semantics on the metadata level (i.e., by requiring components to "speak" the infomodel language), whereas on the content/payload level it is merely strongly recommended to use semantic standards.

Nevertheless, we have made steps towards enabling the infomodel to talk about the structure and semantics of the content of resources, and ids:shapesGraph (just literally reusing sh:shapesGraph) is one of them. Obviously, ids:shapesGraph can be used when the resource holds an RDF graph. However, our intention was that it could also be used to describe resources that could be mapped to RDF, but so far we have not made explicit how to specify how a resource can be mapped to RDF (i.e., what you are suggesting with idea:schemaMapping, which I like). In a similar direction, we have thought about using VoID to talk on a less strict level about what vocabularies (and classes/properties from them) an ids:Resource / ids:Representation is using (or, again, what the RDF graph is using that the resource could be mapped to), and, for data cube / matrix like data resources, we have thought about the Data Cube Vocabulary. For SHACL, we have worked out examples, whereas for VoID and Data Cube, we have rather just talked about the idea (see slide 15). Similar uses of CSV on the Web are in the making.

I also like your idea:resourceType idea. In the general case, this property is not applicable, because an ids:Resource does not necessarily have a type that's more specific than ids:Resource – it might just be some XML or JSON document or some RDF graph, which contains resources that are instances of more specific types, but which in itself is not an instance of a specific type. Still, I'm seeing the use case: that an ids:Resource "is" an RDF graph with a single "root" node :root rdf:type ex:Type, further triples :root <p> <o> and possibly further resources, but only if they are connected to :root via outgoing edges. (I wonder whether such a "single-resource graph" is something you can formalize as a SHACL shape.)

A further requirement in this setting might be that the URI of this root node is the same as the URI of the ids:Resource. Again, to be honest, it has so far been underspecified what the URIs of ids:Resources should look like, for the following reasons:

  • An ids:Resource does not float around freely. It comes into existence in the catalog of a Connector, which the Connector advertises to a Broker.
  • The standard way of accessing the content of an ids:Resource is not to dereference its URI, but to look for whether any endpoints are specified from which the content can be retrieved (e.g., as a file dump or via API calls).
  • Given that access restrictions apply (at least the question of whether or not you are a member of a data space), we are not in a 100% Linked Open Data setting anyway. But, yes, I am in favor of still following the Linked Data principles as closely as possible.

@trueg
Copy link
Author

trueg commented Jul 26, 2021

As discussed in our meeting last week I created a full example of a resource with a schema mapping. Please bear with me as this is a long one.

Let me start by saying that I build on my original idea but simplified it considerably. There are only two new entities as part of the ids namespace involved (I put them into an ids extended ns for clarity).

On to the actual example which I have split up into several graphs (using trig here because I like it), each of which I will go into some more detail on.

Prefixes

Throughout the graphs I will use the following prefixes:

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ids: <https://w3id.org/idsa/core/> .
@prefix idse: <https://w3id.org/idsa/ext/> .
@prefix mbh: <https://www.daimler.com/drm/hazards#> .
@prefix mbhs: <https://www.daimler.com/drm/hazards/shapes#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix rr: <http://www.w3.org/ns/r2rml#>.
@prefix rml: <http://semweb.mmlab.be/ns/rml#>.
@prefix ql: <http://semweb.mmlab.be/ns/ql#>.
@prefix drm: <https://datenraummobilitaet.de/model/core/v1#> .
@prefix drmh: <https://datenraummobilitaet.de/model/hazard/v1#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

Graph 1: The Mediatype

This is a simple one which I just include for clarity.

{
  <https://www.iana.org/assignments/media-types/application/json> a ids:IANAMediaType .
}

Graph 2: The Domain Ontology

The following graph describes the domain ontology, in this case it is an excerpt of the hazard warnings. This is the pseudo-standard that consumers should be able to work with eventually and which is the target ontology for the schema mappings below.

I went a bit overboard here and added too much detail for an example but I guess you just have to deal with that ;)

drmh: {
  drmh:Hazard a owl:Class ;
    rdfs:label "Hazard"@en .

  drmh:HazardType a owl:Class ;
    rdfs:label "Hazard Type"@en .

  drmh:Obstruction a drmh:HazardType ;
    drmh:sensorisId "OBSTRUCTION"^^xsd:string ;
    rdfs:comment "Obstruction such as fallen trees, parts of tires etc. (TPEG-TEC 10.0). Can be defined in more detail within the message RoadObstructionCondition."@en .

  drmh:Accident a drmh:HazardType ;
    drmh:sensorisId "ACCIDENT"^^xsd:string ;
    rdfs:comment """Accident (TPEG-TEC 2.0)."""@en .

  drmh:BrokenDownVehicle a drmh:HazardType ;
    drmh:sensorisId "BROKEN_DOWN_VEHICLE"^^xsd:string ;
    rdfs:comment """Vehicle breakdown of ego vehicle or any similar event of ego vehicle stopped on the road, that might pose a risk to other road users."""@en .

  drmh:SlowVehicle a drmh:HazardType ;
    drmh:sensorisId "SLOW_VEHICLE"^^xsd:string ;
    rdfs:comment """Very slow vehicle, e.g. agriculture vehicles, road service vehicles, grass cutters etc. (TPEG-TEC 16.0)."""@en .

  drmh:WrongWayVehicle a drmh:HazardType ;
    drmh:sensorisId "WRONG_WAY_VEHICLE"^^xsd:string ;
    rdfs:comment """Vehicle driving opposite the allowed direction of travel (TPEG-TEC 14.0)."""@en .

  drmh:Roadworks a drmh:HazardType ;
    drmh:sensorisId "ROADWORKS"^^xsd:string ;
    rdfs:comment """Roadworks (TPEG-TEC 3.0)."""@en .

  drmh:SlipperyRoad a drmh:HazardType ;
    drmh:sensorisId "SLIPPERY_ROAD"^^xsd:string ;
    rdfs:comment """Slippery road."""@en .

  drmh:PeopleThrowingObjects a drmh:HazardType ;
    drmh:sensorisId "PEOPLE_THROWING_OBJECTS"^^xsd:string ;
    rdfs:comment """People throwing objects."""@en .

  drmh:VehicleOnFire a drmh:HazardType ;
    drmh:sensorisId "VEHICLE_ON_FIRE"^^xsd:string ;
    rdfs:comment """Vehicle on fire."""@en .

  drmh:StationaryVehicle a drmh:HazardType ;
    drmh:sensorisId "STATIONARY_VEHICLE"^^xsd:string ;
    rdfs:comment """Stationary non-ego vehicle, that might pose a risk to ego-vehicle or other road users."""@en .

  drmh:ExceptionalConditionLowVisibility a drmh:HazardType ;
    drmh:sensorisId "EXCEPTIONAL_CONDITION_LOW_VISIBILITY"^^xsd:string ;
    rdfs:comment """Exceptional low visibility condition. Can be defined in more details within the message VisibilityCondition."""@en .

  drmh:ExceptionalConditionPrecipitation a drmh:HazardType ;
    drmh:sensorisId "EXCEPTIONAL_CONDITION_PRECIPITATION"^^xsd:string ;
    rdfs:comment """Exceptional precipitation condition. Can be defined in more details within the message Precipitation."""@en .

  drmh:ExceptionalConditionWind a drmh:HazardType ;
    drmh:sensorisId "EXCEPTIONAL_CONDITION_WIND"^^xsd:string ;
    rdfs:comment """Exceptional wind condition. Can be defined in more details within the message WindCondition."""@en .

  drmh:ExceptionalConditionRoadSurface a drmh:HazardType ;
    drmh:sensorisId "EXCEPTIONAL_CONDITION_ROAD_SURFACE"^^xsd:string ;
    rdfs:comment """Exceptional road surface condition. Can be defined in more details within the message RoadSurfaceCondition."""@en .

  drmh:ExceptionalConditionVulnerableRoadUser a drmh:HazardType ;
    drmh:sensorisId "EXCEPTIONAL_CONDITION_VULNERABLE_ROAD_USER"^^xsd:string ;
    rdfs:comment """Exceptional vulnerable road user condition. Can be defined in more details within the message VulnerableRoadUserCondition."""@en .

  drmh:sensorisId a owl:DatatypeProperty ;
    rdfs:label "Sensoris ID"@en ;
    rdfs:comment "An optional ID mapping an invididual to its Sensoris counterpart."@en ;
    rdfs:range xsd:string .

  drmh:Direction a owl:Class ;
    rdfs:label "Direction"@en .

  drmh:EgoDirection a drmh:Direction ;
    drmh:sensorisId "EGO_DIRECTION"^^xsd:string ;
    rdfs:comment "In ego vehicle driving direction."@en .

  drmh:OppositeDirection a drmh:Direction ;
    drmh:sensorisId "OPPOSITE_DIRECTION"^^xsd:string ;
    rdfs:comment "Opposite to ego vehicle driving direction."@en .

  drmh:EgoAndOppositeDirection a drmh:Direction ;
    drmh:sensorisId "BOTH"^^xsd:string ;
    rdfs:comment "In and opposite to ego vehicle driving direction."@en .

  drmh:Heading a owl:Class ;
    rdfs:subClassOf drmh:Direction ;
    rdfs:label "Heading"@en .

  drmh:headingDegree a owl:DatatypeProperty ;
    rdfs:domain drmh:Heading ;
    rdfs:range xsd:double ;
    rdfs:label "Heading"@en ;
    rdfs:comment """Orientation of driving direction at time of event. A direction of 0 degree means north, 90 degree east, 180 degree south and 270 degree west.

Granularity (Unit): 0.0125 (degree)

Minimum value: 0.0°

Maximum value: 360.0°"""@en .

  drmh:direction a owl:ObjectProperty ;
    rdfs:label "Direction"@en ;
    rdfs:comment "Direction describes the direction or heading of the hazard."@en ;
    rdfs:domain drmh:Hazard ;
    rdfs:range drmh:Direction .

  drmh:hazardType a owl:ObjectProperty ;
    rdfs:label "Hazard Type"@en ;
    rdfs:domain drmh:Hazard ;
    rdfs:range drmh:HazardType .

  drmh:confidence a owl:DatatypeProperty ;
    rdfs:label "Confidence"@en ;
    rdfs:domain drmh:Hazard ;
    rdfs:range xsd:integer .
}

Graph 3: The Shapes Graph

This is the graph containing the SHACL shapes for the domain ontology as used in the resource definition below.

mbhs: {
  mbhs:Hazard a sh:NodeShape ;
    sh:targetClass drmh:Hazard ;
    sh:property [
      a sh:PropertyShape ;
      sh:path drmh:direction ;
      sh:maxCount 1
    ] , [
      a sh:PropertyShape ;
      sh:path drmh:confidence ;
      sh:minCount 1 ;
      sh:maxCount 1 ;
      sh:minInclusive 0 ;
      sh:maxInclusive 100
    ] , [
      a sh:PropertyShape ;
      sh:path drmh:hazardType ;
      sh:maxCount 1
    ] .

  mbhs:Heading a sh:NodeShape ;
    sh:targetClass drmh:Heading ;
    sh:property [
      a sh:PropertyShape ;
      sh:path drmh:headingDegree ;
      sh:minCount 1 ;
      sh:maxCount 1 ;
      sh:minInclusive 0.0 ;
      sh:maxExclusive 360.0
    ] .
}

Graph 4: The Resource

This is the interesting one: it contains the resource definition as well as the RML mapping (a set of rr:TripleMap instances). I simply used the same graph for the resource and the mappings since the cross-reference each-other. Each triple map references the artifact it maps as its source.

This graph contains one FIXME in that I introduced a new represenation instance type that has no other properties. This feels weird to me but AFAICS we need an artifact for each represenation, at least the documentation for the connector itself deals with artifacts only.

mbh: {
  mbh:HazardResource a ids:Resource ;
    ids:title "Daimler Hazard Warnings"@en ;
    ids:shapesGraph mbhs: ;
    ids:representation mbh:HazardJsonRep .

  mbh:HazardJsonRep a ids:DataRepresentation ;
    ids:mediaType <https://www.iana.org/assignments/media-types/application/json> ;
    idse:schemaMappingGraph mbh: ;
    ids:instance mbh:HazardJsonArtifact .

  mbh:HazardJsonArtifact a ids:DynamicArtifact ;
    rdfs:comment "FIXME: The instance of the representation does not have any other attributes. It seems superfluous that way, except that the messaging system requires a representation."@en .

  [] a rr:TriplesMap ;
    rml:logicalSource [
      rml:source mbh:HazardJsonArtifact ;
      rml:referenceFormulation ql:JSONPath ;
      rml:iterator "$.result[*]"
    ] ;
    rr:subjectMap [
      rr:template "urn:hazards:daimler:hazard:{uuid}" ;
      rr:class drmh:Hazard
    ] ;
    rr:predicateObjectMap [
      rr:predicate drmh:direction ;
      rr:objectMap [
        rr:template "urn:hazards:daimler:heading:{uuid}" ;
        rr:termType rr:IRI
      ]
    ] , [
      rr:predicate drmh:confidence ;
      rr:object "100"^^xsd:integer
    ] .

  [] a rr:TriplesMap ;
    rml:logicalSource [
      rml:source mbh:HazardJsonArtifact ;
      rml:referenceFormulation ql:JSONPath ;
      rml:iterator "$.result[?(@.cause=='Broken down vehicle')]"
    ] ;
    rr:subjectMap [
      rr:template "urn:hazards:daimler:hazard:{uuid}"
    ] ;
    rr:predicateObjectMap [
      rr:predicate drmh:hazardType ;
      rr:object drmh:BrokenDownVehicle
    ] .

  [] a rr:TriplesMap ;
    rml:logicalSource [
      rml:source mbh:HazardJsonArtifact ;
      rml:referenceFormulation ql:JSONPath ;
      rml:iterator "$.result[?(@.cause=='Heavy rain')]"
    ] ;
    rr:subjectMap [
      rr:template "urn:hazards:daimler:hazard:{uuid}"
    ] ;
    rr:predicateObjectMap [
      rr:predicate drmh:hazardType ;
      rr:object drmh:ExceptionalConditionPrecipitation
    ] .

  [] a rr:TriplesMap ;
    rml:logicalSource [
      rml:source mbh:HazardJsonArtifact ;
      rml:referenceFormulation ql:JSONPath ;
      rml:iterator "$.result[?(@.cause=='Slippery road')]"
    ] ;
    rr:subjectMap [
      rr:template "urn:hazards:daimler:hazard:{uuid}"
    ] ;
    rr:predicateObjectMap [
      rr:predicate drmh:hazardType ;
      rr:object drmh:SlipperyRoad
    ] .

  [] a rr:TriplesMap ;
    rdfs:comment "Generates the Heading resources a referenced by the Hazard resources."@en ;
    rml:logicalSource [
      rml:source mbh:HazardJsonArtifact ;
      rml:referenceFormulation ql:JSONPath ;
      rml:iterator "$.result.[*]"
    ] ;
    rr:subjectMap [
      rr:template "urn:hazards:daimler:heading:{uuid}" ;
      rr:class drmh:Heading
    ] ;
    rr:predicateObjectMap [
      rr:predicate drmh:headingDegree ;
      rr:objectMap [
        rml:reference "heading" ;
        rr:datatype xsd:integer
      ]
    ] .
}

Graph 5: The IDS Extensions

Finally we have the two entities which I mentioned in the beginning. I envision these as being part of the ids: ns in the end but I opted for idse: in this example to emphasize their novelty.

idse: {
  idse:DynamicArtifact a owl:Class ;
    rdfs:subClassOf ids:RepresentationInstance ;
    rdfs:label "dynamic artifact"@en ;
    rdfs:comment "Instance of a Representation materialized through an I/O operation like a network request. FIXME: what about artifact request messages? How does one request another instance?"@en .

  idse:schemaMappingGraph a owl:ObjectProperty ;
    rdfs:domain ids:Representation ;
    rdfs:range xsd:anyURI ;
    rdfs:label "schema mapping graph"@en ;
    rdfs:comment "Reference to an RML schema mapping graph which contains triple maps translating data from specific artifacts to RDF resources honoring the domain-specifics defined in a SHACL graph."@en .
}

Again we have a FIXME since I am confused by the fact that the reference implementation of the connector deals in artifacts only while there are different RepresentationInstance types. Maybe this is not a problem at all.

Graph 6: The Result

Just for clarity I ran the RML engine through the following example:

{
 "result" : [ {
  "cancelled" : true,
  "cause" : "Broken down vehicle",
  "heading" : 42.2,
  "location" : [ [ 42.2 ] ],
  "trace" : [ [ 42.2 ] ],
  "ts" : 42,
  "uuid" : "123456789"
 } , {
  "cancelled" : true,
  "cause" : "Vehicle accident",
  "heading" : 42.2,
  "location" : [ [ 42.2 ] ],
  "trace" : [ [ 42.2 ] ],
  "ts" : 42,
  "uuid" : "523456789"
 } , {
  "cancelled" : true,
  "cause" : "Slippery road",
  "heading" : 42.2,
  "location" : [ [ 42.2 ] ],
  "trace" : [ [ 42.2 ] ],
  "ts" : 42,
  "uuid" : "623456789"
 } , {
  "cancelled" : true,
  "cause" : "Heavy rain",
  "heading" : 42.2,
  "location" : [ [ 42.2 ] ],
  "trace" : [ [ 42.2 ] ],
  "ts" : 42,
  "uuid" : "323456789"
 }
],
 "next_page_token" : "string"
}

As a result we get the following domain-specific RDF blob:

<urn:hazards:daimler:hazard:123456789> a drmh:Hazard;
  drmh:confidence "100";
  drmh:direction <urn:hazards:daimler:heading:123456789>;
  drmh:hazardType drmh:BrokenDownVehicle .

<urn:hazards:daimler:hazard:323456789> a drmh:Hazard;
  drmh:confidence "100";
  drmh:direction <urn:hazards:daimler:heading:323456789>;
  drmh:hazardType drmh:ExceptionalConditionPrecipitation .

<urn:hazards:daimler:hazard:523456789> a drmh:Hazard;
  drmh:confidence "100";
  drmh:direction <urn:hazards:daimler:heading:523456789> .

<urn:hazards:daimler:hazard:623456789> a drmh:Hazard;
  drmh:confidence "100";
  drmh:direction <urn:hazards:daimler:heading:623456789>;
  drmh:hazardType drmh:SlipperyRoad .

<urn:hazards:daimler:heading:123456789> a drmh:Heading;
  drmh:headingDegree "42.2"^^xsd:integer .

<urn:hazards:daimler:heading:323456789> a drmh:Heading;
  drmh:headingDegree "42.2"^^xsd:integer .

<urn:hazards:daimler:heading:523456789> a drmh:Heading;
  drmh:headingDegree "42.2"^^xsd:integer .

<urn:hazards:daimler:heading:623456789> a drmh:Heading;
  drmh:headingDegree "42.2"^^xsd:integer .

And that is it. If you got this far then you have my gratitude. Looking forward to discussing this in more detail very soon.

@HaydarAk HaydarAk added the enhancement ticket proposing an improvement, extension of exisitng or new features label Oct 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement ticket proposing an improvement, extension of exisitng or new features
Projects
None yet
Development

No branches or pull requests

3 participants