author | wenzelm |
Mon, 11 Mar 2019 20:47:04 +0100 | |
changeset 69900 | 18a61caf5e68 |
parent 69870 | 0af6b4a5a7d9 |
child 69902 | 9c697c7ad8d6 |
permissions | -rw-r--r-- |
69807 | 1 |
/* Title: Pure/General/rdf.scala |
2 |
Author: Makarius |
|
3 |
||
4 |
Support for RDF/XML representation, see also: |
|
5 |
- https://www.w3.org/RDF |
|
6 |
- https://www.w3.org/TR/rdf-primer |
|
7 |
*/ |
|
8 |
||
9 |
package isabelle |
|
10 |
||
11 |
||
69809 | 12 |
import java.net.URI |
13 |
||
14 |
||
69807 | 15 |
object RDF |
16 |
{ |
|
17 |
/* document */ |
|
18 |
||
19 |
val rdf: XML.Namespace = XML.Namespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#") |
|
20 |
val dc: XML.Namespace = XML.Namespace("dc", "http://purl.org/dc/elements/1.1/") |
|
21 |
||
22 |
val default_namespaces: List[XML.Namespace] = List(rdf, dc) |
|
23 |
||
24 |
def document(body: XML.Body, |
|
25 |
namespaces: List[XML.Namespace] = default_namespaces, |
|
26 |
attributes: XML.Attributes = Nil): XML.Elem = |
|
27 |
{ |
|
28 |
XML.Elem(Markup(rdf("RDF"), namespaces.map(_.attribute) ::: attributes), body) |
|
29 |
} |
|
30 |
||
31 |
||
32 |
/* multiple triples vs. compact description */ |
|
33 |
||
34 |
sealed case class Triple(subject: String, predicate: String, `object`: XML.Body) |
|
35 |
{ |
|
36 |
def property: XML.Elem = XML.elem(predicate, `object`) |
|
37 |
} |
|
38 |
||
39 |
def triples(args: List[Triple]): XML.Body = |
|
69870
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
40 |
XML.newline :: |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
41 |
args.zipWithIndex.groupBy({ case (t, _) => t.subject }).iterator.map(_._2). |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
42 |
toList.sortBy(ps => ps.head._2).flatMap(ps => |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
43 |
List( |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
44 |
description(ps.head._1.subject, |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
45 |
XML.newline :: ps.flatMap({ case (t, _) => List(t.property, XML.newline) })), |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
46 |
XML.newline)) |
69807 | 47 |
|
48 |
def description(subject: String, body: XML.Body, attributes: XML.Attributes = Nil): XML.Elem = |
|
49 |
XML.Elem(Markup(rdf("Description"), (rdf("about"), subject) :: attributes), body) |
|
69808 | 50 |
|
51 |
||
52 |
/* collections */ |
|
53 |
||
54 |
def collection(kind: String, items: List[XML.Body]): XML.Elem = |
|
55 |
XML.elem(kind, items.map(item => XML.elem(rdf("li"), item))) |
|
56 |
||
57 |
def bag(items: List[XML.Body]): XML.Elem = collection(rdf("Bag"), items) |
|
58 |
def seq(items: List[XML.Body]): XML.Elem = collection(rdf("Seq"), items) |
|
59 |
def alt(items: List[XML.Body]): XML.Elem = collection(rdf("Alt"), items) |
|
69809 | 60 |
|
61 |
||
62 |
/* datatypes */ |
|
63 |
||
64 |
// see https://www.w3.org/TR/rdf11-concepts/#section-Datatypes |
|
65 |
// see https://www.w3.org/TR/xmlschema-2/#built-in-datatypes |
|
66 |
||
67 |
def string(x: String): XML.Body = if (x.isEmpty) Nil else List(XML.Text(x)) |
|
68 |
def uri(x: URI): XML.Body = string(x.toString) |
|
69 |
def bool(x: Boolean): XML.Body = string(x.toString) |
|
70 |
def int(x: Int): XML.Body = string(Value.Int(x)) |
|
71 |
def long(x: Long): XML.Body = string(Value.Long(x)) |
|
72 |
def double(x: Double): XML.Body = string(Value.Double(x)) |
|
73 |
def seconds(x: Time): XML.Body = double(x.seconds) |
|
74 |
def date_time_stamp(x: Date): XML.Body = string(Date.Format("uuuu-MM-dd'T'HH:mm:ss.SSSxxx")(x)) |
|
69858 | 75 |
|
76 |
||
77 |
/* predicates */ |
|
78 |
||
79 |
object Property // binary relation with plain value |
|
80 |
{ |
|
81 |
val title: String = dc("title") |
|
82 |
val creator: String = dc("creator") |
|
83 |
val contributor: String = dc("contributor") |
|
84 |
val date: String = dc("date") |
|
85 |
val description: String = dc("description") |
|
86 |
} |
|
69900 | 87 |
|
88 |
private val meta_data_table = |
|
89 |
Map( |
|
90 |
Markup.META_TITLE -> Property.title, |
|
91 |
Markup.META_CREATOR -> Property.creator, |
|
92 |
Markup.META_CONTRIBUTOR -> Property.contributor, |
|
93 |
Markup.META_DATE -> Property.date, |
|
94 |
Markup.META_DESCRIPTION -> Property.description) |
|
95 |
||
96 |
def meta_data(props: Properties.T): Properties.T = |
|
97 |
props.flatMap({ case (a, b) => meta_data_table.get(a).map((_, b)) }) |
|
69807 | 98 |
} |