<?xml version="1.0"?>

<!--
 * ========================================================================
 * 
 * Copyright 2004 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.
 * 
 * ========================================================================
-->

<jsl:stylesheet
  select="$doc"
  xmlns:j="jelly:core"
  xmlns:jsl="jelly:jsl"
  xmlns:x="jelly:xml"
  xmlns:define="jelly:define"
  xmlns:util="jelly:util"
  xmlns:doc="doc"
  xmlns:jdepend="jdepend"
  trim="true">

  <!-- This needs to be instantiated here to be available in the template matches -->
  <j:useBean var="mavenTool" class="org.apache.maven.util.MavenTool"/>
  <j:useBean var="htmlescape" class="org.apache.velocity.anakia.Escape"/>
  <j:useBean var="fileutil" class="org.apache.velocity.texen.util.FileUtil"/>
  <j:useBean var="pathtool" class="org.apache.maven.util.DVSLPathTool"/>
  <j:useBean var="stringTool" class="org.apache.maven.util.StringTool"/>

  <define:taglib uri="jdepend">
    <define:tag name="nav">
      <p>
        [<a href="#Summary">summary</a>]
        [<a href="#Packages">packages</a>]
        [<a href="#Cycles">cycles</a>]
        [<a href="#Explanations">explanations</a>]
      </p>
    </define:tag>
    <!--
     | Used to print the abstract and concrete classes that a package
     | contains.  Also removes the leading package information from
     | the fully qualified class (to conserve screen space).  Also,
     | creates a link to the xref sources so users can quickly navigate
     | the code.
    -->
    <define:tag name="classes">
      <j:choose>
        <j:when test="${currentNode.selectNodes(xpath).isEmpty()}">
          <em>None</em>
        </j:when>
        <j:otherwise>
          <ul>
            <j:forEach var="class" items="${currentNode.selectNodes(xpath)}">
              <!-- class.StringValue =~ org.apache.maven.SomeClass -->
              <j:set var="packageName">${stringTool.splitStringAtLastDelim(class.StringValue.trim(), '.').get(0)}</j:set>
              <j:set var="className">${stringTool.splitStringAtLastDelim(class.StringValue.trim(), '.').get(1)}</j:set>
              <util:replace var="dir" oldChar="." newChar="/" value="${packageName}"/>
              
              <j:choose>
                <j:when test="${class.attribute('sourceFile') != null}">
                  <j:set var="classSourceFile" value="${class.attribute('sourceFile').getValue()}"/>
                  <j:set var="classSourceFile" value="${stringTool.splitStringAtLastDelim(classSourceFile, '.').get(0)}"/>
                  <li><a href="xref/${dir}/${classSourceFile}.html">${className}</a></li>
                </j:when>
                <j:otherwise>
                  <li><a href="xref/${dir}/${className}.html">${className}</a></li>
                </j:otherwise>
              </j:choose>
            </j:forEach>
          </ul>
        </j:otherwise>
      </j:choose>
    </define:tag>
    <!--
     | Used to print the "used" and "used by" packages.  Also, creates a
     | link to the appropriate package in the report.
    -->
    <define:tag name="packages">
      <j:choose>
        <j:when test="${currentNode.selectNodes(xpath).isEmpty()}">
          <em>None</em>
        </j:when>
        <j:otherwise>
          <ul>
            <j:forEach var="class" items="${currentNode.selectNodes(xpath)}">
              <li><a href="#${class.getStringValue()}">${class.getStringValue()}</a></li>
            </j:forEach>
          </ul>
        </j:otherwise>
      </j:choose>
    </define:tag>
  </define:taglib>

  <jsl:template match="JDepend">
    <document>

      <properties>
        <title>JDepend Source Code Analysis</title>
      </properties>
      
      <head>
        <x:element name="style"><x:attribute name="type">text/css</x:attribute>
          <![CDATA[
              .jdepend td ul, .jdepend td ul li {
                 margin:0; padding:0;
                 list-style-type: none;
              }
          ]]>
        </x:element>
       
      </head>

      <body class="jdepend">
        <section name="Metric Results">
          <jdepend:nav/>
          <p>
            The following document contains the results of a
            <a href="http://www.clarkware.com/software/JDepend.html">JDepend</a> metric analysis.
            The various metrics are defined at the bottom
            of this document.
          </p>
        </section>

        <section name="Summary">
          <jdepend:nav/>
          <table summary="Summary">
            <thead>
              <tr>
                <th title="Package">Package</th>
                <th style="text-align:right"><acronym title="Total Classes">TC</acronym></th>
                <th style="text-align:right"><acronym title="Abstract Classes">AC</acronym></th>
                <th style="text-align:right"><acronym title="Concrete Classes">CC</acronym></th>
                <th style="text-align:right"><acronym title="Afferent Couplings">AC</acronym></th>
                <th style="text-align:right"><acronym title="Efferent Couplings">EC</acronym></th>
                <th style="text-align:right"><acronym title="Abstractness">A</acronym></th>
                <th style="text-align:right"><acronym title="Instability">I</acronym></th>
                <th style="text-align:right"><acronym title="Distance">D</acronym></th>
              </tr>
            </thead>

            <x:set var="packages" select="Packages/Package"/>
            <tbody>
              <j:forEach var="package" items="${packages}">
                <!-- Is this the only way I can tell if an element has a value properly? -->
                <j:set var="error" value="${package.valueOf('error').trim()}"/>
                <j:if test="${error == ''}">
                  <tr>
                    <td>
                      <a href="#${package.attribute('name').getValue()}">${package.attribute('name').getValue()}</a>
                    </td>
                    <td style="text-align:right">
                      <x:expr select="$package/Stats/TotalClasses"/>
                    </td>
                    <td style="text-align:right"><x:expr select="$package/Stats/AbstractClasses"/></td>
                    <td style="text-align:right"><x:expr select="$package/Stats/ConcreteClasses"/></td>
                    <td style="text-align:right"><x:expr select="$package/Stats/Ca"/></td>
                    <td style="text-align:right"><x:expr select="$package/Stats/Ce"/></td>
                    <td style="text-align:right">
                      <j:set var="display"><x:expr select="$package/Stats/A"/></j:set>
                      <doc:formatAsNumber string="${display}" pattern="#.##"/>
                    </td>
                    <td style="text-align:right">
                      <j:set var="display"><x:expr select="$package/Stats/I"/></j:set>
                      <doc:formatAsNumber string="${display}" pattern="#%"/>
                    </td>
                    <td style="text-align:right">
                      <j:set var="display"><x:expr select="$package/Stats/D"/></j:set>
                      <doc:formatAsNumber string="${display}" pattern="#%"/>
                    </td>
                  </tr>
                </j:if>
              </j:forEach>
            </tbody>

          </table>
        </section>

        <section name="Packages">
          <jdepend:nav/>

          <j:forEach var="package" items="${packages}">
            <!-- Is this the only way I can tell if an element has a value properly? -->
            <j:set var="error" value="${package.valueOf('error').trim()}"/>
            <j:if test="${error == ''}">
              <subsection name="${package.attribute('name').getValue()}">
                <table summary="Packages">
                  <thead>
                    <tr>
                      <th>Afferent Couplings</th>
                      <th>Efferent Couplings</th>
                      <th>Abstractness</th>
                      <th>Instability</th>
                      <th>Distance</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>${package.valueOf("Stats/Ca")}</td>
                      <td>${package.valueOf("Stats/Ce")}</td>
                      <td>
                        <doc:formatAsNumber string="${package.valueOf('Stats/A')}" pattern="#%"/>
                      </td>
                      <td>
                        <doc:formatAsNumber string="${package.valueOf('Stats/I')}" pattern="#%"/>
                      </td>
                      <td>
                        <doc:formatAsNumber string="${package.valueOf('Stats/D')}" pattern="#%"/>
                      </td>
                    </tr>
                  </tbody>
                </table>

                <table summary="Packages">
                  <thead>
                    <tr>
                      <th>Abstract Classes</th>
                      <th>Concrete Classes</th>
                      <th>Used by Packages</th>
                      <th>Uses Packages</th>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>
                        <jdepend:classes currentNode="${package}" xpath="AbstractClasses/Class"/>
                      </td>
                      <td>
                        <jdepend:classes currentNode="${package}" xpath="ConcreteClasses/Class"/>
                      </td>
                      <td>
                        <jdepend:packages currentNode="${package}" xpath="UsedBy/Package"/>
                      </td>
                      <td>
                        <jdepend:packages currentNode="${package}" xpath="DependsUpon/Package"/>
                      </td>
                    </tr>
                  </tbody>
                </table>
              </subsection>
            </j:if>
          </j:forEach>
        </section>

        <section name="Cycles">
          <jdepend:nav/>
          <x:set var="packages" select="Cycles/Package"/>
          <j:choose>
            <j:when test="${size(packages) == 0}">
              <p>There are no cyclic dependencies.</p>
            </j:when>
            <j:otherwise>
              <table sumary="Cyclic dependencies">
                <thead>
                  <tr>
                    <th>Package</th>
                    <th>Cyclic Dependencies</th>
                  </tr>
                </thead>
                
                <tbody>
                  <j:forEach var="package" items="${packages}">
                    <tr>
                      <td>${package.attribute('Name').getValue()}</td>
                      <td>
                        <x:set var="cycles" select="$package/Package"/>
                        <j:if test="${!cycles.isEmpty()}">
                          <ul>
                            <j:forEach var="cycle" items="${cycles}">
                              <li>${cycle.getText()}</li>
                            </j:forEach>
                          </ul>
                        </j:if>
                      </td>
                    </tr>
                  </j:forEach>
                </tbody>
              </table>
            </j:otherwise>
          </j:choose>
        </section>

        <section name="Explanations">
          <jdepend:nav/>

          <p>
            The following explanations are for quick reference and are
            lifted directly from the original
            <a
              href="http://www.clarkware.com/software/JDepend.html">JDepend
              documentation</a>.
          </p>

          <table summary="Explanations">
            <thead>
              <tr>
                <th>Term</th>
                <th>Description</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td>Number of Classes</td>
                <td>
                  The number of concrete and abstract classes (and interfaces)
                  in the package is an indicator of the extensibility of the
                  package.
                </td>
              </tr>
              <tr>
                <td>Afferent Couplings</td>
                <td>
                  The number of other packages that depend upon classes within
                  the package is an indicator of the package's responsibility.
                </td>
              </tr>
              <tr>
                <td>Efferent Couplings</td>
                <td>
                  The number of other packages that the classes in the package
                  depend upon is an indicator of the package's independence.
                </td>
              </tr>
              <tr>
                <td>Abstractness</td>
                <td>
                  The ratio of the number of abstract classes (and interfaces)
                  in the analyzed package to the total number of classes in
                  the analyzed package.  The range for this metric is 0 to 1,
                  with A=0 indicating a completely concrete package and A=1
                  indicating a completely abstract package.
                </td>
              </tr>
              <tr>
                <td>Instability</td>
                <td>
                  The ratio of efferent coupling (Ce) to total coupling (Ce /
                  (Ce + Ca)). This metric is an indicator of the package's
                  resilience to change.  The range for this metric is 0 to 1,
                  with I=0 indicating a completely stable package and I=1
                  indicating a completely instable package.
                </td>
              </tr>
              <tr>
                <td>Distance</td>
                <td>
                  The perpendicular distance of a package from the idealized
                  line A + I = 1. This metric is an indicator of the package's
                  balance between abstractness and stability.  A package
                  squarely on the main sequence is optimally balanced with
                  respect to its abstractness and stability. Ideal packages
                  are either completely abstract and stable (x=0, y=1) or
                  completely concrete and instable (x=1, y=0).  The range for
                  this metric is 0 to 1, with D=0 indicating a package that is
                  coincident with the main sequence and D=1 indicating a
                  package that is as far from the main sequence as possible.
                </td>
              </tr>
              <tr>
                <td>Cycles</td>
                <td>
                  Packages participating in a package dependency cycle are in
                  a deadly embrace with respect to reusability and their
                  release cycle. Package dependency cycles can be easily
                  identified by reviewing the textual reports of dependency
                  cycles. Once these dependency cycles have been identified
                  with JDepend, they can be broken by employing various
                  object-oriented techniques.
                </td>
              </tr>
            </tbody>
          </table>
        </section>

      </body>
    </document>

  </jsl:template>
</jsl:stylesheet>
