VIADE data model specification

Living Document,

This version:
https://arquisoft.github.io/viadeSpec/
Issue Tracking:
GitHub
Editors:
Hugo Lebredo Bujan (University of Oviedo)
Irece Cid Rico (University of Oviedo)
Jose Emilio Labra Gayo (WESO Research group)
Pablo González González (University of Oviedo)

Abstract

This document describes the VIADE data model for Solid based route descriptions.

Status of This Document

This document is an incomplete draft.

You are invited to contribute any feedback, comments, or questions you might have.

1. Introduction

The VIADE data model contains a specification for a common data model to represent routes in RDF inside Solid data Pods. The data model has been prepared by the teachers and students of the Software Architecture course as part of the 2019-20 edition. The assignment description consists in the implementation of Solid based apps for route management. In order to improve the interoperability between those apps, a common data model is required and this document is an attempt to provide one.

1.1. Definitions

A data pod is a place for storing documents, with mechanisms for controlling who can access what.

A Solid app is an application that reads or writes data from one or more data pods.

1.2. Namespaces

Prefix Namespace Description
gpx https://www.w3.org/ns/pim/gpx# [GPX]
ldp http://www.w3.org/ns/ldp# [LDP]
schema http://schema.org/ Schema.org
rdf http://www.w3.org/1999/02/22-rdf-syntax-ns# [rdf11-concepts]
rdfs http://www.w3.org/2000/01/rdf-schema# [rdf-schema]
solid http://www.w3.org/ns/solid/terms# Solid Terms
viade http://arquisoft.github.io/viadeSpec/ Viade specification

1.3. Data model

Note: This data model is a proposal made by the students and teachers of the Software Architecture Course (edition 2019/20) at the University of Oviedo. The data model is work-in-progress and we appreciate any feedback which can be done by raising issues.

A route must contain a name, optionally it can have a description. Its composed by a list of points which must conform be GeoCoordinates and may or not have a list of comments and media elements.

The GeoCoordinates must have latitude and longitude. They can have as optional properties a name, altitude and a physical address.

A UserComment must contain the text of the comment, the time it was published and the author, being the last one an IRI to a pod profile shape.

And finally, an Image or a Video must have an IRI to be a resource, another IRI to the pod profile of the author and the time it was published.

prefix :  <http://arquisoft.github.io/viadeSpec/>
prefix schema: <http://schema.org/>
prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#>
prefix xsd:    <http://www.w3.org/2001/XMLSchema#>
prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

# Represents a route
:Route {
  schema:name          xsd:string   ;
  schema:description  xsd:string ? ;
  :point              @:Point * ;
  :gpx                @:GPXShape ;  // See ShEx description for GPX Routes
  :hasComments        xsd:string OR @:UserComment * ;
  :hasMediaAttached    @:Image OR @:Video *;
}

:Point @:GeoCoordinates AND {
   :order xsd:integer ;
}
    
# Represents geo coordinates following: https://schema.org/GeoCoordinates
:GeoCoordinates {
  schema:latitude      xsd:decimal  ;
  schema:longitude    xsd:decimal  ;
  schema:elevation    xsd:decimal  ? ;
}

:UserComment IRI {
  schema:text       xsd:string;
  schema:publishedDate xsd:datetime;
  schema:author     @:PodProfile;
}

:Image {
  schema:contentUrl   IRI ;
  schema:publishedDate xsd:datetime;
  schema:author     @:PodProfile;
}

:Video {
  schema:contentUrl   IRI;
  schema:publishedDate xsd:dateTime;
  schema:author     @:PodProfile;
}

:PodProfile IRI 

# This model is work-in progress
:GPXShape {}   // See GPX section

1.3.1. Simple routes examples

An example of a route in Turtle following the previous Shape could be:

prefix viade:  <http://arquisoft.github.io/viadeSpec/>
prefix :       <http://example.org/>
prefix schema: <http://schema.org/>
prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#>
prefix xsd:    <http://www.w3.org/2001/XMLSchema#>

