<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:lxslt="http://xml.apache.org/xslt"
    xmlns:redirect="http://xml.apache.org/xalan/redirect"
    xmlns:stringutils="xalan://org.apache.tools.ant.util.StringUtils"
    xmlns:regexp="com.linkwerk.util.Regexp"
    extension-element-prefixes="redirect regexp">
    <xsl:output method="html" indent="yes" encoding="US-ASCII"/>
    <xsl:decimal-format decimal-separator="." grouping-separator=","/>
    <!--
    Copyright 2006 Kerry Buckley, http://www.kerrybuckley.com/
    
    Based on JunitReport stylesheet
    
    Copyright 2001-2005 The Apache Software Foundation
    
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at
    
    http://www.apache.org/licenses/LICENSE-2.0
    
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
    -->
    
    <!--
    
    Spec-generating stylesheet to be used with Ant JUnitReport output.
    
    Requires lw-regexp-util-1.0.0.jar (from http://www.linkwerk.com/pub/xslt/lib/) in the classpath.
    
    -->
    <xsl:param name="output.dir" select="'.'"/>
    
    <xsl:template match="testsuites">
        <!-- create index.html -->
        <redirect:write file="{$output.dir}/index.html">
            <xsl:call-template name="index.html"/>
        </redirect:write>
        
        <!-- create stylesheet.css -->
        <redirect:write file="{$output.dir}/stylesheet.css">
            <xsl:call-template name="stylesheet.css"/>
        </redirect:write>
        
        <!-- create intro.html -->
        <redirect:write file="{$output.dir}/intro.html">
            <xsl:call-template name="intro.html"/>
        </redirect:write>
        
        <!-- create packages.html -->
        <redirect:write file="{$output.dir}/packages.html">
            <xsl:apply-templates select="." mode="packages"/>
        </redirect:write>
        
        <!-- process all packages -->
        <xsl:for-each
            select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
            <xsl:variable name="name">
                <xsl:call-template name="package-name">
                    <xsl:with-param name="name" select="@package"/>
                </xsl:call-template>
            </xsl:variable>
            <redirect:write file="{$output.dir}/{$name}.html">
                <xsl:call-template name="package">
                    <xsl:with-param name="name" select="@package"/>
                </xsl:call-template>
            </redirect:write>
        </xsl:for-each>
    </xsl:template>
    
    <xsl:template name="index.html">
        <html>
            <head>
                <title>Behaviour specifications</title>
            </head>
            <frameset cols="20%,80%">
                <frame src="packages.html" name="packageListFrame"/>
                <frame src="intro.html" name="packageFrame"/>
                <noframes>
                    <h2>Frame Alert</h2>
                    <p> This document is designed to be viewed using the frames feature. If
                        you see this message, you are using a non-frame-capable web
                        client. </p>
                </noframes>
            </frameset>
        </html>
    </xsl:template>
    
    <xsl:template name="stylesheet.css">
        <![CDATA[body {
    font:normal 68% verdana,arial,helvetica;
    color:#000000;
}
table tr td, table tr th {
    font-size: 68%;
}

p {
    line-height:1.5em;
    margin-top:0.5em; margin-bottom:1.0em;
}
h1 {
    margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
}
h2 {
    margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
}]]>
    </xsl:template>
    
    <xsl:template name="intro.html">
        <html>
            <head>
                <link rel="stylesheet" type="text/css" title="Style"
                    href="stylesheet.css"/>
                <title>Behaviour specifications</title>
            </head>
            <body>
                <h1>Behaviour specifications</h1>
                <xsl:call-template name="pageHeader"/>
                <p>Select a package on the left to view the specifications for classes in
                    that package.</p>
            </body>
        </html>
    </xsl:template>
    
    <xsl:template match="testsuites" mode="packages">
        <html>
            <head>
                <link rel="stylesheet" type="text/css" title="Style"
                    href="stylesheet.css"/>
                <title>Packages</title>
            </head>
            <body>
                <h2>Packages</h2>
                <table width="100%">
                    <xsl:apply-templates
                        select="testsuite[not(./@package = preceding-sibling::testsuite/@package)]"
                        mode="all.packages">
                        <xsl:sort select="@package"/>
                    </xsl:apply-templates>
                </table>
            </body>
        </html>
    </xsl:template>
    
    <xsl:template match="testsuite" mode="all.packages">
        <tr>
            <td nowrap="nowrap">
                <xsl:element name="a">
                    <xsl:attribute name="href">
                        <xsl:call-template name="package-name">
                            <xsl:with-param name="name" select="@package"/>
                        </xsl:call-template>
                        <xsl:text>.html</xsl:text>
                    </xsl:attribute>
                    <xsl:attribute name="target">packageFrame</xsl:attribute>
                    <xsl:call-template name="package-name">
                        <xsl:with-param name="name" select="@package"/>
                    </xsl:call-template>
                </xsl:element>
            </td>
        </tr>
    </xsl:template>
    
    <xsl:template name="package">
        <xsl:param name="name"/>
        <xsl:variable name="local-name">
            <xsl:call-template name="package-name">
                <xsl:with-param name="name" select="$name"/>
            </xsl:call-template>
        </xsl:variable>
        <html>
            <head>
                <link rel="stylesheet" type="text/css" title="Style"
                    href="stylesheet.css"/>
                <title>Behaviour specifications:
                    <xsl:value-of select="$local-name"/></title>
            </head>
            <body>
                <h1>Behaviour specifications: <code>
                    <xsl:value-of select="$local-name"/></code></h1>
                <xsl:call-template name="pageHeader"/>
                <xsl:apply-templates
                    select="/testsuites/testsuite[@package = $name]"/>
            </body>
        </html>
    </xsl:template>
    
    <xsl:template match="testsuite">
        <h2>
            <xsl:call-template name="prettify-suite">
                <xsl:with-param name="name" select="@name"/>
            </xsl:call-template>
        </h2>
        <ul>
            <xsl:apply-templates select="./testcase"/>
        </ul>
    </xsl:template>
    
    <xsl:template match="testcase">
        <li>
            <xsl:call-template name="prettify-test">
                <xsl:with-param name="name" select="@name"/>
            </xsl:call-template>
        </li>
    </xsl:template>
    
    <!-- Page header -->
    <xsl:template name="pageHeader">
        <p>Derived from reports generated by
            <a href="http://www.junit.org/">JUnit</a> and
            <a href="http://jakarta.apache.org/">Ant</a>.</p>
        <hr size="1"/>
    </xsl:template>
    
    <!-- replace the package name with "default-package" if it is empty -->
    <xsl:template name="package-name">
        <xsl:param name="name"/>
        <xsl:value-of select="$name"/>
        <xsl:if test="$name = ''">default-package</xsl:if>
    </xsl:template>
    
    <!-- turn a test suite name into a human-readable phrase -->
    <xsl:template name="prettify-suite">
        <xsl:param name="name"/>
        
        <!-- remove leading "Test" or trailing "Test[s]" from classname (adjust for your naming convention) -->
        <xsl:variable name="suite">
            <xsl:value-of
                select="regexp:replace(regexp:replace(string($name), '^Test', '', ''), 'Tests?$', '', '')"/>
        </xsl:variable>
        <!-- split into separate words -->
        <xsl:variable name="context">
            <xsl:call-template name="separate-words">
                <xsl:with-param name="str" select="$suite"/>
            </xsl:call-template>
        </xsl:variable>
        <!-- Convert all but first character to lower case -->
        <xsl:value-of select="substring($context, 1, 1)"/>
        <xsl:call-template name="lower-case">
            <xsl:with-param name="str" select="substring($context, 2)"/>
        </xsl:call-template>
    </xsl:template>
    
    <!-- turn a test name into a human-readable phrase -->
    <xsl:template name="prettify-test">
        <xsl:param name="name"/>
        <!-- remove leading "test" -->
        <xsl:variable name="test">
            <xsl:value-of
                select="regexp:replace(string($name), '^test', '', '')"/>
        </xsl:variable>
        <!-- split into separate words -->
        <xsl:variable name="spec">
            <xsl:call-template name="separate-words">
                <xsl:with-param name="str" select="$test"/>
            </xsl:call-template>
        </xsl:variable>
        <!-- Convert to lower case -->
        <xsl:call-template name="lower-case">
            <xsl:with-param name="str" select="$spec"/>
        </xsl:call-template>
    </xsl:template>
    
    
    <!-- convert a camelCase string to separate words (treat multiple consecutive digits as a word) -->
    <xsl:template name="separate-words">
        <xsl:param name="str"/>
        <xsl:value-of
            select="normalize-space(regexp:replace(regexp:replace(string($str), '([A-Z])', 'g', ' $1'), '([^0-9])([0-9])', 'g', '$1 $2'))"/>
    </xsl:template>
    
    <!-- convert a string to lower case -->
    <xsl:template name="lower-case">
        <xsl:param name="str"/>
        <xsl:value-of
            select="translate($str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
    </xsl:template>
    
</xsl:stylesheet>
