<xsl:transform 
    xmlns:xsl  ="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:h    ="http://www.w3.org/1999/xhtml"
    xmlns:shoe ="http://www.cs.umd.edu/projects/plus/SHOE/"
    xmlns:sshoe="http://www.w3.org/2000/04shoe-swell/#"
    xmlns:shoeb="http://www.w3.org/2000/04shoe-swell/convert?in=http://www.cs.umd.edu/projects/plus/SHOE/onts/base1.0.html#"
    xmlns:rdf  ="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:rdfs ="http://www.w3.org/2000/01/rdf-schema#"
    xmlns:uri  ="http://www.w3.org/2000/07/uri43/uri.xsl?template="
    xmlns:kif  ="http://www.w3.org/2000/07/hs78/KIF#"
	exclude-result-prefixes="h shoe uri"
    >

<xsl:import href="../07/uri43/uri.xsl"/>
<xsl:param name="Base"/>

<div xmlns="http://www.w3.org/1999/xhtml">
<p>$Id: shoe-swell.xsl,v 1.16 2000/08/14 08:41:32 connolly Exp $</p>

<p>based on <a
href="http://www.cs.umd.edu/projects/plus/SHOE/spec.html">SHOE 1.01
Specification</a>, April 28, 2000, Sean Luke and Jeff Heflin</p>

<p>things to check: @@ me, @@ !constants</p>

</div>

<xsl:output method="xml" indent="yes"/>

<xsl:param name="URI"/> <!-- of the shoe document we're converting -->

<xsl:variable name="Empty" select='"http://www.w3.org/2000/07/12-lists#empty"'/>

<xsl:variable name="ShoeBaseNS"
	      select='"http://www.w3.org/2000/04shoe-swell/convert?in=http://www.cs.umd.edu/projects/plus/SHOE/onts/base1.0.html#"'/>

<xsl:variable name="KIFWordNS"
	select='"http://www.w3.org/2000/07/hs78/KIF?word="'/>

<xsl:variable name="KIFNS"
	select='"http://www.w3.org/2000/07/hs78/KIF#"'/>

<!-- cf 1.2 Indicating a SHOE-conformant Document -->