:myRoute a viade:Route ;
 schema:name "My first route" ;
 schema:description "This is an example of route" ;
 viade:point [ 
  schema:latitude 47.64458 ; 
  schema:longitude -122.326897 ; 
  viade:order 1 
 ] ;
 viade:point [ 
  schema:latitude 47.644532; 
  schema:longitude -123.3345 ; 
  viade:order 2; 
  schema:elevation 34 
 ]; 
 viade:hasComments "I really enjoyed this route" ;
 viade:hasMediaAttached :media1 .

:media1 schema:contentUrl <http://example.org/picture.jpg> ;
        schema:publishedDate "2020-03-26T21:32:52"^^xsd:dateTime ;
        schema:author <https://labra.solid.community/profile/card#me> .

You can run the example using the RDFShape tool

A possible SPARQL query to retrieve the route information and it’s points can be:

PREFIX schema: <http://schema.org/>
PREFIX viade:<http://arquisoft.github.io/viadeSpec/>
PREFIX rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?lat ?long ?order ?name ?description ?name ?elevation WHERE {
 ?route a viade:Route.
 ?route viade:point ?point .
 ?point schema:latitude ?lat ;
        schema:longitude ?long ;
        viade:order ?order.
OPTIONAL {?route schema:description ?description.}
OPTIONAL {?route schema:name ?name.}
OPTIONAL {?point schema:elevation ?elevation.}
}

1.4. GPX Routes

[GPX] is a popular XML format that could be used to represent routes. There are two possibilities: to convert the XML format to Turtle or to embed the XML file as an RDF literal.

1.4.1. GPX Routes converted to Turtle

GPX routes can be represented in Turtle using the following Shape Expression:

prefix :    <https://www.w3.org/ns/pim/gpx#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix gpx: <https://www.w3.org/ns/pim/gpx#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>


# This document contains a ShEx representation of the XML Schema defined for GPX
# The original schema URI is <http://www.topografix.com/GPX/1/1>

start = @:gpxType

# GPX documents contain a metadata header, followed by waypoints, routes, and tracks.
# You can add your own elements to the extensions section of the GPX document
:gpxType {
 gpx:creator    xsd:string ? ;
 gpx:version    xsd:string ? ;
 gpx:metadata   @:metadataType ? ;
 gpx:wpt        @:wptType * ;
 gpx:rte        @:rteType * ;
 gpx:trk        @:trkType * ;
 gpx:extensions @:extensionsType ?
}

# Information about the GPX file, author, and copyright restrictions goes in the metadata section.
# Providing rich, meaningful information about your GPX files allows others to search for and use your GPS data.
:metadataType {
 gpx:name       xsd:string ? ;
 gpx:desc       xsd:string ? ;
 gpx:author     @:personType ? ;
 gpx:copyright  @:copyrightType ? ;
 gpx:link       @:linkType * ;
 gpx:time       xsd:dateTime ? ;
 gpx:keywords   xsd:string ? ;
 gpx:bounds     @:boundsType ? ;
 gpx:extensions @:extensionsType ?
}

# wpt represents a waypoint, point of interest, or named feature on a map
:wptType {
 gpx:lat           @:latitudeType ;
 gpx:lon           @:longitudeType ;
 gpx:ele           xsd:decimal ? ;
 gpx:time          xsd:dateTime ? ;
 gpx:magvar        @:degreesType ? ;
 gpx:geoidheight   xsd:decimal ? ;
 gpx:name          xsd:string ? ;
 gpx:cmt           xsd:string ? ;
 gpx:desc          xsd:string ? ;
 gpx:src           xsd:string ? ;
 gpx:link          @:linkType ? ;
 gpx:sym           xsd:string ? ;
 gpx:type          xsd:string ? ;
 gpx:fix           @:fixType ? ;
 gpx:sat           xsd:nonNegativeInteger ? ;
 gpx:hdop          xsd:decimal ? ;
 gpx:vdop          xsd:decimal ? ;
 gpx:pdop          xsd:decimal ? ;
 gpx:ageofdgpsdata xsd:decimal ? ;
 gpx:dgpsid        @:dgpsStationType ? ;
 gpx:extensions    @:extensionsType ?
}

