<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
		xmlns:db="http://docbook.org/ns/docbook"
		xmlns:dc="http://purl.org/dc/elements/1.1/"
		xmlns:owl="http://www.w3.org/2002/07/owl#"
		xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
		xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
		xmlns:f="http://docbook.org/xslt/ns/extension"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
		exclude-result-prefixes="f xs"
                version="2.0">

<xsl:output method="xml" encoding="utf-8" indent="yes"
	    omit-xml-declaration="yes"/>

<xsl:strip-space elements="*"/>

<xsl:param name="ns" select="'http://www.w3.org/2006/vcard/ns#'"/>

<xsl:template match="db:book">
  <rdf:RDF>
    <xsl:apply-templates select="db:info"/>
    <xsl:apply-templates
	select="//db:refentry[db:refmeta/db:refmiscinfo[@role='rdf:type']='owl:Class']"
	mode="class"/>
    <xsl:apply-templates
	select="//db:refentry[db:refmeta/db:refmiscinfo[@role='rdf:type']='owl:ObjectProperty']
		|//db:refentry[db:refmeta/db:refmiscinfo[@role='rdf:type']='owl:DatatypeProperty']"
	mode="property"/>
  </rdf:RDF>
</xsl:template>

<xsl:template match="db:info">
  <owl:Ontology rdf:about="{$ns}">
    <dc:title>
      <xsl:value-of select="db:title"/>
    </dc:title>
    <xsl:for-each select=".//db:author/db:personname">
      <dc:creator>
	<xsl:value-of select="db:firstname"/>
	<xsl:text> </xsl:text>
	<xsl:value-of select="db:surname"/>
      </dc:creator>
    </xsl:for-each>
    <dc:date>
      <xsl:value-of select="db:pubdate"/>
    </dc:date>
    <dc:description>
      <xsl:value-of select="db:abstract/db:para[1]"/>
    </dc:description>
  </owl:Ontology>
</xsl:template>

<xsl:template match="db:refentry" mode="class">
  <owl:Class rdf:about="{f:uri(db:refnamediv/db:refname, .)}">
    <rdfs:comment>
      <xsl:value-of select="db:refnamediv/db:refpurpose"/>
    </rdfs:comment>
    <xsl:apply-templates select="db:refmeta/db:refmiscinfo[@role='rdfs:label']"/>
    <xsl:apply-templates select=".//db:itemizedlist[@role='constraints']"/>
  </owl:Class>
</xsl:template>

<xsl:template match="db:itemizedlist[@role='constraints']">
  <xsl:for-each select=".//db:para[@role='cardinality' and contains(.,'at most')]">
    <rdfs:subClassOf rdf:parseType="Resource">
      <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#Restriction"/>
      <owl:maxCardinality rdf:datatype="{f:uri(db:token/@role, .)}">
	<xsl:value-of select="db:token"/>
      </owl:maxCardinality>
      <owl:onProperty rdf:resource="{f:uri(db:property, .)}"/>
    </rdfs:subClassOf>
  </xsl:for-each>

  <xsl:for-each select=".//db:para[@role='domain']">
    <xsl:choose>
      <xsl:when test="contains(., 'union of')">
	<rdfs:domain rdf:parseType="Resource">
	  <owl:unionOf rdf:parseType="Resource">
	    <xsl:call-template name="list">
	      <xsl:with-param name="elements" select="db:classname"/>
	    </xsl:call-template>
	  </owl:unionOf>
	</rdfs:domain>
      </xsl:when>
      <xsl:otherwise>
	<rdfs:domain rdf:resource="{f:uri(db:classname, .)}"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>

  <xsl:for-each select=".//db:para[@role='range']">
    <xsl:choose>
      <xsl:when test="contains(., 'union of')">
	<rdfs:range rdf:parseType="Resource">
	  <owl:unionOf rdf:parseType="Resource">
	    <xsl:call-template name="list">
	      <xsl:with-param name="elements" select="db:classname"/>
	    </xsl:call-template>
	  </owl:unionOf>
	</rdfs:range>
      </xsl:when>
      <xsl:otherwise>
	<rdfs:range rdf:resource="{f:uri(db:classname, .)}"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each>
</xsl:template>

<xsl:template match="db:refmiscinfo[@role='rdfs:label']">
  <rdfs:label>
    <xsl:value-of select="."/>
  </rdfs:label>
</xsl:template>

<xsl:template match="db:refentry" mode="property">
  <xsl:variable name="type" select="db:refmeta/db:refmiscinfo[@role='rdf:type']"/>

  <xsl:element name="{$type}">
    <xsl:attribute name="rdf:about"
		   select="f:uri(db:refnamediv/db:refname,.)"/>
    <rdfs:comment>
      <xsl:value-of select="db:refnamediv/db:refpurpose"/>
    </rdfs:comment>
    <xsl:apply-templates select="db:refmeta/db:refmiscinfo[@role='rdfs:label']"/>
    <xsl:apply-templates select=".//db:itemizedlist[@role='constraints']"/>
  </xsl:element>
</xsl:template>

<!--============================================================ -->

<xsl:template name="list">
  <xsl:param name="elements" as="element()+" required="yes"/>

  <rdf:first rdf:resource="{f:uri($elements[1],.)}"/>
  <xsl:choose>
    <xsl:when test="count($elements) = 1">
      <rdf:rest rdf:resource="http://www.w3.org/1999/02/22-rdf-syntax-ns#nil"/>
    </xsl:when>
    <xsl:otherwise>
      <rdf:rest rdf:parseType="Resource">
	<xsl:call-template name="list">
	  <xsl:with-param name="elements" select="$elements[position() &gt; 1]"/>
	</xsl:call-template>
      </rdf:rest>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:function name="f:uri">
  <xsl:param name="qname" as="xs:string"/>
  <xsl:param name="context" as="element()"/>

  <xsl:variable name="qn" select="resolve-QName($qname,$context)"/>
  <xsl:value-of select="namespace-uri-from-QName($qn)"/>
  <xsl:value-of select="local-name-from-QName($qn)"/>
</xsl:function>

</xsl:stylesheet>

