9.12 Creating a Template File

9.12.1 Problem

You want to create a new template file (.xdt) that uses the JUnitPerfTagHandler class created in the previous recipe.

9.12.2 Solution

Create a template file called junitperf.xdt.

9.12.3 Discussion

XDoclet template files mix snippets of Java code and XML-style tags. These tags refer to XDoclet tag handler classes.

Instead of jumping directly into the completed example, it is best if we walk through each step of how the example template file is created. This example can be modified if your coding conventions differ or if you want to add extra functionality.

First, the template creates the package statement:

package <XDtPackage:packageName/>;

XDoclet prefixes all namespaces with "XDt", and is not part of the actual namespace specified in the xdoclet.xml file. In order to reference the "Perf" namespace, you would use "XDtPerf". This is simply a convention that XDoclet uses.

Next, we add the import statements.

import com.clarkware.junitperf.*;
import junit.framework.*;

These are the only import statements that we need. Here is how to include import statements from the class being parsed (if you need them):

<XDtClass:importedList currentClass="&lt;XDtClass:className/&gt;"/>

It's not a strict requirement to use entity references such as &lt; and &gt; when nesting greater-than and less-than symbols, but it does make the file easier to read, in our opinion. You are free to write this too: currentClass="<XDtClass:className/>"

For fun, any class comments are copied from the JUnit test.

/**
 <XDtClass:classCommentTags indent="0"/> */

Let's look at our first JUnitPerfTagHandler class, which is referenced by the namespace "XDtPerf". The next recipe shows how to define a namespace for a tag handler class. This snippet maps directly to the JUnitPerfTagHandler.className( ) method.

public class <XDtPerf:className/> {

We create the start of the suite( ) method and a new TestSuite for the JUnitPerf tests.

public static Test suite(  ) {
    TestSuite suite = new TestSuite(  );

It's time to create the JUnitPerf tests. We start by iterating all methods of the JUnit test being parsed. Recall that since the "destinationFile" attribute has a value that contains the substring "{0}", XDoclet generates output for multiple files. Specifically, this means that the template file is executed for each JUnit test class that is parsed. The attribute "superclasses" is set to "false", indicating that superclasses should not be evaluatedprobably what we want most of the time.

<XDtMethod:forAllMethods superclasses="false">

Now, the next snippet evaluates each method's Javadoc, looking for the tag junitperf.timedtest. If a method has this tag, the nested content is evaluated. Otherwise, it is skipped. The nested content simply creates a new JUnitPerf TimedTest and adds it to the TestSuite. The template tag XDtPerf:timedTest references the JUnitPerfTagHandler.timedTest( ) method to create a line of code that constructs a new JUnitPerf TimedTest.

<XDtMethod:ifHasMethodTag tagName="junitperf.timedtest">
    Test timedTest = <XDtPerf:timedTest/>
    suite.addTest(timedTest);
</XDtMethod:ifHasMethodTag>

This next snippet is identical to the previous snippet, except that now we are looking for the tag junitperf.loadtest.

<XDtMethod:ifHasMethodTag tagName="junitperf.loadtest">
    Test loadTest = <XDtPerf:loadTest/>
    suite.addTest(loadTest);
</XDtMethod:ifHasMethodTag>

Example 9-13 shows a complete template file that can be used to generate JUnitPerf code.

Example 9-13. JUnitPerfDoclet template file
package <XDtPackage:packageName/>;

import com.clarkware.junitperf.*;
import junit.framework.*;

/**
 <XDtClass:classCommentTags indent="0"/> */
public class <XDtPerf:className/> {

    public static Test suite(  ) {
        TestSuite suite = new TestSuite(  );

        <XDtMethod:forAllMethods superclasses="false">
            <XDtMethod:ifHasMethodTag tagName="junitperf.timedtest">
        Test timedTest = <XDtPerf:timedTest/>
        suite.addTest(timedTest);
            </XDtMethod:ifHasMethodTag>
            <XDtMethod:ifHasMethodTag tagName="junitperf.loadtest">
        Test loadTest = <XDtPerf:loadTest/>
        suite.addTest(loadTest);
            </XDtMethod:ifHasMethodTag>
        </XDtMethod:forAllMethods>

        return suite;
        }
}

9.12.4 See Also

Recipe 9.10 shows how to create a custom Ant Doclet subtask to generate JUnitPerf tests. Recipe 9.11 shows how to create the JUnitPerfDoclet tag handler class to perform simple logic and generate snippets of code. Recipe 9.13 shows how to create an XDoclet xdoclet.xml file used to define information about your code generator. Recipe 9.14 shows how to package JUnitPerfDoclet into a JAR module. Chapter 8 provides information on the JUnitPerf tool and how to update your Ant buildfile to invoke JUnitPerfDoclet.