# rte represents route - an ordered list of waypoints representing a series of turn points leading to a destination
:rteType {
 gpx:name       xsd:string ? ;
 gpx:cmt        xsd:string ? ;
 gpx:desc       xsd:string ? ;
 gpx:src        xsd:string ? ;
 gpx:link       @:linkType * ;
 gpx:number     xsd:nonNegativeInteger ? ;
 gpx:type       xsd:string ? ;
 gpx:extensions @:extensionsType ? ;
 gpx:rtept      @:wptTypeList
}

:wptTypeList [ rdf:nil ] OR CLOSED {
 rdf:first { gpx:trkpt @:wptType } ;
 rdf:rest  @:wptTypeList
}

# trk represents a track - an ordered list of points describing a path
:trkType {
 gpx:name       xsd:string ? ;
 gpx:cmt        xsd:string ? ;
 gpx:desc       xsd:string ? ;
 gpx:src        xsd:string ? ;
 gpx:link       @:linkType * ;
 gpx:number     xsd:nonNegativeInteger ? ;
 gpx:type       xsd:string ? ;
 gpx:extensions @:extensionsType ? ;
 gpx:trkseg     @:trksegType *
}

# Allow any elements from a namespace other than this schema’s namespace
:extensionsType {
}

# A Track Segment holds a list of Track Points which are logically connected in order.
# To represent a single GPS track where GPS reception was lost, or the GPS receiver was turned off,
# start a new Track Segment for each continuous span of track data.
:trksegType {
 gpx:trkpts     @:wptTypeList    * ;
 gpx:extensions @:extensionsType ?
}

# Information about the copyright holder and any license governing use of this file.
# By linking to an appropriate license, you may place your data into the public domain or grant additional usage rights.
:copyrightType {
 gpx:author  xsd:string ;
 gpx:year    xsd:gYear ? ;
 gpx:license xsd:anyURI ?
}

# A link to an external resource (Web page, digital photo, video clip, etc) with additional information
:linkType {
 gpx:href xsd:anyURI   ;
 gpx:text xsd:string ? ;
 gpx:type xsd:string ?
}

# An email address. Broken into two parts (id and domain) to help prevent email harvesting.
:emailType {
 gpx:id     xsd:string ;
 gpx:domain xsd:string ;
}

# A person or organization.
:personType {
 gpx:name   xsd:string ? ;
 gpx:email  @:emailType ;
 gpx:link   @:linkType
}

# A geographic point with optional elevation and time. Available for use by other schemas.
:ptType {
 gpx:lat  @:latitudeType    ;
 gpx:long @:longitudeType   ;
 gpx:ele  xsd:decimal     ? ;
 gpx:time xsd:dateTime    ?
}

# An ordered sequence of points. (for polygons or polylines, e.g.)
:ptsegType [rdf:nil] OR CLOSED {
 rdf:first { gpx:pt @:ptType } ;
 rdf:rest  @:ptsegType ;
}

# Two lat/lon pairs defining the extent of an element.
:boundsType {
 gpx:minlat @:latitudeType  ;
 gpx:minlon @:longitudeType ;
 gpx:maxlat @:latitudeType  ;
 gpx:maxlon @:longitudeType
}

# The latitude of the point. Decimal degrees, WGS84 datum
:latitudeType xsd:decimal minInclusive -90.0 maxInclusive 90.0

# The longitude of the point. Decimal degrees, WGS84 datum.
:longitudeType xsd:decimal minInclusive -180.0 maxInclusive 180.0

