author | wenzelm |
Sun, 27 Oct 2024 11:02:21 +0100 | |
changeset 81266 | 8300511f4c45 |
parent 75393 | 87ebf5a50283 |
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 |
||
75393 | 12 |
object RDF { |
69807 | 13 |
/* document */ |
14 |
||
15 |
val rdf: XML.Namespace = XML.Namespace("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#") |
|
69916
3235ecdcd884
more meta data from "dcterms" (superset of "dc");
wenzelm
parents:
69902
diff
changeset
|
16 |
val dcterms: XML.Namespace = XML.Namespace("dcterms", "http://purl.org/dc/terms/") |
69807 | 17 |
|
69916
3235ecdcd884
more meta data from "dcterms" (superset of "dc");
wenzelm
parents:
69902
diff
changeset
|
18 |
val default_namespaces: List[XML.Namespace] = List(rdf, dcterms) |
69807 | 19 |
|
20 |
def document(body: XML.Body, |
|
21 |
namespaces: List[XML.Namespace] = default_namespaces, |
|
75393 | 22 |
attributes: XML.Attributes = Nil |
23 |
): XML.Elem = { |
|
69807 | 24 |
XML.Elem(Markup(rdf("RDF"), namespaces.map(_.attribute) ::: attributes), body) |
25 |
} |
|
26 |
||
27 |
||
28 |
/* multiple triples vs. compact description */ |
|
29 |
||
69902
9c697c7ad8d6
URIs should normally be "rdf:resource", not string body;
wenzelm
parents:
69900
diff
changeset
|
30 |
sealed case class Triple( |
75393 | 31 |
subject: String, |
32 |
predicate: String, |
|
33 |
`object`: XML.Body = Nil, |
|
34 |
resource: String = "" |
|
35 |
) { |
|
69902
9c697c7ad8d6
URIs should normally be "rdf:resource", not string body;
wenzelm
parents:
69900
diff
changeset
|
36 |
require(`object`.isEmpty || resource.isEmpty) |
9c697c7ad8d6
URIs should normally be "rdf:resource", not string body;
wenzelm
parents:
69900
diff
changeset
|
37 |
|
9c697c7ad8d6
URIs should normally be "rdf:resource", not string body;
wenzelm
parents:
69900
diff
changeset
|
38 |
def property: XML.Elem = |
9c697c7ad8d6
URIs should normally be "rdf:resource", not string body;
wenzelm
parents:
69900
diff
changeset
|
39 |
if (resource.nonEmpty) XML.elem(Markup(predicate, List("rdf:resource" -> resource))) |
9c697c7ad8d6
URIs should normally be "rdf:resource", not string body;
wenzelm
parents:
69900
diff
changeset
|
40 |
else XML.elem(predicate, `object`) |
69807 | 41 |
} |
42 |
||
43 |
def triples(args: List[Triple]): XML.Body = |
|
69870
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
44 |
XML.newline :: |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
45 |
args.zipWithIndex.groupBy({ case (t, _) => t.subject }).iterator.map(_._2). |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
46 |
toList.sortBy(ps => ps.head._2).flatMap(ps => |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
47 |
List( |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
48 |
description(ps.head._1.subject, |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
49 |
XML.newline :: ps.flatMap({ case (t, _) => List(t.property, XML.newline) })), |
0af6b4a5a7d9
afford redundant whitespace for improved readability;
wenzelm
parents:
69868
diff
changeset
|
50 |
XML.newline)) |
69807 | 51 |
|
52 |
def description(subject: String, body: XML.Body, attributes: XML.Attributes = Nil): XML.Elem = |
|
53 |
XML.Elem(Markup(rdf("Description"), (rdf("about"), subject) :: attributes), body) |
|
69808 | 54 |
|
55 |
||
56 |
/* collections */ |
|
57 |
||
58 |
def collection(kind: String, items: List[XML.Body]): XML.Elem = |
|
59 |
XML.elem(kind, items.map(item => XML.elem(rdf("li"), item))) |
|
60 |
||
61 |
def bag(items: List[XML.Body]): XML.Elem = collection(rdf("Bag"), items) |
|
62 |
def seq(items: List[XML.Body]): XML.Elem = collection(rdf("Seq"), items) |
|
63 |
def alt(items: List[XML.Body]): XML.Elem = collection(rdf("Alt"), items) |
|
69809 | 64 |
|
65 |
||
66 |
/* datatypes */ |
|
67 |
||
68 |
// see https://www.w3.org/TR/rdf11-concepts/#section-Datatypes |
|
69 |
// see https://www.w3.org/TR/xmlschema-2/#built-in-datatypes |
|
70 |
||
71 |
def string(x: String): XML.Body = if (x.isEmpty) Nil else List(XML.Text(x)) |
|
72 |
def bool(x: Boolean): XML.Body = string(x.toString) |
|
73 |
def int(x: Int): XML.Body = string(Value.Int(x)) |
|
74 |
def long(x: Long): XML.Body = string(Value.Long(x)) |
|
75 |
def double(x: Double): XML.Body = string(Value.Double(x)) |
|
76 |
def seconds(x: Time): XML.Body = double(x.seconds) |
|
69982 | 77 |
|
78 |
val date_format: Date.Format = Date.Format("uuuu-MM-dd'T'HH:mm:ss.SSSxxx") |
|
79 |
def date_time_stamp(x: Date): XML.Body = string(date_format(x)) |
|
69858 | 80 |
|
81 |
||
82 |
/* predicates */ |
|
83 |
||
75393 | 84 |
object Property { |
85 |
// binary relation with plain value |
|
69983
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
86 |
def title: String = dcterms("title") |
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
87 |
def creator: String = dcterms("creator") |
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
88 |
def contributor: String = dcterms("contributor") |
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
89 |
def date: String = dcterms("date") |
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
90 |
def license: String = dcterms("license") |
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
91 |
def description: String = dcterms("description") |
69858 | 92 |
} |
69900 | 93 |
|
69983
4ce5ce3a612b
more robust: avoid NPE due to odd problems with object initialization;
wenzelm
parents:
69982
diff
changeset
|
94 |
private lazy val meta_data_table = |
69900 | 95 |
Map( |
96 |
Markup.META_TITLE -> Property.title, |
|
97 |
Markup.META_CREATOR -> Property.creator, |
|
98 |
Markup.META_CONTRIBUTOR -> Property.contributor, |
|
99 |
Markup.META_DATE -> Property.date, |
|
69982 | 100 |
Markup.META_LICENSE -> Property.license, |
101 |
Markup.META_DESCRIPTION -> Property.description) |
|
69900 | 102 |
|
103 |
def meta_data(props: Properties.T): Properties.T = |
|
104 |
props.flatMap({ case (a, b) => meta_data_table.get(a).map((_, b)) }) |
|
69807 | 105 |
} |