<xsl:template match="/h:html[//h:meta/@http-equiv='SHOE'
	and //h:meta/@content='VERSION=1.0']">
  <rdf:RDF>

    <!-- "Ontology declarations may appear at the top level
	 within the body of an HTML document (i.e., they may
	 not be enclosed by any other tags within the BODY)."
	 - 3 Declaring Ontologies -->
    <xsl:for-each select="*/shoe:ontology">
      <sshoe:Ontology
		sshoe:id="{@id}"
		sshoe:version="{@version}"
		shoeb:description="{@description}">

		<!-- we don't say "and there are no others",
		     i.e. we don't preserve the list-ness -->
        <xsl:call-template name="each-literal">
	  <xsl:with-param name="objects"
			  select="normalize-space(@backward-compatible-with)"/>
          <xsl:with-param name="property"
			  select='"sshoe:backward-compatible-with"'/>
        </xsl:call-template>

        <xsl:call-template name="each-literal"> <!-- @@each-reference: absolutize, pointToConversion -->
	  <xsl:with-param name="objects"
			  select="normalize-space(@declarators)"/>
          <xsl:with-param name="property"
			  select='"sshoe:declarators"'/> <!-- @@ make it a Seq? i.e. preserve lists-ness? -->
        </xsl:call-template>


        <xsl:for-each select="shoe:use-ontology">
	  <sshoe:use-ontology>
	    <sshoe:Ontology
	       sshoe:id="{@id}"
	       sshoe:version="{@version}"
	       >
	      <xsl:if test="@url">
	        <xsl:attribute name="about">
		  <xsl:call-template name="pointToConversion">
		    <xsl:with-param name="shoeAddr"
				    select="@url"/> <!-- @@SPECQ: absolutize? -->
		  </xsl:call-template>
		</xsl:attribute>
	      </xsl:if>
	    </sshoe:Ontology>
	  </sshoe:use-ontology>
	</xsl:for-each>

      </sshoe:Ontology>

        <xsl:for-each select="shoe:def-category">
          <sshoe:Category rdf:ID='{@name}'
	    shoeb:description="{@description}"
	    sshoe:short="{@short}">
	    <!-- @@ omit description attribute in output
		    if it's not in input? -->

            <xsl:call-template name="each-name">
	      <xsl:with-param name="names" select="@isa"/>
	      <xsl:with-param name="property"
			      select="'sshoe:isa'"/>
            </xsl:call-template>
	  </sshoe:Category>

	</xsl:for-each>

        <xsl:for-each select="shoe:def-relation">
          <sshoe:Relation rdf:ID="{@name}"
	    sshoe:short="{@short}">

	    <!-- @@do something with short="..." on def-arg -->
          <xsl:for-each select="shoe:def-arg[number(@pos)=1]">
            <!-- complain if there is more than one @@VALIDATE -->
	    <xsl:variable name="d">
	      <xsl:call-template name="name2uri">
	        <xsl:with-param name="n" select="@type"/>
	      </xsl:call-template>
	    </xsl:variable>

            <rdfs:domain resource="{$d}"/>
	  </xsl:for-each>

	  <xsl:for-each select="shoe:def-arg[number(@pos)=2]">
	    <!-- complain if there is more than one @@VALIDATE -->

	    <xsl:variable name="r">
	      <xsl:call-template name="name2uri">
	        <xsl:with-param name="n" select="@type"/>
	      </xsl:call-template>
	    </xsl:variable>

            <rdfs:domain resource="{$r}"/>
          </xsl:for-each>

          <xsl:for-each select="shoe:def-arg[number(@pos)>2]">
            <xsl:message>@@found n-ary predicate; only binary predicates are
	    implemented</xsl:message>
          </xsl:for-each>
        </sshoe:Relation>
      </xsl:for-each>


      <!-- @@ 3.5 Renaming Rules -->


      <xsl:for-each select="shoe:def-inference">

	<!-- wtr is a one place relation in KIF, i.e. an RDF class -->
        <kif:wtr
		shoeb:description='{@description}'>

          <kif:first resource='{concat($KIFWordNS, "%3d%3e")}'/> <!-- => uri-escaped -->

	  <xsl:for-each select="shoe:inf-if"> <!-- there's only one -->
	    <kif:rest><kif:list><kif:first>
	      <kif:list>
		<kif:first resource='{concat($KIFWordNS, "and")}'/>

	        <xsl:call-template name="list-props">
	          <xsl:with-param name="idx" select="1"/>
	          <xsl:with-param name="qty" select="count(*)"/>
		  <xsl:with-param name="list" select="."/>
		</xsl:call-template>
	      </kif:list>
	    </kif:first>
	    <kif:rest><kif:list><kif:first>
	  <xsl:for-each select="shoe:inf-then"> <!-- there's only one -->
	      <kif:list>
		<kif:first resource='{concat($KIFWordNS, "and")}'/>
	        <xsl:call-template name="list-props">
	          <xsl:with-param name="idx" select="1"/>
	          <xsl:with-param name="qty" select="count(*)"/>
		  <xsl:with-param name="list" select="."/>
		</xsl:call-template>
	      </kif:list>
	  </xsl:for-each>
	    </kif:first></kif:list></kif:rest></kif:list></kif:rest>
      </xsl:for-each>
        </kif:wtr>

	  </xsl:for-each>

      <!-- @@ Constants -->
      <!-- @@ types -->

    </xsl:for-each>

  </rdf:RDF>
</xsl:template>

<!-- http://www.w3.org/2000/04shoe-swell/convert? is (shall be)
	a service that converts SHOE to RDF as specified
	by this transformation. -->
<xsl:template name="pointToConversion">
  <xsl:param name="shoeAddr"/>

  <!-- @@ %XX escape shoeAddr -->
  <!-- tidy flag? -->
  <xsl:value-of select='concat("http://www.w3.org/2000/04shoe-swell/convert?in=", $shoeAddr)'/>