# Used for bearing, heading, course. Units are decimal degrees, true (not magnetic).
:degreesType xsd:decimal minInclusive 0.0 maxInclusive 360.0

# Type of GPS fix. none means GPS had no fix. To signify "the fix info is unknown, leave out fixType entirely. pps = military signal used
:fixType [ "none" "2d" "3d" "dgps" "pps" ]

# Represents a differential GPS station.
:dgpsStationType xsd:integer minInclusive 0 maxInclusive 1023

1.4.2. GPX Route example as Turtle

As an example a VIADE route represented using GPX as Turtle could be:

prefix :   <http://example.org/>
prefix viade: <http://arquisoft.github.io/viadeSpec/>
prefix schema: <http://schema.org/>
prefix xsd:    <http://www.w3.org/2001/XMLSchema#>
prefix gpx:   <https://www.w3.org/ns/pim/gpx#>

:exampleRoute a viade:Route ;
 schema:name   "A nice walk" ;
 viade:gpx [
  gpx:creator  "Oregon 400t" ;
  gpx:version   "1.1";
  gpx:metadata  [ gpx:link  [ gpx:href  "http://www.garmin.com" ;
                                    gpx:text  "Garmin International"
                                  ] ;
                  gpx:time  "2009-10-17T22:58:43Z"^^xsd:dateTime
        ] ;
  gpx:trk [ gpx:name    "Example GPX Document" ;
            gpx:trkseg  [ gpx:trkpts  ( [ gpx:trkpt  [ gpx:ele   4.46 ;
                                                       gpx:lat   47.644548 ;
                                                       gpx:lon   -122.326897 ;
                                                       gpx:time  "2009-10-17T18:37:26Z"^^xsd:dateTime
                                                     ] ]
                                                    [ gpx:trkpt  [
                                                       gpx:ele   4.94 ;
                                                       gpx:lat   47.644548 ;
                                                       gpx:lon   -122.326897 ;
                                                       gpx:time  "2009-10-17T18:37:31Z"^^xsd:dateTime
                                                    ] ]
                                                    [ gpx:trkpt  [
                                                       gpx:ele   6.87 ;
                                                       gpx:lat   47.644548 ;
                                                       gpx:lon   -122.326897 ;
                                                       gpx:time  "2009-10-17T18:37:34Z"^^xsd:dateTime
                                                    ] ]
                                        ) ]
            ]
 ]
.

1.4.3. GPX routes embedded as literals

It is also possible to represent the routes embedding the XML content as an RDF literal.

The following example contains a GPX route embedded as an RDF literal.

prefix :   <http://example.org/>
prefix rdf:   <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
prefix viade: <http://arquisoft.github.io/viadeSpec/>
prefix schema: <http://schema.org/>
prefix xsd:    <http://www.w3.org/2001/XMLSchema#>
prefix gpx:   <https://www.w3.org/ns/pim/gpx#>

:exampleRoute a viade:Route ;
 schema:name   "A nice walk" ;
 viade:gpx [
     viade:source """<gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:gpxx="http://www.garmin.com/xmlschemas/GpxExtensions/v3" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v1" creator="Oregon 400t" version="1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd">
  <metadata>
    <link href="http://www.garmin.com">
      <text>Garmin International</text>
    </link>
    <time>2009-10-17T22:58:43Z</time>
  </metadata>
  <trk>
    <name>Example GPX Document</name>
    <trkseg>
      <trkpt lat="47.644548" lon="-122.326897">
        <ele>4.46</ele>
        <time>2009-10-17T18:37:26Z</time>
      </trkpt>
      <trkpt lat="47.644548" lon="-122.326897">
        <ele>4.94</ele>
        <time>2009-10-17T18:37:31Z</time>
      </trkpt>
      <trkpt lat="47.644548" lon="-122.326897">
        <ele>6.87</ele>
        <time>2009-10-17T18:37:34Z</time>
      </trkpt>
    </trkseg>
  </trk>
 </gpx>"""^^rdf:XMLLiteral ;
 ]
