<!-- logicOut.xsl - generate fopl assertions -->

<!-- This stylesheet generates fopl assertions based on a -->
<!-- document decorated with map: attributes. -->
<!-- infoset-r.xsl generates decorated documents based on -->
<!-- a serialized infoset produced by xsv -r -->

<xsl:stylesheet version="1.0"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:i  ="http://www.w3.org/2001/05/XMLInfoset"
 xmlns:psv="http://www.w3.org/2001/05/PSVInfosetExtension"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:map="http://www.cogsci.ed.ac.uk/~kari/schema-mapping"
 xmlns:fopl="http:www.cogsci.ed.ac.uk/~kari/firstOrderPredicateLogic"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:variable name="standardBuiltins" select="document('standardBuiltins.xml')/map:pings"/>
  <xsl:variable name="defaultStepIndent" select="'  '"/>

  <xsl:template name="getMappedTypeName">
    <xsl:param name="xmlTypeName"/>
    <xsl:variable name="namespaceName" select="substring-before (substring-after ($xmlTypeName, '{'), '}')"/>
    <xsl:variable name="localName" select="substring-after($xmlTypeName, '}')"/>
    <xsl:choose>
      <!--xsl:when test="$namespaceName='http://www.w3.org/2001/XMLSchema'">
        <xsl:value-of select="$standardBuiltins/map:simpleType[@name=$localName]/map:ping[@map:lang='fopl']"/>
      </xsl:when-->
      <!-- should there really be a mapping for fopl? it might be
           sufficient to use the local name of the type? what about
           name collisions? what about types other than schema
           builtins that don't have mappings? maybe use expanded
           names? -->
      <xsl:when test="''"/>
      <xsl:otherwise>
        <xsl:value-of select="$localName"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="getMappedTypeIsPrimitive">
    <xsl:param name="xmlTypeName"/>
    <xsl:variable name="namespaceName" select="substring-before (substring-after ($xmlTypeName, '{'), '}')"/>
    <xsl:variable name="localName" select="substring-after($xmlTypeName, '}')"/>
    <xsl:choose>
      <xsl:when test="$namespaceName='http://www.w3.org/2001/XMLSchema'">
        <xsl:value-of select="$standardBuiltins/map:simpleType[@name=$localName]/map:ping[@map:lang='Java']/@primitive"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="'false'"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <xsl:template match="/">
    <fopl:assertions>
      <xsl:apply-templates select="*">
        <xsl:with-param name="indent" select="''"/>
        <xsl:with-param name="map:parentItem" select="."/>
      </xsl:apply-templates>
    </fopl:assertions>
  </xsl:template>


  <xsl:template match="*">
    <xsl:param name="indent"/>
    <xsl:param name="map:parentItem"/>

    <xsl:choose>
      <xsl:when test="@map:type-to='nothing'">
        <!-- do nothing -->
      </xsl:when>
      <xsl:when test="@map:type-to='promote'">
        <!-- don't process this node, process its children only -->
        <!-- don't 'increment' map:parentItem -->
        <xsl:apply-templates select="*">
          <xsl:with-param name="indent" select="concat ($defaultStepIndent, $indent)"/>
          <xsl:with-param name="map:parentItem" select="$map:parentItem"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <!-- process this node and its children -->
	<xsl:if test="@map:type-to='atom'">
	  <xsl:call-template name="atom"/>
	</xsl:if>
	<xsl:if test="@map:type-to='individual'">
	  <xsl:call-template name="individual"/>
	</xsl:if>

        <!--xsl:call-template name="property">
          <xsl:with-param name="indent" select="$indent"/>
          <xsl:with-param name="map:parentItem" select="$map:parentItem"/>
        </xsl:call-template-->

        <xsl:apply-templates select="*">
          <xsl:with-param name="indent" select="concat ($defaultStepIndent, $indent)"/>
          <xsl:with-param name="map:parentItem" select="."/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>

  </xsl:template>


  <xsl:template name="individual">
    <xsl:variable name="mappedTypeName">
      <xsl:call-template name="getMappedTypeName">
        <xsl:with-param name="xmlTypeName" select="@map:type-name"/>
      </xsl:call-template>
    </xsl:variable>
    <fopl:individual id="{generate-id()}" type="{$mappedTypeName}"/>
    <xsl:if test="../..">
      <fopl:relation name="{@map:item-name}">
        <fopl:pointer ref="{generate-id(..)}"/>
        <fopl:pointer ref="{generate-id()}"/>
      </fopl:relation>
    </xsl:if>
  </xsl:template>


  <xsl:template name="atom">
    <xsl:variable name="mappedTypeName">
      <xsl:call-template name="getMappedTypeName">
        <xsl:with-param name="xmlTypeName" select="@map:type-name"/>
      </xsl:call-template>
    </xsl:variable>
    <fopl:relation name="{@map:item-name}">
      <fopl:pointer ref="{generate-id(..)}"/>
      <fopl:atom type="{$mappedTypeName}">
        <xsl:value-of select="."/>
      </fopl:atom>
    </fopl:relation>
  </xsl:template>


  <xsl:template name="property">
    <xsl:param name="indent"/>
    <xsl:param name="map:parentItem"/>

    <xsl:variable name="mappedTypeName">
      <xsl:call-template name="getMappedTypeName">
        <xsl:with-param name="xmlTypeName" select="@map:type-name"/>
      </xsl:call-template>
    </xsl:variable>

    <!-- this variable holds the map:type-name attribute of the current node for out-of-context comparison -->
    <xsl:variable name="map:type-name" select="@map:type-name"/>

    <!-- array initialization -->
    <!-- temporarily disabled -->
    <xsl:if test="false() and (@map:maxOccurs &gt; 1 or @map:maxOccurs='unbounded') and
         count(preceding-sibling::*[@map:type-name=$map:type-name])=0">
      <xsl:value-of select="$indent"/><xsl:value-of select="$mappedTypeName"/>
      <xsl:text>[] a</xsl:text>
      <xsl:value-of select="generate-id()"/> = new <xsl:text/>
      <xsl:value-of select="$mappedTypeName"/>
      <xsl:text>[</xsl:text>
      <xsl:value-of select="count(../*[@map:type-name=$map:type-name])"/>
      <xsl:text>]</xsl:text>;  // initialize an array
    <xsl:value-of select="$indent"/>
      <xsl:value-of select="generate-id($map:parentItem)"/>.<xsl:value-of select="@map:item-name"/>
      <xsl:text/> = a<xsl:value-of select="generate-id()"/>;  // assign the array to it's parent's member
    </xsl:if>

    <!-- scalar initialization -->
    <xsl:value-of select="$indent"/><xsl:value-of select="$mappedTypeName"/>
    <xsl:text> (</xsl:text>
    <xsl:value-of select="generate-id()"/>) //  <xsl:text/>

    <xsl:variable name="mappedTypeIsPrimitive">
      <xsl:call-template name="getMappedTypeIsPrimitive">
        <xsl:with-param name="xmlTypeName" select="@map:type-name"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:if test="$mappedTypeIsPrimitive = 'false'">
      <xsl:value-of select="concat ('new ', $mappedTypeName, ' (&quot;')"/>
    </xsl:if>

    <xsl:value-of select="text()"/>

    <xsl:if test="$mappedTypeIsPrimitive = 'false'">
      <xsl:value-of select="'&quot;)'"/>
    </xsl:if>

    <xsl:text>;
    </xsl:text>

    <!-- assignment to parent -->
    <!-- check that this element has a parent that is not root -->
    <xsl:if test="../..">
      <xsl:value-of select="$indent"/>
      <xsl:value-of select="generate-id($map:parentItem)"/>.<xsl:value-of select="@map:item-name"/>

      <!-- check if this element is as array member -->
      <!-- temporarily disabled -->
      <xsl:if test="false() and (@map:maxOccurs &gt; 1 or @map:maxOccurs='unbounded')">
        <xsl:text>[</xsl:text>
        <xsl:value-of select="count(preceding-sibling::*[@map:type-name=$map:type-name])"/>
        <xsl:text>]</xsl:text>
      </xsl:if>

      <xsl:text/> = <xsl:value-of select="generate-id()"/>;
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>