</xsl:template>

<!-- ontology markup -->



<xsl:template name="list-props">
  <xsl:param name="list"/>
  <xsl:param name="idx"/>
  <xsl:param name="qty"/>

  <xsl:choose>
    <xsl:when test='$qty >= $idx'>
      <xsl:for-each select='$list/*[$idx]'>
        <xsl:choose>

	  <xsl:when test='local-name()="relation"'>
	    <kif:rest>
              <kif:list>
	        <kif:first>
	          <xsl:call-template name="extract-prop"/>
		</kif:first>

	        <xsl:call-template name="list-props">
		  <xsl:with-param name="idx" select="$idx + 1"/>
		  <xsl:with-param name="qty" select="$qty"/>
		  <xsl:with-param name="list" select="$list"/>
		</xsl:call-template>
	      </kif:list>
	    </kif:rest>
	  </xsl:when>

	  <xsl:otherwise>
	    <xsl:message>@@unimplemented subclause syntax</xsl:message>
	  </xsl:otherwise>
	</xsl:choose>
      </xsl:for-each>
    </xsl:when>

    <xsl:otherwise>
	<!-- null is a one place relation in KIF, i.e. an RDF class -->
      <kif:rest><kif:null/></kif:rest>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="extract-prop">
  <xsl:variable name="from" select='shoe:arg[@pos="FROM"]'/>
  <xsl:variable name="to" select='shoe:arg[@pos="TO"]'/>

  <!-- @@nary, pos=1/2 -->

  <rdf:Statement>
    <xsl:variable name="pred">
      <xsl:call-template name="name2uri">
        <xsl:with-param name="n" select="@name"/>
      </xsl:call-template>
    </xsl:variable>

    <rdf:predicate resource="{concat($KIFWordNS, $pred)}"/>

    <rdf:subject>
      <xsl:attribute name="resource">
        <xsl:call-template name="ruleArg">
	  <xsl:with-param name="arg" select="$from"/>
	</xsl:call-template>
      </xsl:attribute>
    </rdf:subject>

    <rdf:object>
      <xsl:attribute name="resource">
        <xsl:call-template name="ruleArg">
	  <xsl:with-param name="arg" select="$to"/>
	</xsl:call-template>
      </xsl:attribute>
    </rdf:object>

  </rdf:Statement>
</xsl:template>

<xsl:template name="ruleArg">
  <xsl:param name="arg"/>

  <xsl:choose>
    <xsl:when test='$arg/@usage = "var"'>
      <xsl:value-of select='concat($KIFWordNS, "%3f", $arg/@value)'/>
						 <!-- %3f for ? -->
    </xsl:when>

    <xsl:otherwise>
      <xsl:message>@@assuming rule arg is a literal: [<xsl:value-of select="$arg/@value"/>]; @@constants, etc.</xsl:message>
      <xsl:value-of select="$arg/@value"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- instance markup -->

<xsl:template match="shoe:instance"> <!-- hmm... need to un-nest these@@ -->
  <rdf:Description about="{@key}">
    <xsl:apply-templates/>
  </rdf:Description>
</xsl:template>

<xsl:template match="shoe:instance/shoe:category">
    <xsl:call-template name="named-object">
      <xsl:with-param name="name" select="@name"/>
      <xsl:with-param name="property" select="'rdf:type'"/>
    </xsl:call-template>
</xsl:template>

<xsl:template match="shoe:instance/shoe:relation[shoe:arg/@pos='TO']">
  <xsl:call-template name="named-property">
    <xsl:with-param name="name" select="@name"/>
    <xsl:with-param name="valueLit" select="shoe:arg/@value"/> <!-- @@ URI or not??? -->
  </xsl:call-template>
</xsl:template>


<!-- Utility templates -->


