Barnabás Szász*, Rita Fleiner**, András Micsik***
*University of Debrecen, Debrecen, Hungary
** Óbuda University, Budapest, Hungary
*** MTA, SZTAKI, Budapest, Hungary
This
document explains the use of Self-Unfolding URI's through a real life example.
The first part of this page shows examples for the conceptual template describing the structure of generated triples.
Each template consist of a URI class and a set of triplets.
The second part contains three example SPARQL Insert implementations.
Each self unfolding URI comes with a template which has the following structure:
<Base URI>/<type without namespace>;<Property1>=<Value1>;<Property2>=<Value2>...
<URI> rdf:type <type with namespace>
<property1> <value1> ;
<property2> <value2> ;
<property3> <calculated value> ;
<property4> <related URI> .
<http://example.org/data/UnitMinuteInstant;year={year};month={month};day={day};hour={hour};minute={minute}.
<http://example.org/data/UnitMinuteInstant;year={year};month={month};day={day};hour={hour};minute={minute}>
rdf:type
otime:UnitMinuteInstant ;
time:inDateTime
<http://example.org/data/UnitMinuteDateTimeDescription;year={year};month={month};day={day};hour={hour};minute={minute}> .
<http://example.org/data/UnitMinuteDateTimeDescription;year={year};month={month};day={day};hour={hour};minute={minute}>
rdf:type
otime:unitMinuteDateTimeDescription ;
time:hour "{hour}"^^xsd:nonNegativeInteger ;
time:minute "{minute}"^^xsd:nonNegativeInteger ;
time:month "{month}"^^xsd:nonNegativeInteger ;
time:day "{day}" ;
time:year "{year}" .
The template for
<http://example.org/data/CourseTime;courseTerm={term};hour={hour};minute={minute};durationHour={durationHour};durationMinute={durationMinute};dayofweek={dayOfWeek}> .
<http://example.org/data/CourseTime;courseTerm={term};hour={hour};minute={minute};durationHour={durationHour};durationMinute={durationMinute};dayofweek={dayOfWeek}>
rdf:type
otime:CourseTime ;
ta:hasTemporalAggregateDescription
<http://example.org/data/StandardCourseTemporalAggregateDescription;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute};durationHour={durationHour};durationMinute={durationMinute};dayofweek={dayOfWeek}> .
<http://example.org/data/StandardCourseTemporalAggregateDescription;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute};durationHour={durationHour};durationMinute={durationMinute};dayofweek={dayOfWeek}>
rdf:type
otime:StandardCourseTemporalAggregateDescription ;
ta:hasithTemporalUnit {dayOfWeek} ;
ta:hasStart
<http://example.org/data/UnitMinuteInterval;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute};durationHour={durationHour};durationMinute={durationMinute}> .
<http://example.org/data/UnitMinuteInterval;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute};durationHour={durationHour};durationMinute={durationMinute}>
rdf:type
otime:UnitMinuteInterval ;
time:hasDurationDescription
<http://example.org/data/DurationDescription;durationHour={durationHour};durationMinute={durationMinute}> ;
time:hasBeginning <http://example.org/data/UnitMinuteInstant;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute}> .
<http://example.org/data/DurationDescription;durationHour={durationHour};durationMinute={durationMinute}>
rdf:type
time:DurationDescription ;
time:hours {durationHour} ;
time:minutes {durationMinute} .
<http://example.org/data/UnitMinuteInstant;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute}>
rdf:type
otime:UnitMinuteInstant ;
time:inDateTime
<http://example.org/data/UnitMinuteDateTimeDescription;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute}>
.
<http://example.org/data/UnitMinuteDateTimeDescription;year={year};month={month};day=({day}+{dayOfWeek}-1);hour={hour};minute={minute}>
rdf:type
otime:unitMinuteDateTimeDescription ;
time:hour "{hour}"^^xsd:nonNegativeInteger ;
time:minute "{minute}"^^xsd:nonNegativeInteger ;
time:month "{month}"^^xsd:nonNegativeInteger ;
time:day "({day}+{dayOfWeek}-1)" ;
time:year "{year}" .
PREFIX oloud: <http://lod.nik.uni-obuda.hu/oloud-base#>
PREFIX otime: <http://lod.nik.uni-obuda.hu/oloud-time#>
PREFIX ta: <http://ontology.ihmc.us/temporalAggregates.owl#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
oloud:CourseTerm
rdf:type
owl:Class ;
rdfs:subClassOf
time:Interval .
otime:CourseTime
rdf:type
owl:Class ;
rdfs:subClassOf
ta:TemporalSeq.
otime:StandardCourseTemporalAggregateDescription
a owl:Class ;
rdfs:subClassOf ta:TemporalAggregateDescription ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:hasValue 14 ;
owl:onProperty ta:hasCount ] ,
[ a owl:Restriction ;
owl:hasValue time:unitDay ;
owl:onProperty ta:hasTemporalUnit ] .
otime:UnitMinuteDateTimeDescription
a owl:Class ;
rdfs:subClassOf time:DateTimeDescription ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:hasValue time:UnitMinute ;
owl:onProperty time:unitType ] .
otime:UnitMinuteInstant
a owl:Class ;
rdfs:subClassOf time:Instant ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:allValuesFrom otime:UnitMinuteDateTimeDescription ;
owl:onProperty
time:inDateTime ] .
otime:UnitMinuteInterval
a owl:Class ;
rdfs:subClassOf time:Interval ;
rdfs:subClassOf
[ a owl:Restriction ;
owl:allValuesFrom oloud:UnitMinuteInstant ;
owl:onProperty time:hasBeginning ] .
PREFIX
oloud: <http://lod.nik.uni-obuda.hu/oloud-base#>
PREFIX
otime: <http://lod.nik.uni-obuda.hu/oloud-time#>
PREFIX
ta: <http://ontology.ihmc.us/temporalAggregates.owl#>
PREFIX
time: <http://www.w3.org/2006/time#>
PREFIX
owl: <http://www.w3.org/2002/07/owl#>
PREFIX
rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
<http://example.org/2015Fall> a oloud:CourseTerm;
time:hasBeginning
<http://example.org/UnitMinuteInstant;year=2015;month=9;day=7;hour=0;minute=0> .
<http://example.org/c001> a oloud:Course ;
oloud:courseTerm <http://example.org/2015Fall> ;
otime:courseTime
<http://example.org/CourseTime;courseTerm=2015Fall;hour=10;minute=0;durationHour=1;durationMinute=30;dayofweek=2> .
Please note, that the following URI's are self unfolding and unfolding such a URI can trigger generating more self unfolding URIs. [1] and [3] is part of the inital data, [2] has been unfolded from [1], [4] from [3], [5] from [4], [6] and [7] from [5] and finally [8] from [7].
1. <http://example.org/UnitMinuteInstant;year=2015;month=9;day=7;hour=0;minute=0>
2. <http://example.org/UnitMinuteDateTimeDescription;year=2015;month=9;day=7;hour=0;minute=0>
3. <http://example.org/CourseTime;courseTerm=2015Fall;hour=10;minute=0;durationHour=1;durationMinute=30;dayofweek=2>
4. <http://example.org/StandardCourseTemporalAggregateDescription;year=2015;month=9;day=8;hour=10;minute=0;durationHour=1;durationMinute=30;dayofweek=2>
5. <http://example.org/UnitMinuteInterval;year=2015;month=9;day=8;hour=10;minute=0;durationHour=1;durationMinute=30>
6. <http://example.org/DurationDescription;durationHour=1;durationMinute=30>
7. <http://example.org/UnitMinuteInstant;year=2015;month=9;day=8;hour=10;minute=0>
8.
<http://example.org/UnitMinuteDateTimeDescription;year=2015;month=9;day=8;hour=10;minute=0>
The Following INSERT statement is used to unfold [1], [2], [7] and [8] (for [7] and [8] run this statement again after the 3. - as [5] needs to already generated for [7]):
PREFIX oloud: <http://lod.nik.uni-obuda.hu/oloud-base#>
PREFIX otime: <http://lod.nik.uni-obuda.hu/oloud-time#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
INSERT
{
?uri a otime:UnitMinuteInstant;
time:inDateTime ?desc_uri.
?desc_uri a otime:unitMinuteDateTimeDescription;
time:minute ?minute ;
time:hour ?hour ;
time:day ?day ;
time:month ?month ;
time:year ?year .
}
WHERE {
# matching any triplets
?anyobject ?anyproperty ?uri.
# with a specific URI pattern
FILTER(STRSTARTS(STR(?uri), "http://example.org/UnitMinuteInstant")).
# we need to generate a URI for the UnitMinuteDateTimeDescription entity
BIND(IRI(REPLACE(str(?uri),"/UnitMinuteInstant;","/UnitMinuteDateTimeDescription;")) AS ?desc_uri) .
# extract the URI parameters
BIND(REPLACE(str(?uri), '^(.*)\\?', "") AS ?p)
BIND(xsd:nonNegativeInteger(REPLACE(REPLACE(str(?p), '^.*year=', "") , ';.*$', "")) AS ?year).
BIND(xsd:nonNegativeInteger(REPLACE(REPLACE(str(?p), '^.*month=', "") , ';.*$', "")) AS ?month).
BIND(xsd:nonNegativeInteger(REPLACE(REPLACE(str(?p), '^.*day=', "") , ';.*$', "")) AS ?day).
BIND(xsd:nonNegativeInteger(REPLACE(REPLACE(str(?p), '^.*hour=', "") , ';.*$', "")) AS ?hour).
BIND(xsd:nonNegativeInteger(REPLACE(REPLACE(str(?p), '^.*minute=', "") , ';.*$', "")) AS ?minute).
}
Which results:
<http://example.org/UnitMinuteInstant;year=2015;month=9;day=7;hour=0;minute=0>
rdf:type
otime:UnitMinuteInstant ;
time:inDateTime
<http://example.org/UnitMinuteDateTimeDescription;year=2015;month=9;day=7;hour=0;minute=0>
.
<http://example.org/UnitMinuteDateTimeDescription;year=2015;month=9;day=7;hour=0;minute=0>
rdf:type otime:unitMinuteDateTimeDescription ;
time:hour"0"^^xsd:nonNegativeInteger ;
time:minute "0"^^xsd:nonNegativeInteger;
time:month "9"^^xsd:nonNegativeInteger;
time:day "7";
time:year"2015" .
<http://example.org/UnitMinuteInstant;year=2015;month=9;day=8;hour=10;minute=0>
rdf:type
otime:UnitMinuteInstant ;
time:inDateTime <http://example.org/UnitMinuteDateTimeDescription;year=2015;month=9;day=8;hour=10;minute=0>
.
<http://example.org/UnitMinuteDateTimeDescription;year=2015;month=9;day=8;hour=10;minute=0>
rdf:type
otime:unitMinuteDateTimeDescription ;
time:hour
"10"^^xsd:nonNegativeInteger
;
time:minute "0"^^xsd:nonNegativeInteger ;
time:month "9"^^xsd:nonNegativeInteger ;
time:day "8"
;
time:year
"2015" .
The Following INSERT statement is used to unfold [3] and [4]:
PREFIX oloud: <http://lod.nik.uni-obuda.hu/oloud-base#>
PREFIX otime: <http://lod.nik.uni-obuda.hu/oloud-time#>
PREFIX ta: <http://ontology.ihmc.us/temporalAggregates.owl#>
PREFIX time: <http://www.w3.org/2006/time#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
INSERT
{
?uri a otime:CourseTime;
ta:hasTemporalAggregateDescription ?desc_uri.
?desc_uri a otime:StandardCourseTemporalAggregateDescription ;
ta:hasStart ?interval_uri ;
ta:hasithTemporalUnit ?dayofweek .
}
WHERE {
# matching any triplets
?anyobject ?anyproperty ?uri.
# with a specific URI pattern
FILTER(STRSTARTS(STR(?uri), "http://example.org/CourseTime")).
# extract the URI parameters
BIND(REPLACE(str(?uri), '^(.*)\\?', "") AS ?p)
BIND(REPLACE(REPLACE(str(?p), '^.*courseTerm=', "") , ';.*$', "") AS ?ct).
BIND(IRI(CONCAT("http://example.org/", ?ct)) AS ?courseTerm).
# extract the start date of the specific Course Term
?courseTerm time:hasBeginning ?b.
?b time:inDateTime ?d.
?d time:year ?year;
time:month ?month;
time:day ?startday.
# calculate the first course occurance
BIND(REPLACE(REPLACE(str(?p), '^.*hour=', "") , ';.*$', "") AS ?hour).
BIND(REPLACE(REPLACE(str(?p), '^.*minute=', "") , ';.*$', "") AS ?minute).
BIND(REPLACE(REPLACE(str(?uri), '^.*dayofweek=', "") , ';.*$', "") AS ?dayofweek) .
BIND(xsd:integer(?startday)+xsd:integer(?dayofweek)-1 as ?day).
BIND(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(CONCAT(";year=",STR(?year)),";month="),STR(?month)),";day="),STR(?day),";"))AS ?u2).
# Create a new UnitMinuteInterval entity representing the first course occurance
BIND(IRI(REPLACE(REPLACE(REPLACE(str(?uri),"/CourseTime;","/UnitMinuteInterval;"),';courseTerm=[^;]*(;|$)', ?u2),';dayofweek=[^;]*(;|$)', "")) AS ?interval_uri) .
# we need to generate a URI for the StandardCourseTemporalAggregateDescription entity
BIND(IRI(REPLACE(REPLACE(str(?uri),"/CourseTime;","/StandardCourseTemporalAggregateDescription;"),';courseTerm=[^;]*(;|$)', ?u2)) AS ?desc_uri) .
}
Which results:
<http://example.org/CourseTime;courseTerm=2015Fall;hour=10;minute=0;durationHour=1;durationMinute=30;dayofweek=2>
rdf:type
otime:CourseTime ; ta:hasTemporalAggregateDescription
<http://example.org/StandardCourseTemporalAggregateDescription;year=2015;month=9;day=8;hour=10;minute=0;durationHour=1;durationMinute=30;dayofweek=2>
.
<http://example.org/StandardCourseTemporalAggregateDescription;year=2015;month=9;day=8;hour=10;minute=0;durationHour=1;durationMinute=30;dayofweek=2>
rdf:type otime:StandardCourseTemporalAggregateDescription ;
ta:hasithTemporalUnit 2 ;
ta:hasStart <http://example.org/UnitMinuteInterval;year=2015;month=9;day=8;hour=10;minute=0;durationHour=1;durationMinute=30>
.
The Following INSERT statement is used to unfold [5] and [6]:
PREFIX oloud: <http://lod.nik.uni-obuda.hu/oloud-base#>
PREFIX otime: <http://lod.nik.uni-obuda.hu/oloud-time#>
PREFIX time: <http://www.w3.org/2006/time#>
INSERT
{
?uri a otime:UnitMinuteInterval;
time:hasBeginning ?instant_uri ;
time:hasDurationDescription ?duration_uri .
?duration_uri a time:DurationDescription;
time:minutes ?durationMinute ;
time:hours ?durationHour .
} WHERE {
# matching any triplets
?anyobject ?anyproperty ?uri.
# with a specific URI pattern
FILTER(STRSTARTS(STR(?uri), "http://example.org/UnitMinuteInterval")).
# extract the URI parameters
BIND(REPLACE(str(?uri), '^(.*)\\?', "") AS ?p)
BIND(REPLACE(REPLACE(str(?p), '^.*durationHour=', "") , ';.*$', "") AS ?durationHour).
BIND(REPLACE(REPLACE(str(?p), '^.*durationMinute=', "") , ';.*$', "") AS ?durationMinute).
# we need to generate a URI for the DurationDescription entity
BIND(IRI(REPLACE(REPLACE(str(?uri),"/UnitMinuteInterval;","/DurationDescription;"),'(year=[^;]*(;|$))|(month=[^;]*(;|$))|(day=[^;]*(;|$))|(hour=[^;]*(;|$))|(minute=[^;]*(;|$))', "")) AS ?duration_uri) .
# we need to generate a URI for the UnitMinuteInstant entity
BIND(IRI(REPLACE(REPLACE(REPLACE(str(?uri),"/UnitMinuteInterval;","/UnitMinuteInstant;"),'(durationHour=[^;]*(;|$))|(durationMinute=[^;]*(;|$))', ""),'([;]*$)', "")) AS ?instant_uri) .
}
Which results (see in action here):
<http://example.org/UnitMinuteInterval;year=2015;month=9;day=8;hour=10;minute=0;durationHour=1;durationMinute=30>
rdf:type otime:UnitMinuteInterval ;
time:hasDurationDescription <http://example.org/DurationDescription;durationHour=1;durationMinute=30> ;
time:hasBeginning <http://example.org/UnitMinuteInstant;year=2015;month=9;day=8;hour=10;minute=0> .
<http://example.org/DurationDescription;durationHour=1;durationMinute=30>
rdf:type time:DurationDescription ;
time:hours 1 ;
time:minutes 30 .