.

1.4.4. GPX to RDF converters

It is possible to convert from GPX files in XML to RDF files in RDF/XML using the following XSLT file

2. Pod Management

It is crucial for the interoperability that we handle the POD data in the same way. Here is a proposal of what we can do. Note that this pretends to be an starting point to the complete specification, and so it is open to discussion.

2.1. File format

For the file format we can use JSON-LD, we have used JSON along the degree and we are very familiar with it, it won’t be a problem to handle that in the application, in fact Javascript facilitates that task with the built-in object "JSON".

2.1.1. File example

What comes next is an example of the minimum data that should be stored in the pod with the JSON-LD. More data could be added by our apps, but at least this should be there.

The following properties can be found:

The example (if any error is seen in the context, please point it out):

_If it cannot be seen in the include please check it manually because afterwards there will be mentions about it._

{ "@context": { "@version": 1.1, "comments": { "@id": "viade:comments", "@type": "@id" }, "description": { "@id": "schema:description", "@type": "xsd:string" }, "media": { "@container": "@list", "@id": "viade:media" }, "name": { "@id": "schema:name", "@type": "xsd:string" }, "points": { "@container": "@list", "@id": "viade:points" }, "latitude": { "@id": "schema:latitude", "@type": "xsd:double" }, "longitude": { "@id": "schema:longitude", "@type": "xsd:double" }, "elevation": { "@id": "schema:elevation", "@type": "xsd:double" }, "author":{ "@id": "schema:author", "@type": "@id" }, "date": { "@id": "schema:DateTime", "@type": "xsd:dateTime" }, "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdfs": "http://www.w3.org/2000/01/rdf-schema#", "schema": "http://schema.org/", "viade": "http://arquisoft.github.io/viadeSpec/", "xsd": "http://www.w3.org/2001/XMLSchema#" }, "name": "Route test 1", "author": "https://luispresacollada.solid.community/profile/card#me", "description": "This is a test to see the output of the JsonLDConversor", "comments": "http://inrupt.luispc1998/viade/comments/commentExample.json", "date": "2020-02-25T18:50:22Z", "media": [ { "@id": "http://inrupt.luispc1998/viade/resources/da34fas749sa3h883j.jpg", "name": "MyFoto" }, { "@id": "http://inrupt.angelixus/viade/resources/pt92as74234a3h5xb3j.mp4", "name": "MyVideo" }, { "@id": "http://inrupt.raupemol/viade/resources/da34zas4213sa7b542.png", "name": "OtherFoto" }, { "@id": "http://inrupt.luispc1998/viade/resources/da345432jtsa7b542e.mp4", "name": "OtherVideo" } ], "waypoints" : [ { "name": "Name for the waypoint", "description": "Description of the waypoint", "latitude": 45.123, "longitude": 34.121, "elevation": 34 }, { "name": "Computer Science School", "description": "Become a good engineer with us", "latitude": 45.123, "longitude": 34.121, "elevation": 34 }

], "points": [ { "latitude": 45.123, "longitude": 34.121, "elevation": 34 }, { "latitude": 46.123, "longitude": 34.121, "elevation": 36 }, { "latitude": 47.123, "longitude": 34, "elevation": 39 }, { "latitude": 48.123, "longitude": 32.121, "elevation": 40 }, { "latitude": 49.123, "longitude": 34.121, "elevation": 43 }, { "latitude": 40.123, "longitude": 32.121, "elevation": 46 }, { "latitude": 50.123, "longitude": 33.121, "elevation": 50 }, { "latitude": 53.123, "longitude": 34.121, "elevation": 55 }, { "latitude": 54.123, "longitude": 34.121, "elevation": 56 }, { "latitude": 55.123, "longitude": 35.121, "elevation": 50 }, { "latitude": 55.123, "longitude": 34.121, "elevation": 45 } ]

}

2.2. Directory hierarchy in the POD

Not only we need to state what information should be in the pod, but also where it is located.