<xsl:template name="each-literal">
  <!-- produces a property element for each literal object in a list -->

  <xsl:param name="objects"/>
  <xsl:param name="property"/>

  <xsl:choose>
    <xsl:when test="contains($objects, ' ')">
      <xsl:element name="{$property}">
        <xsl:value-of select='substring-before($objects, " ")'/>
      </xsl:element>

      <xsl:call-template name="each-literal">
        <xsl:with-param name="objects"
    		    select='substring-after($objects, " ")'/>
        <xsl:with-param name="property" select="$property"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:when test="$objects">
      <xsl:element name="{$property}">
        <xsl:value-of select='$objects'/>
      </xsl:element>
    </xsl:when>

    <xsl:otherwise>
      <!-- nothing -->
    </xsl:otherwise>

  </xsl:choose>
</xsl:template>


<xsl:template name="each-name">
  <!-- produces a property element for each named object in a list -->

  <xsl:param name="names"/>
  <xsl:param name="property"/>

  <xsl:choose>
    <xsl:when test="contains($names, ' ')">
      <xsl:call-template name="named-object">
        <xsl:with-param name="name" select='substring-before($names, " ")'/>
	<xsl:with-param name="property" select="$property"/>
      </xsl:call-template>

      <xsl:call-template name="each-name">
        <xsl:with-param name="names"
    		    select='substring-after($names, " ")'/>
        <xsl:with-param name="property" select="$property"/>
      </xsl:call-template>
    </xsl:when>

    <xsl:otherwise>
      <xsl:call-template name="named-object">
        <xsl:with-param name="name" select='$names'/>
	<xsl:with-param name="property" select="$property"/>
      </xsl:call-template>
    </xsl:otherwise>

  </xsl:choose>
</xsl:template>

  <!-- this is ugly code. redo it@@ -->
<xsl:template name="named-object">
  <!-- produces a property element whose object
  comes from a shoe (qualified) name -->
  <!-- @@FIX: only one level of prefix is supported -->

  <xsl:param name="name"/>
  <xsl:param name="property"/>

  <xsl:variable name="prefix"
		select="substring-before($name, '.')"/>
  <xsl:variable name="convertedOntology">
    <xsl:call-template name="pointToConversion">
      <xsl:with-param name="shoeAddr"
		 select='ancestor::*/shoe:use-ontology[@prefix = $prefix]/@url'/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:choose>
    <xsl:when test="starts-with($name, '.')">
      <xsl:element name="{$property}">
        <xsl:attribute name="rdf:resource">
	  <xsl:call-template name="uri:expand">
	    <xsl:with-param name="base" select='$Base'/>
	    <xsl:with-param name="there">
	      <xsl:value-of select="concat($ShoeBaseNS,
			    substring-after($name, '.'))"/>
	    </xsl:with-param>
	  </xsl:call-template>
	</xsl:attribute>
      </xsl:element>
    </xsl:when>

    <xsl:when test="$prefix">
      <xsl:element name="{$property}">
        <xsl:attribute name="rdf:resource">
	  <xsl:call-template name="uri:expand">
	    <xsl:with-param name="base" select='$Base'/>
	    <xsl:with-param name="there">
              <xsl:value-of select="concat($convertedOntology, '#',
			    	        substring-after($name, '.'))"/>
	    </xsl:with-param>
	  </xsl:call-template>
	</xsl:attribute>
      </xsl:element>
    </xsl:when>

    <xsl:otherwise>
      <xsl:element name="{$property}">
        <xsl:attribute name="rdf:resource">
	  <xsl:call-template name="uri:expand">
	    <xsl:with-param name="base" select='$Base'/>
	    <xsl:with-param name="there">
              <xsl:value-of select="concat('#', $name)"/>
	    </xsl:with-param>
	  </xsl:call-template>
	</xsl:attribute>
      </xsl:element>

    </xsl:otherwise>
  </xsl:choose>

</xsl:template>


