<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:output method='html' encoding='iso-8859-1'/>

  <xsl:param name="top-documentation-link">../index.html</xsl:param>

  <!-- Main ==============================================================-->
  
  <xsl:template match="module">
    <html>
      <head>
        <title>
          <xsl:text>4Suite API Documentation: </xsl:text>
          <xsl:value-of select="@name"/>
        </title>
        <style>
          <xsl:comment>
            <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"
                        href="modules.css" parse="text"/>
          </xsl:comment>
        </style>
        <link rel="stylesheet" type="text/css" href="modules.css"/>
      </head>
      <body>
        <div class="universal-header">
          <span class="universal-header-prefix">&#160;&#160;&#160;</span>
          <xsl:text>&#160;</xsl:text>
          <span class="universal-header-prefix">&#160;&#160;</span>
          <xsl:text>&#160;</xsl:text>
          <span class="universal-header-prefix">&#160;</span>
          <xsl:text>&#160;</xsl:text>
          <a href="{$top-documentation-link}">4Suite<sup>&#8482;</sup> API Documentation</a>
        </div>
        <h1>
          <span class="glyph-arrow">&#9658;</span>
          <xsl:text> Module </xsl:text>
          <span class="this-name">
            <xsl:call-template name='link-python-path'>
              <xsl:with-param name='path' select='@name'/>
            </xsl:call-template>
          </span>
        </h1>

        <xsl:apply-templates select="abstract"/>
        <xsl:apply-templates select="description"/>

        <xsl:variable name="members" 
                      select="(classes|functions|fields)[*/@public = 'yes']"/>
        <xsl:if test="$members">
          <div class="summary-section">
            <table cellpadding="0" cellspacing="0">
              <tbody>
                <tr>
                  <xsl:apply-templates select="$members" mode="summary"/>
                </tr>
              </tbody>
            </table>
          </div>
        </xsl:if>

        <xsl:apply-templates select="modules"/>
        <xsl:apply-templates select="classes"/>
        <xsl:apply-templates select="functions"/>
        <xsl:apply-templates select="fields"/>

        <div class="universal-footer">
          <xsl:text>Last modified on </xsl:text>
          <xsl:value-of select="modification-date"/>
        </div>
      </body>
    </html>
  </xsl:template>

  <!-- Module Summary ====================================================-->

  <xsl:template match="classes | functions | fields" mode="summary">
    <!-- add separator cells between groups -->
    <xsl:if test="position() != 1">
      <td valign="middle" width="7"/>
      <td valign="middle" width="1" bgcolor="#C5C5C5"/>
      <td valign="middle" width="7"/>
    </xsl:if>

    <td valign="top">
      <div class="summary-header">
        <xsl:choose>
          <xsl:when test="name() = 'modules'">Modules:</xsl:when>
          <xsl:when test="name() = 'classes'">Classes:</xsl:when>
          <xsl:when test="name() = 'functions'">Functions:</xsl:when>
          <xsl:when test="name() = 'fields'">Fields:</xsl:when>
        </xsl:choose>
      </div>
      <div class="summary-list">
        <xsl:for-each select="*[@public = 'yes']">
          <a href="#{@name}"><xsl:value-of select="@name"/></a>
          <xsl:if test="position() != last()">, </xsl:if>
        </xsl:for-each>
      </div>
    </td>
  </xsl:template>

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

  <xsl:template match="modules">
    <xsl:if test="count(module-reference[@public = 'yes'])">
      <div class="section">
        <h2>Modules</h2>
        <table>
          <tbody>
            <xsl:apply-templates select="module-reference[@public = 'yes']"
                                 mode="module"/>
          </tbody>
        </table>
      </div>
    </xsl:if>
  </xsl:template>

  <xsl:template match="module-reference" mode="module">
    <tr>
      <td valign="top" class="moduledesc">
        <div class="definition module-name">
          <a name="{@name}"/>
          <xsl:choose>
            <xsl:when test="@documented = 'no'">
              <span class='undocumented'>
                <xsl:value-of select="@name"/>
              </span>
            </xsl:when>
            <xsl:otherwise>
              <a>
                <xsl:attribute name="href">
                  <xsl:call-template name='translate-href'>
                    <xsl:with-param name="href" select="@realname"/>
                  </xsl:call-template>
                </xsl:attribute>
                <xsl:value-of select="@name"/>
              </a>
            </xsl:otherwise>
          </xsl:choose>
        </div>
      </td>
      <td valign="bottom" class="moduledesc">
        <xsl:apply-templates select='abstract'/>
      </td>
    </tr>
  </xsl:template>

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

  <xsl:template match="classes">
    <xsl:if test="count(class[@public = 'yes'])">
      <div class="section">
        <h2>Classes</h2>
        <xsl:apply-templates select="class[@public = 'yes']"/>
      </div>
    </xsl:if>
  </xsl:template>
  
  <xsl:template name="class-reference">
    <xsl:choose>
      <xsl:when test="@documented = 'no'">
        <span class='undocumented'>
          <xsl:if test="@module">
            <xsl:value-of select="concat(@module, '.')"/>
          </xsl:if>
          <xsl:value-of select="@class"/>
        </span>
      </xsl:when>
      <xsl:otherwise>
        <xsl:variable name='href'>
          <xsl:call-template name='translate-href'>
            <xsl:with-param name='href' select='@module'/>
          </xsl:call-template>
        </xsl:variable>
        <a href='{$href}#{@class}'>
          <xsl:if test="@module != /module/@name">
            <xsl:value-of select="concat(@module, '.')"/>
          </xsl:if>
          <xsl:value-of select="@class"/>
        </a>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template name="inherited">
    <xsl:param name="type"/>

    <xsl:variable name="documented" select="@documented = 'yes'"/>
    <xsl:variable name='linkbase'>
      <xsl:call-template name='translate-href'>
        <xsl:with-param name='href' select='@module'/>
      </xsl:call-template>
      <xsl:text>#</xsl:text>
      <xsl:value-of select="@class"/>
    </xsl:variable>
        
    <h3>
      <xsl:value-of select="$type"/>
      <xsl:text> inherited from class </xsl:text>
      <xsl:call-template name="class-reference"/>
    </h3>
    <div class="synopsis inherited-list">
      <xsl:for-each select="member-reference">
        <xsl:choose>
          <xsl:when test="$documented">
            <a href='{$linkbase}-{@name}'>
              <xsl:value-of select="@name"/>
            </a>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="@name"/>
          </xsl:otherwise>
        </xsl:choose>
        <xsl:if test="position() != last()">, </xsl:if>
      </xsl:for-each>
    </div>
  </xsl:template>

  <xsl:template match="class">
    <div class="classdesc">
      <a name="{@name}"/>
      <div class="definition">
        <xsl:text>class </xsl:text>
        <span class="class-name">
          <xsl:value-of select="@name"/>
        </span>
        <xsl:apply-templates select="bases" mode="class"/>
      </div>
      <div class="synopsis">
        <xsl:apply-templates select="abstract"/>
        <xsl:apply-templates select="description"/>
        <xsl:apply-templates select="methods" mode="class"/>
        <xsl:apply-templates select="fields" mode="class"/>
      </div>
    </div>
    <xsl:if test="position() != last()">
      <hr/>
    </xsl:if>
  </xsl:template>

  <xsl:template match="bases" mode="class">
    <xsl:apply-templates select="base" mode="class"/>
  </xsl:template>

  <xsl:template match="base" mode="class">
    <xsl:if test="position() = 1">(</xsl:if>
    <span class="base-name">
      <xsl:call-template name="class-reference"/>
    </span>
    <xsl:choose>
      <xsl:when test="position() = last()">)</xsl:when>
      <xsl:otherwise>, </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match='methods' mode='class'>
    <h3>Methods</h3>
    <xsl:apply-templates mode='class'/>
  </xsl:template>

  <xsl:template match="methods[@inherited = 'yes']" mode="class">
    <xsl:call-template name="inherited">
      <xsl:with-param name="type">Methods</xsl:with-param>
    </xsl:call-template>
  </xsl:template>

  <xsl:template match='method | class-method | static-method | function' mode='class'>
    <div class="methoddesc">
      <div class="definition">
        <a name="{@id}">
          <span class="method-name">
            <xsl:value-of select='@name'/>
          </span>
        </a>
        <xsl:if test='@realname'> = </xsl:if>
        <xsl:choose>
          <xsl:when test='@realid'>
            <a href='#{@realid}'>
              <xsl:value-of select='@realname'/>
            </a>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select='@realname'/>
          </xsl:otherwise>
        </xsl:choose>
        <xsl:apply-templates select='arguments'/>
      </div>
      <div class="synopsis">
        <xsl:apply-templates select="abstract"/>
        <xsl:apply-templates select="description"/>
      </div>
    </div>
  </xsl:template>

  <xsl:template match='fields' mode='class'>
    <h3>Fields</h3>
    <xsl:apply-templates mode='class'/>
  </xsl:template>

  <xsl:template match='field' mode='class'>
    <div class="fielddesc">
      <div class="declaration">
        <a name="{@name}">
          <span class="field-name">
            <xsl:value-of select="@name"/>
          </span>
        </a>
        <xsl:text> = </xsl:text>
        <xsl:value-of select='value'/>
      </div>
      <div class="synopsis">
        <xsl:apply-templates select='abstract'/>
        <xsl:apply-templates select='description'/>
      </div>
    </div>
  </xsl:template>


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

  <xsl:template match="functions">
    <xsl:if test="count(function[@public = 'yes'])">
      <div class="section">
        <h2>Functions</h2>
        <xsl:apply-templates select="function[@public = 'yes']"/>
      </div>
    </xsl:if>
  </xsl:template>

  <xsl:template match="function">
    <div class="functiondesc">
      <div class="definition">
        <a name="{@id}">
          <span class="function-name">
            <xsl:value-of select='@name'/>
          </span>
        </a>
        <xsl:if test='@realname'> = </xsl:if>
        <xsl:choose>
          <xsl:when test='@realid'>
            <a href='#{@realid}'>
              <xsl:value-of select='@realname'/>
            </a>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select='@realname'/>
          </xsl:otherwise>
        </xsl:choose>
        <xsl:apply-templates select='arguments'/>
      </div>
      <div class="synopsis">
        <xsl:apply-templates select="abstract"/>
        <xsl:apply-templates select="description"/>
      </div>
    </div>
  </xsl:template>


  <!-- Function Arguments ================================================-->

  <xsl:template match='arguments'>
    <xsl:text>(</xsl:text>
    <xsl:apply-templates select='*' mode='argument'/>
    <xsl:text>)</xsl:text>
  </xsl:template>

  <xsl:template match='arg' mode='argument'>
    <xsl:if test='position() &gt; 1'>, </xsl:if>
    <span class="argument-name">
      <xsl:value-of select='@name'/>
    </span>
    <xsl:if test='@default'>
      <span class='argument-default'>
        <xsl:text>=</xsl:text>
        <xsl:value-of select='@default'/>
      </span>
    </xsl:if>
  </xsl:template>

  <xsl:template match='sequence' mode='argument'>
    <xsl:if test='position() &gt; 1'>, </xsl:if>
    <xsl:text>(</xsl:text>
    <xsl:apply-templates select='*' mode='argument'/>
    <xsl:if test='count(*) = 1'>
      <!-- add the trailing comma for tuples of length one -->
      <xsl:text>,</xsl:text>
    </xsl:if>
    <xsl:text>)</xsl:text>
  </xsl:template>

  <xsl:template match='var-args' mode='argument'>
    <xsl:if test='position() &gt; 1'>, </xsl:if>
    <span class="argument-name">
      <xsl:text>*</xsl:text>
      <xsl:value-of select='@name'/>
    </span>
  </xsl:template>

  <xsl:template match='var-keywords' mode='argument'>
    <xsl:if test='position() &gt; 1'>, </xsl:if>
    <span class="argument-name">
      <xsl:text>**</xsl:text>
      <xsl:value-of select='@name'/>
    </span>
  </xsl:template>

  <xsl:template match='unknown' mode='argument'>
    <span class="argument-name">
      <xsl:apply-templates/>
    </span>
  </xsl:template>
  
  <!-- Fields ============================================================-->

  <xsl:template match="fields">
    <xsl:variable name='public' select="*[@public = 'yes']"/>
    <xsl:if test="count($public)">
      <div class="section">
        <h2>Fields</h2>
        <xsl:apply-templates select='$public'/>
      </div>
    </xsl:if>
  </xsl:template>
  
  <xsl:template match="field">
    <div class="fielddesc">
      <div class="declaration">
        <a name="{@name}">
          <span class="field-name">
            <xsl:value-of select="@name"/>
          </span>
        </a>
        <xsl:text> = </xsl:text>
        <xsl:value-of select='value'/>
      </div>
      <div class="synopsis">
        <xsl:apply-templates select='abstract'/>
        <xsl:apply-templates select='description'/>
      </div>
    </div>
  </xsl:template>

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

  <xsl:template match="abstract[normalize-space()]">
    <div class="abstract">
      <xsl:apply-templates/>
    </div>
  </xsl:template>

  <xsl:template match="description[normalize-space()]">
    <div class="description">
      <br/>
      <xsl:call-template name="lf2br">
        <xsl:with-param name="text" select="string()"/>
      </xsl:call-template>
    </div>
  </xsl:template>

  <!--
      Description formatter:

      If only one paragraph, whitespace is normalized and uses description CSS class.

      If multiple paragraphs, first paragraph has whitespace normalized and
         uses description CSS class; remaining paragraphs use desc CSS class and
         have their linefeeds converted to <br>s and leading spaces on each
         line are converted to no-break spaces.

      The first paragraph is identified by 2 consecutive linefeed characters at
      its end.
  -->
  <xsl:template name="description">
    <xsl:param name="text" select="string()"/>

    <xsl:variable name="first-para" select="normalize-space(substring-before($text, '&#xA;&#xA;'))"/>

    <xsl:choose>
      <xsl:when test="not($first-para)">
        <div class="abstract">
          <xsl:call-template name="lf2br">
            <xsl:with-param name="text" select="$text"/>
          </xsl:call-template>
        </div>
      </xsl:when>
      <!-- multi-paragraph -->
      <xsl:otherwise>
        <xsl:variable name="remaining-text" select="substring-after($text, '&#xA;&#xA;')"/>
        <div class="abstract">
          <xsl:value-of select="$first-para"/>
        </div>
        <xsl:if test="normalize-space($remaining-text)">
          <div class="description">
            <br/>
            <xsl:call-template name="lf2br">
              <xsl:with-param name="text" select="$remaining-text"/>
            </xsl:call-template>
          </div>
        </xsl:if>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- convert LF to <br/> -->
  <xsl:template name="lf2br">
    <xsl:param name="text"/>
    <xsl:variable name="txt">
      <xsl:call-template name="ls2nbs">
        <xsl:with-param name="text" select="$text"/>
      </xsl:call-template>
    </xsl:variable>
    <xsl:variable name="txt-s" select="string($txt)"/>
    <xsl:choose>
      <xsl:when test="contains($txt-s,'&#xA;')">
        <xsl:value-of select="substring-before($txt-s,'&#xA;')"/>
        <br/>
        <xsl:call-template name="lf2br">
          <xsl:with-param name="text" select="substring-after($txt-s,'&#xA;')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$txt-s"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <!-- convert literal space to no-break space -->
  <xsl:template name="ls2nbs">
    <xsl:param name="text"/>
    <xsl:choose>
      <xsl:when test="starts-with($text,' ')">
        <xsl:text>&#160;</xsl:text>
        <xsl:call-template name="ls2nbs">
          <xsl:with-param name="text" select="substring-after($text,' ')"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


  <!-- Helper functions to allow overriding of link creation -->
  <xsl:template name='translate-href'>
    <xsl:param name='href'/>
    <xsl:if test="$href">
      <xsl:value-of select='concat($href,".html")'/>
    </xsl:if>
  </xsl:template>


  <!-- Funcion to split a Python dotted path into separate links -->
  <xsl:template name='link-python-path'>
    <xsl:param name='path'/>
    <xsl:param name='parent-path'/>

    <xsl:choose>
      <xsl:when test="contains($path, '.')">
        <xsl:variable name="module" select="substring-before($path, '.')"/>    
        <xsl:variable name="fullpath">
          <xsl:if test='$parent-path'>
            <xsl:value-of select="concat($parent-path, '.')"/>
          </xsl:if>
          <xsl:value-of select='$module'/>
        </xsl:variable>

        <a title="{$fullpath}">
          <xsl:attribute name="href">
            <xsl:call-template name='translate-href'>
              <xsl:with-param name='href' select='$fullpath'/>
            </xsl:call-template>
          </xsl:attribute>
          <xsl:value-of select="$module"/>
        </a>
        <xsl:text>.</xsl:text>

        <xsl:call-template name='link-python-path'>
          <xsl:with-param name="path" select="substring-after($path, '.')"/>
          <xsl:with-param name="parent-path" select="$fullpath"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <!-- no link needed as this is the module we're displaying -->
        <xsl:value-of select="$path"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

</xsl:stylesheet>
