<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:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="text"/>
  <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='Java']"/>
      </xsl:when>
      <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="/">
public class Test {
    public static void main (String[] argv) {
        init();
    }
    public static <xsl:text/>
    <xsl:call-template name="getMappedTypeName">
      <xsl:with-param name="xmlTypeName" select="*/@map:type-name"/>
    </xsl:call-template>
    <xsl:text/> init () {
    <xsl:apply-templates select="*">
      <xsl:with-param name="indent" select="'    '"/>
      <xsl:with-param name="map:parentItem" select="."/>
    </xsl:apply-templates>
        return <xsl:value-of select="generate-id (*)"/>;
    }
}
  </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: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="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 -->
    <xsl:if test="(@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 -->
      <xsl:if test="@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>
