src/Pure/General/rdf.scala
author wenzelm
Sun, 09 Jul 2023 14:33:45 +0200
changeset 78273 95a3bb4d7e38
parent 75393 87ebf5a50283
permissions -rw-r--r--
clarified "vacuum" operation for various database versions (PostgreSQL <= 10 is strictly speaking obsolete, but still used on some test machines);
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
69807
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/General/rdf.scala
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     3
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     4
Support for RDF/XML representation, see also:
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     5
  - https://www.w3.org/RDF
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     6
  - https://www.w3.org/TR/rdf-primer
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     7
*/
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     8
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
     9
package isabelle
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    10
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    11
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    12
object RDF {
69807
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    13
  /* document */
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    14
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    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
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    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
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    19
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    20
  def document(body: XML.Body,
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    21
    namespaces: List[XML.Namespace] = default_namespaces,
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    22
    attributes: XML.Attributes = Nil
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    23
  ): XML.Elem = {
69807
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    24
    XML.Elem(Markup(rdf("RDF"), namespaces.map(_.attribute) ::: attributes), body)
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    25
  }
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    26
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    27
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    28
  /* multiple triples vs. compact description */
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    29
69902
9c697c7ad8d6 URIs should normally be "rdf:resource", not string body;
wenzelm
parents: 69900
diff changeset
    30
  sealed case class Triple(
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    31
    subject: String,
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    32
    predicate: String,
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    33
    `object`: XML.Body = Nil,
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    34
    resource: String = ""
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    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
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    41
  }
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    42
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    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
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    51
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    52
  def description(subject: String, body: XML.Body, attributes: XML.Attributes = Nil): XML.Elem =
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
    53
    XML.Elem(Markup(rdf("Description"), (rdf("about"), subject) :: attributes), body)
69808
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    54
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    55
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    56
  /* collections */
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    57
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    58
  def collection(kind: String, items: List[XML.Body]): XML.Elem =
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    59
    XML.elem(kind, items.map(item => XML.elem(rdf("li"), item)))
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    60
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    61
  def bag(items: List[XML.Body]): XML.Elem = collection(rdf("Bag"), items)
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    62
  def seq(items: List[XML.Body]): XML.Elem = collection(rdf("Seq"), items)
c64197a224c6 more operations;
wenzelm
parents: 69807
diff changeset
    63
  def alt(items: List[XML.Body]): XML.Elem = collection(rdf("Alt"), items)
69809
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    64
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    65
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    66
  /* datatypes */
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    67
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    68
  // see https://www.w3.org/TR/rdf11-concepts/#section-Datatypes
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    69
  // see https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    70
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    71
  def string(x: String): XML.Body = if (x.isEmpty) Nil else List(XML.Text(x))
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    72
  def bool(x: Boolean): XML.Body = string(x.toString)
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    73
  def int(x: Int): XML.Body = string(Value.Int(x))
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    74
  def long(x: Long): XML.Body = string(Value.Long(x))
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    75
  def double(x: Double): XML.Body = string(Value.Double(x))
028f61045e8d more operations;
wenzelm
parents: 69808
diff changeset
    76
  def seconds(x: Time): XML.Body = double(x.seconds)
69982
f150253cb201 RDF meta data for AFP entries;
wenzelm
parents: 69916
diff changeset
    77
f150253cb201 RDF meta data for AFP entries;
wenzelm
parents: 69916
diff changeset
    78
  val date_format: Date.Format = Date.Format("uuuu-MM-dd'T'HH:mm:ss.SSSxxx")
f150253cb201 RDF meta data for AFP entries;
wenzelm
parents: 69916
diff changeset
    79
  def date_time_stamp(x: Date): XML.Body = string(date_format(x))
69858
3d0f27273aa1 concrete predicates from "Dublin Core";
wenzelm
parents: 69809
diff changeset
    80
3d0f27273aa1 concrete predicates from "Dublin Core";
wenzelm
parents: 69809
diff changeset
    81
3d0f27273aa1 concrete predicates from "Dublin Core";
wenzelm
parents: 69809
diff changeset
    82
  /* predicates */
3d0f27273aa1 concrete predicates from "Dublin Core";
wenzelm
parents: 69809
diff changeset
    83
75393
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    84
  object Property {
87ebf5a50283 clarified formatting, for the sake of scala3;
wenzelm
parents: 69983
diff changeset
    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
3d0f27273aa1 concrete predicates from "Dublin Core";
wenzelm
parents: 69809
diff changeset
    92
  }
69900
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
    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
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
    95
    Map(
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
    96
      Markup.META_TITLE -> Property.title,
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
    97
      Markup.META_CREATOR -> Property.creator,
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
    98
      Markup.META_CONTRIBUTOR -> Property.contributor,
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
    99
      Markup.META_DATE -> Property.date,
69982
f150253cb201 RDF meta data for AFP entries;
wenzelm
parents: 69916
diff changeset
   100
      Markup.META_LICENSE -> Property.license,
f150253cb201 RDF meta data for AFP entries;
wenzelm
parents: 69916
diff changeset
   101
      Markup.META_DESCRIPTION -> Property.description)
69900
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
   102
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
   103
  def meta_data(props: Properties.T): Properties.T =
18a61caf5e68 support for document meta data in PIDE and RDF;
wenzelm
parents: 69870
diff changeset
   104
    props.flatMap({ case (a, b) => meta_data_table.get(a).map((_, b)) })
69807
3389fda6cffd support for RDF/XML representation;
wenzelm
parents:
diff changeset
   105
}