We proposed a "viade" folder in the root of the pod, and inside it three folders: routes, comments, resources.

viade/

    routes/

      example.jsonld
      example2.jsonld

    comments/

      ruta1Comments.jsonld
      ruta2Comments.jsonld

    resources/

      foto.jpg
      image.png
      video.mp4

    inbox/

      sharingNotification1.jsonld
      sharingNotification2.jsonld

    shared/

      luispresacollada.solid.community.jsonld

2.2.1. Comments and resources

Each route will have linked a file for the comments from the very momment of its creation. In this file the users that have received the route in a share operation can post their comments. This approach is highly efficient and by using it we get rid of permissions problems with respect to the one that stores the comments of each user in his pod.

Such files just to follow a convention are supposed to be stored in viade/comments folder, although since we are navigating through a graph it is not really important from the interoperability point of view where is the file.

Consider the following example:

Luis published a route long ago, and now he shared it with his friend Sara. Sara wants to comment it. Sara will access the comments file of the route by means of the route file, and she will post there her comment. She has permissions because Luis gave them to her when sharing the route.

You can find examples of the files int the jsonlfProposal folder.

2.3. What should be done about GPX?

A gpx file can contain several elements "trk" (from the word "track") which are the ones that match our concept of "Route", that is a path, a sequence of points. Inside this label we can have several "trkseg", which stand as sequences of ordered points (trkpt). Our duty will be to take all the trkpt and put them inside the "viade:points" property of the example json.

The gpx trk label can have a name and a description so it could be direct translation. Or we may want the user to introduce that data, that’s an app design decision.

There is a type of points in a GPX called "waypoints", they are relevant points that are in some way related to the specified tracks. Assuming a path across a city, a waypoint can be a church, a restaurant, a monument, and so far so forth. We will include this points in our routes jsonld files. They will have name, description and coordinates. Check the provided example to see its implementation. Elevation and description are optional attributes.

2.4. How to share

We have performed a voting in order to follow the approach of the permissions, or use the inbox folder in order to manipulate the sharing functionality. In the end we wil be using the second one. But for such a task we need some kind of agreement in the file structure in the "receiver". Assume Luis wants to share a route with Sara. Luis will give her permissions to the files, and send her a notification, with the webid of the route and his own webid. Sara’s app will parse the notification and add that route id to a file.

Such files will be placed in the folder viade/shared, and will have a name such as: luispresacollada.solid.community. (The corresponding part of the webID) You may check the structure in the file "sharedRoutesExample", it contains a simple list with @id pointing to the shared routes.

{ "@context": { "@version": 1.1, "routes": { "@container": "@list", "@id": "viade:routes" }, "viade": "http://arquisoft.github.io/viadeSpec/" }, "routes": [ { "@id": "http://inrupt.luispc1998/viade/routes/route1.jsonld" }, { "@id": "http://inrupt.angelixus/viade/routes/example.jsonld" }, { "@id": "http://inrupt.raupemol/viade/routes/magicalRoute.jsonld" }, { "@id": "http://inrupt.luispc1998/viade/routes/exampl2.jsonld" } ]

}

Conformance

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Index

Terms defined by this specification

References

Normative References

[RDF11-CONCEPTS]
Richard Cyganiak; David Wood; Markus Lanthaler. RDF 1.1 Concepts and Abstract Syntax. 25 February 2014. REC. URL: https://www.w3.org/TR/rdf11-concepts/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119

Informative References

[GPX]
GPX schema version 1.1. URL: https://www.topografix.com/gpx
[LDP]
Steve Speicher; John Arwe; Ashok Malhotra. Linked Data Platform 1.0. 26 February 2015. REC. URL: https://www.w3.org/TR/ldp/
[RDF-SCHEMA]
Dan Brickley; Ramanathan Guha. RDF Schema 1.1. 25 February 2014. REC. URL: https://www.w3.org/TR/rdf-schema/