<xsl:template name="name2uri">
  <!-- converts a shoe qualified name to a URI -->
  <!-- @@FIX: only one level of prefix is supported -->
  <xsl:param name="n"/>

  <xsl:variable name="prefix"
		select="substring-before($n, '.')"/>
  <xsl:variable name="convertedOntology">
    <xsl:call-template name="pointToConversion">
      <xsl:with-param name="shoeAddr"
		 select='ancestor::*/shoe:use-ontology[@prefix = $prefix]/@url'/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:choose>
    <xsl:when test="starts-with($n, '.')">
      <xsl:value-of select="concat($ShoeBaseNS,
			substring-after($n, '.'))"/>
    </xsl:when>

    <xsl:when test="$prefix">
      <xsl:value-of select="concat($convertedOntology, '#',
                                   substring-after($n, '.'))"/>
    </xsl:when>

    <xsl:otherwise>
      <xsl:call-template name="uri:expand">
	<xsl:with-param name="base" select='$Base'/>
	<xsl:with-param name="there">
          <xsl:value-of select="concat('#', $n)"/>
	</xsl:with-param>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>

</xsl:template>


<!-- @@this is copy-and-paste programming. Blech.
     I've learned more about XSLT since I wrote this.
     I think I can factor out the commonality. -->

<xsl:template name="named-property">
  <!-- produces a property element whose property name
  comes from a shoe (qualified) name -->
  <!-- @@FIX: only one level of prefix is supported -->

  <xsl:param name="name"/>
  <xsl:param name="valueLit"/>
  <xsl:param name="valueRef"/>
  <xsl:param name="stID"/>

  <xsl:variable name="prefix"
		select="substring-before($name, '.')"/>
  <xsl:variable name="convertedOntology">
    <xsl:call-template name="pointToConversion">
      <xsl:param name="shoeAddr"
		 select='ancestor::*/shoe:use-ontology[@prefix = $prefix]/@url'/>
    </xsl:call-template>
  </xsl:variable>

  <xsl:choose>
    <xsl:when test="starts-with($name, '.')">
      <xsl:element name="{substring-after($name, '.')}"
		   namespace="{$ShoeBaseNS}">
	  <xsl:if test="$stID">
	    <xsl:attribute name="rdf:ID"><xsl:value-of select="$stID"/>
	    </xsl:attribute>
	  </xsl:if>

	  <xsl:call-template name="value">
	    <xsl:with-param name="valueRef" select="$valueRef"/>
	    <xsl:with-param name="valueLit" select="$valueLit"/>
	  </xsl:call-template>

      </xsl:element>
    </xsl:when>

    <xsl:when test="$prefix">
      <xsl:element name="{substring-after($name, '.')}"
		   namespace='{concat($convertedOntology, "#")}'>
	  <xsl:if test="$stID">
	    <xsl:attribute name="rdf:ID"><xsl:value-of select="$stID"/>
	    </xsl:attribute>
	  </xsl:if>
	  <xsl:call-template name="value">
	    <xsl:with-param name="valueRef" select="$valueRef"/>
	    <xsl:with-param name="valueLit" select="$valueLit"/>
	  </xsl:call-template>
      </xsl:element>

    </xsl:when>

    <xsl:otherwise>
      <!-- @@ is this an error case? -->
      <xsl:element name="{$name}">
	  <xsl:if test="$stID">
	    <xsl:attribute name="rdf:ID"><xsl:value-of select="$stID"/>
	    </xsl:attribute>
	  </xsl:if>
	  <xsl:call-template name="value">
	    <xsl:with-param name="valueRef" select="$valueRef"/>
	    <xsl:with-param name="valueLit" select="$valueLit"/>
	  </xsl:call-template>
      </xsl:element>

    </xsl:otherwise>
  </xsl:choose>

</xsl:template>


<xsl:template name="value">
  <xsl:param name="valueRef"/>
  <xsl:param name="valueLit"/>

  <xsl:choose>
    <xsl:when test="$valueRef">
      <xsl:attribute name="rdf:resource">
        <xsl:call-template name="uri:expand">
	  <xsl:with-param name="base" select='$Base'/>
	  <xsl:with-param name="there">
	    <xsl:value-of select="$valueRef"/>
	  </xsl:with-param>
	</xsl:call-template>
      </xsl:attribute>
    </xsl:when>

    <xsl:otherwise>
      <xsl:value-of select="$valueLit"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<!-- don't pass text thru -->
<xsl:template match="text()|@*">
</xsl:template>

</xsl:transform>
