type safe templating

Template Reference Manual

    1. Static content
    2. Emit statements
    3. Flow control
    4. Arbitrary Java code
    5. Inheritance
    6. Class code
    7. Comments
    8. Imports
    9. Implements
    10. Annotations
    11. Arguments
    12. Invoking other templates
    13. Subtemplates
    14. Fragment arguments
    15. Parametrized fragment arguments
    16. Context
    17. jamon.properties
    18. Generics
    19. Path aliases
    20. Character encoding
  1. Static content In general, any characters appearing in a template are output literally, whitespace included. This excludes whitespace inside <%args>, <%xargs>, <%import>, <%alias>, <%absmeth>, <%generic> and <%frag> declarations. Other ignored white space includes whitespace immediately after the following tags:
    • <%def ...> and </%def>
    • <%method ...> and </%method>
    • <%override ...> and </%override>
    • </%absmeth>
    • </%alias>
    • </%args>
    • </%class>
    • </%doc>
    • </%frag>
    • </%generic>
    • </%implements>
    • </%import>
    • </%java>
    • </%xargs>
    • <%abstract>
    • <%annotate ...%>
    • <%encoding ...>
    • <%escape ...%>
    If you would like to force whitespace to appear after one of the above tags, you can follow the tag with a backslash and a newline; whitespace after that will be emitted.
    Newline escape
    One other notable exception is that if a newline is preceded by a backslash, then neither the newline nor the backslash are output.
  2. Emit statements The value of a java expression can be emitted by enclosing the expression in <% ...%> pairs, e.g.
    <% person.getFirstName().substring(0,10) %>
    
    Note that there must be at least one whitespace character following the <%.

    Before a Java expression is emitted, the string that represents it is escaped. The default escaping mechanism is HTML, so for example the following template

    this <% "&" %> that
    
    produces
    this &amp; that
    However different escaping mechanisms can be specified in the template itself. A string can be emitted with no escaping as follows:
    this <% "&" #n %> that
    
    producing
    this & that
    JavaScript escaping is also available
    <a 
    href="about:blank"
    onclick="<&| /org/jamon/escape/StrictHtml 
      &>return confirm("<% '"' +
                           "<b>this\n'n\nthat</b>" +
                           '"' #j %>")</&>">this</a>
    
    producing
    <a 
    href="about:blank"
    onclick="return confirm(&quot;\&quot;&lt;b&gt;this\n\&#39;n\nthat&lt;/b&gt;\&quot;&quot;)">this</a>
    The available escaping mechanism are
    • HTML (use #h in the emit block) -- produces output suitable for inclusion in the body of HTML elements
    • Strict HTML (use #H in the emit block) -- produces output suitable for use as an HTML attribute value (it is similar to HTML escaping but also escapes quotes and apostrophes)
    • JavaScript (use #j in the emit block) -- produces output suitable for use in a JavaScript string literal
    • XML (use #x in the emit block)
    • URL (use #u in the emit block)
    • None (use #n in the emit block)

    In addition the default escaping mechanism can also be changed. This can be done at the template level by use of the <%escape ...%> tag. For example,

    <%escape #n>
    <% "< & >" %>
    
    will produce
    < & >
    
    Finally, by using jamon.properties , escaping can be set for all templates in a directory and its subdirectories. For example, if jamon.properties includes the line:
    org.jamon.escape=u
    
    Then templates will default to URL escaping, unless they specify their own default escaping with a <%escape ...%> tag.

    Mode

    It is possible to restrict the allowable types that can appear in emit directives by assigning a value to the org.jamon.emitMode in the jamon.properties file. The following values are allowed:
    • standard - all types allowed
    • limited - Strings, primitives, and boxed primitives
    • strict - Strings only
    An attempt to emit a disallowed type will result in a Java compilation error when the template is compiled.
  3. Flow control

    Jamon uses the following tags to handle flow control:

    • Basic for statement:
      <%for int i = 10; i >= 0; i-- %><% %i %>... </%for>
      Ready or not, here I come!
      
    • Enhanced for statement:
      <%for Employee employee : employees %><% employee.getName() %> earns <% employee.getSalary() %>
      </%for>
      
    • While loops
      <%while throwable != null %>
      Exception: throwable.getMessage()
      <%java throwable = throwable.getCause(); %>
      </%while>
      
    • If, ifelse and else statements
      There will be
      <%if attending < 5 %>a few<%elseif attending < 10%>some<%else>lots of</%if>
      people attending.
      </%while>
      
      Note that there can be zero or more <%elseif ...%> tags, and zero or one <%else> tags. The </%if> tag is mandetory.
  4. Arbitrary Java code

    Arbitrary Java code can be inserted into the template using <%java>...</%java>, e.g.

    <%java>
      SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM d, yyyy");
      Date birthday = person.getBirthDay();
    </%java>
    <% p.name() %> was born on <% dateFormat.format(birthday) %>.
    
    Alternatively, java code can be inserted "inline" using <%java ... %>. The previous example could be equivalently written as
    <%java SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM d, yyyy");
           Date birthday = person.getBirthDay(); %>
    <% p.name() %> was born on <% dateFormat.format(birthday) %>.
    

    The kinds of Java code that can appear is fairly unrestricted. Be warned, however, that code will appear inside a method body. Thus, for example, package declarations and import statements would trigger a compilation error.

  5. Inheritance Templates can inherit from other templates. A template is an "abstract" template if it contains a <%abstract> tag. A template extends another template by means of an <%extends pathToParent> tag. There can be multiple levels of inheritance: /grandchild can extend /child, which in turn can extend /parent. When Jamon encounters a <& *CHILD &> tag, it inserts the results of rendering the child template.

    For example, suppose /restaurant/Menu contains:

    <%abstract>
    <html>
     <body>
       <h1>Menu</h1>
       <& *CHILD &>
     </body>
    </html>
    
    and /restaurant/Lunch contains:
    <%extends /restaurant/Menu>
    Sandwich Jamon y Queso
    
    Then rendering /restaurant/Lunch produces
    <html>
     <body>
       <h1>Menu</h1>
       Sandwich Jamon y Queso
    
     </body>
    </html>
  6. Class code Any code to be included in the generated class should be placed inside a <%class>...</%class> block. If one template inherits from another, there is corresponding inheritance of java classes. As a result, protected members declared in a parent template's <%class>...</%class> block will be visible to the child.

    For example:

    <%class>
      static int pageViews = 1;
    </%class>
    This component has been accessed <% pageViews++ %> times.
    
  7. Comments Any template content between <%doc> and </%doc> is considered "documentation", and ignored by the template processor
  8. Imports Java classes or packages to be imported and used in a template should be placed inside an <%import>...</%import> block. Each package or class should be separated by a semicolon (';'). Static imports are accomplished by preceding the imported element with the static keyword. Note that imports are not inherited, so if you use an import to aid in the declaration of an argument type in a parent template, you must use the same import in all descendants of that template.

    For example:

    <%import>
      java.util.Iterator;
      org.myorg.myapp.data.*;
      static org.myorg.myapp.Constants.*;
    </%import>
  9. Implements Templates can be declared to implement interfaces through use of the <%implements ... %> tag. It is not possible to add arbitrary public methods to generated templates, so the use of this is practically limited to capturing methods such as setFoo() and makeRenderer().

    For example, given

    interface RenderableWithInt {
      Renderer makeRenderer(int i);
    }
    it's possible to declare MyTemplate.jamon with
    <%implements>
      RenderableWithInt;
    </%implements>
    <%args>
      int i;
    </%args>
    
    and then use it like
    RenderableWithInt t = new MyTemplate();
    i.makeRenderer(3);
  10. Annotations It is possible to add class level annotations to the generated java files by use of an <%annotate ... %> tag. By default, annotations are placed on both the generated proxy and impl classes. An annotation can be restricted to one or the other with an optional #impl or #proxy suffix.

    For example:

    <%annotate @Deprecated %>
    <%doc>Silence complaints about imports in the proxy class</%doc>
    <%annotate @SuppressWarnings("unused") #proxy %>
    <%annotate @Comment("Only on the impl class") #impl %>
    
  11. Arguments Arguments to a template are specified in <%args>...</%args> blocks. Each argument consists of a type followed by the argument name, optionally followed by = and a default value. Each argument must appear on a separate line, and each argument declaration must be terminated by a semicolon. Note that the old style for optional arguments, where the default value follows a => instead of a =, is deprecated.

    Arguments are usable inside any java escape or java expression in the template, including those in subtemplates. Top-level visible arguments are also usable inside <%class>...</%class> blocks. Technically, arguments are declared "final", so it is not possible to (re)assign a value to an argument.

    For example:

    <%args>
      String[] nicknames = new String[0];
      Address address;
      java.util.Iterable<Person> friends;
    </%args>
    Your nicknames are
    <ul>
    <%for int i = 0; i < nicknames.length; ++i %>
        <li> <% nicknames[i] %>
    </%for>
    </ul>
    <%for Person p: friends %>
        <%if p.getAddress().getPostalCode().equals(address.getPostalCode()) %>
          Hey, guess what? <% p.getName() %> lives close by!
        </%if>
    </%while>
    
    Note that for this template to compile, the Address class would need to appear in an <%import>...</%import> block.

    Arguments with default values are optional, and need not be specified when invoking a template. At the top-level (i.e. the interface to "standard" java code), optional arguments are implemented as "setters" on the template object rather than as arguments to the render method.

    If a template inherits from another template, the arguments to the template's ancestors are not automatically visible to the child template. They can be made visible to code in the child template by declaring them in <%xargs>...</%xargs> blocks. Unlike <%args>...</%args> blocks, <%xargs>...</%xargs> blocks do not specify argument types, since those have already been specified by a parent template. Optional arguments, however, may have their default values redefined by the child. For example, if /parent contains:

    <%abstract>
    <%args>
      String name;
      String favoriteColor = "red";
      String favoriteFood = "Jamon";
      int luckyNumber = 7;
    </%args>
    <font color="<% favoriteColor %>">Hello <% name %></font>.
    Would you like some <% favoriteFood %>?
    <& *CHILD &>
    Remember, today's lucky number is <% luckyNumber %>.
    
    then /child might contain:
    <%extends /parent>
    <%args>
      int temperature;
    </%args>
    <%xargs>
      name;
      favoriteColor = "green"
      luckyNumber;
    </%xargs>
    Today's temperature is
    <font color="<% favoriteColor %>"><% temperature %></font>, which is
    <%if temperature != luckyNumber %> not </%if> a good sign for you, <% name %>.
    
    Note that it would be an error if /child tried referring to favoriteFood's argument to /parent without referencing it in an <%xargs>...<%/xargs> block.
  12. Invoking other templates It is possible to invoke other templates from within a template. To invoke a template which takes no argument, simply write <& template-name &>.

    There are two ways to pass arguments to templates: named parameters, and positional parameters. Templates can be invoked with named parameters via the <& template-name; argument1 = value1; ... &> construct. All arguments without default values (i.e. required arguments) must be specified, but arguments given default values are optional. The old-style syntax of having the value follow a => instead of a = is deprecated. If values are only being passed for required arguments, positional parameter syntax may be used instead. The syntax for positional parameters is simply <& template-name: value1; ... &> With positional parameter syntax, arguments are passed in the order that they are declared in the <%args> section of the template. Note that while with named parameter syntax, the template name is followed by a semicolon, positional parameter syntax follows the template name with a colon. In each case, semicolons are used to separate parameters.

    For example, suppose /accounting/bill contains

    <%args>
      int amount;
      String payee;
      boolean overdue = false;
    </%args>
    You owe <% payee %> $<% amount %>.  <%if overdue%>Pay now, or else!</%if>
    
    This tempate can be called in the following ways:
    <& /accounting/bill; amount = 30; payee = "the phone company" &>
    <& /accounting/bill; payee = "the gas company"; amount = 35 &>
    <& /accounting/bill: 25; "the mechanic" &>
    <& /accounting/bill; amount = 400; payee = "Dad"; overdue = true &>
    
    resulting in something like
    You owe the phone company $30.  
    You owe the gas company $35.  
    You owe the mechanic $25.  
    You owe Dad $400.  Pay now, or else!
    
    When using positional parameter syntax to invoke templates which extend abstract templates, first pass the required arguments of the parent, and then those of the child.
  13. Subtemplates In addition to calling other templates, a template can call "subtemplates" defined within a template. Subtemplates come in two forms, "private" and "protected". Subtemplates may be declared to accept arguments similar to templates by using %args. Subtemplates can invoke other subtemplates in the same template, and can be directly or indirectly recursive. Arguments to subtemplates can be given default values.

    Private subtemplates ("defs") can be declared via the <%def def-name> instruction, and are only visible within the template in which they are declared.

    For example:

    <%def _row>
      <%args>
        String name;
        int age;
      </%args>
      <tr>
        <td align="left"><% name %></td>
        <td>&nbsp;</td>
        <td align="center"<%if age < 18 %> bgcolor="red"</%if>>
          <% age %>
        </td>
      </tr>
    </%def>
    
    <table>
    <%doc>named parameter syntax</%doc>
      <& _row; name = "Mickey"; age = 46 &>
      <& _row; name = "Junior"; age = 8 &>
    <%doc>positional parameter syntax</%doc>
      <& _row: "Minnie"; 25 &>
    </table>
    
    produces
    <table>
    <tr>
        <td align="left">Mickey</td>
        <td>&nbsp;</td>
        <td align="center">
          46
        </td>
      </tr>
    
      <tr>
        <td align="left">Junior</td>
        <td>&nbsp;</td>
        <td align="center" bgcolor="red">
          8
        </td>
      </tr>
    
    <tr>
        <td align="left">Minnie</td>
        <td>&nbsp;</td>
        <td align="center">
          25
        </td>
      </tr>
    
    </table>
    

    Protected templates ("methods") can be declared via the <%method method-name> instruction. A method is similar to a def, but is visible to all descendants of the declaring template. Moreover, a method declared in an ancestor template can be overriddden via the <%override method-name> instruction. Overridden methods take the same arguments as the method they override, although, as with template inheritance, only those args declared in an <%xargs>....</%xargs> block will be visible within the body of the override. Finally, an ancestor template may declare an "abstract" protected subtemplate by using <%absmeth method-name>...</%absmeth> . The only things allowed inside an <%absmeth ...>...<%/absmeth> block are <%args>...</%args> blocks and <%frag ...>...</%frag> blocks. It is an error for a non-abstract template to extend (directly or indirectly) a template with an abstract method, and not have that method overridden by the non-abstract template, or one of it's intermediate ancestors. For example, suppose /weather/Report contains:

    <%abstract>
    <%method backgroundColor>white</%method>
    <%absmeth title>
      <%args>
        String city;
        String dayOfWeek;
      </%args>
    </%absmeth>
    <%args>
      WeatherReport report;
    </%args>
    <html>
      <head>
        <title>
          <& title; city = report.getCity(); dayOfWeek = report.getDay(); &>
        </title>
      </head>
      <body bgcolor="<& backgroundColor &>">
        <& *CHILD  &>
      </body>
    </html>
    
    Then /weather/Sunny might contain:
    <%extends Report>
    <%override title>
      <%xargs>
        dayOfWeek;
      </%xargs>
      <% dayOfWeek %> looks Sunny!
    </%override>
    Head for the beach!  It's going to be sunny and beautiful.
    
    resulting in something like
    <html>
      <head>
        <title>
          Monday looks Sunny!
    
        </title>
      </head>
      <body bgcolor="white">
        Head for the beach!  It's going to be sunny and beautiful.
      </body>
    </html>
    
    However, /weather/StormWarning could contain:
    <%extends Report>
    <%override title>
      <%xargs>
        city;
      </%xargs>
      Storm Warning for <% city %>
    </%override>
    <%override backgroundColor>grey</%override>
    Now would be a poor time to go sailing.
    
    resulting in something like
    <html>
      <head>
        <title>
          Storm Warning for Boston
    
        </title>
      </head>
      <body bgcolor="grey">
        Now would be a poor time to go sailing.
      </body>
    </html>
    
  14. Fragment arguments It is possible to pass a "fragment" of a template as an argument to a template or subtemplate. When passing template fragments, the invocation syntax must look like <&| target ... &>, and any template content up until a closing </&> is considered the fragment argument.

    In order to pass a fragment argument, the target template or subtemplate must declare that it expects a fragment argument. This is done using the <%frag name/> declaration, which declares that the template or subtemplate expects a fragment argument.

    The fragment can be invoked in the target template or subtemplate like any other template or subtemplate invocation, simply specifying the name of the fragment argument as the target

    Putting this all together, the template

    <%def _lilink>
      <%frag content/>
      <%args>
        String href;
      </%args>
      <li><a href="<% href %>"><& content &></a></li>\
    </%def>
    
    <%def _big>
      <%frag stuff/>
    <font size="+4"><& stuff &></font>\
    </%def>
    
    <ul>
      <&| _lilink; href = "index.html" &>Home</&>
      <&| _lilink; href = "faq.html" &><b>FAQ</b></&>
      <&| _lilink; href = "toc.html" &><&| _big &>Table of contents</&></&>
    </ul>
    
    produces
    <ul>
      <li><a href="index.html">Home</a></li>
      <li><a href="faq.html"><b>FAQ</b></a></li>
      <li><a href="toc.html"><font size="+4">Table of contents</font></a></li>
    </ul>
    
  15. Parametrized fragment arguments Template fragments can themselves take arguments. The invocation syntax is similar to a regular template fragment with the addition of an <%args>...</%args> inside the fragment.

    To pass a parameterized template fragment to a template or subtemplate, the fragment and its parameters must be declared via a <%frag name%>parameters</%frag>, where each parameter is a type followed by an identifier. Thus a <%frag name>...</%frag> block is similar to a <%args>...</%args> block, except that it has a name and its parameters cannot have default values. Inside the template or subtemplate, the parameterized fragment is invoked exactly like a call to a subtemplate whose name is the name of the fragment.

    For example

    <%def _list>
      <%frag display>
        double temperature;
      </%frag>
      <%args>
        double[] temps;
      </%args>
    <ul>
    <%for int i = 0; i < temps.length; i++ %>\
      <li><& display; temperature = temps[i] &>
    </%for>\
    </ul>
    </%def>
    
    <&| _list; temps = new double[] { -13.0, 34.0 }  &>\
      <%args>
        double temperature;
      </%args>
      <%if temperature > 0.0 %>water at <% temperature %> degrees<%else><b>ice</b></%if>\
    </&>
    
    produces
    <ul>
      <li>  <b>ice</b>
      <li>  water at 34.0 degrees
    </ul>
    
  16. Context In addition to explicit arguments, a special variable called jamonContext can optionally be passed around between some or all templates in a project. To do this, first assign a value to the org.jamon.contextType property via a jamon.properties file; this value should be a java type, or the empty string to have no jamonContext. All templates with a jamonContext will have a setJamonContext method on their proxies, and a variable named jamonContext will be visible in the template. It is an error to try calling a template that expects context from one that does not have a context object. If a template inherits from another template which has a context variable, the child template will automatically have a context variable of the same type, regardless of what settings are specified via jamon.properties.

    For example, to supply the protocol to use for image urls, one might include in jamon.properties the line:

    org.jamon.contextType=String
    
    and then have a template image.jamon contain
    <%args>String path;</%args>
    <img href="<% jamonContext %>://www.somehost.org/<% path %>"/>
    
    Since in general, one can expect to have more than one piece of data needed in context, it is advised that the type chosen for jamonContext be a user-defined java bean that can be extended with additional properties as needed. Third party libraries wishing to take advantage of context should chose an interface for their context type, so that clients of the library can implement that interface, and still provide any additional context information they might need.
  17. jamon.properties Certain options in template processing are expressed by properties files. If a file called "jamon.properties" is present in the template directory, or one of it's subdirectories, then all jamon templates within that directory and its subdirectories will be processed according to the properties set. If a descendant subdirectory also contains a jamon.properties file, then properties set there will override properties set above.

    Currently, there are three types of properties jamon knows about:

    • org.jamon.emitMode - can be one of standard, limited or strict. See the section on Emit Modes for more information.
    • org.jamon.contextType - sets the type for the jamon context variable; if this property is the empty string, then there is no context variable. See the section on Context for more information.
    • org.jamon.alias.aliasName - declares a path alias for all templates.
  18. Generics Templates can have parameterized types, otherwise known as generics. This is primarily usefull for templates accepting parameterized fragments. For example, if map.jamon contains
    <%import>java.util.Map;</%import>
    <%generic>K, V</%generic>
    <%args>Map<K, V> map;</%args>
    <%frag key>K key;</%frag>
    <%frag value>V value;</%frag>
    <%for Map.Entry<K, V> entry : map.entrySet() %>\
    <& key: entry.getKey() &>: <& value: entry.getValue() &>
    </%for>
    
    then
    <%import>
      java.util.*;
      java.text.*;
    </%import>
    <%java>
      HashMap<String, Date> birthDays = new HashMap<String, Date>();
      birthDays.put("John", new GregorianCalendar(1940, 9, 9).getTime());
      birthDays.put("Paul", new GregorianCalendar(1942, 5, 18).getTime());
      birthDays.put("George", new GregorianCalendar(1943, 1, 25).getTime());
      birthDays.put("Ringo", new GregorianCalendar(1940, 6, 7).getTime());
      final DateFormat format = new SimpleDateFormat("EEE, MMM d, yyyy");
    </%java>
    
    <&|| map<String, Date>: birthDays &>
      <|key><%args>String name;</%args><% name %>'s birthday</|>
      <|value><%args>Date birthday;</%args><% format.format(birthday) %></|>
    </&>
    
    produces
    Paul's birthday: Thu, Jun 18, 1942
    Ringo's birthday: Sun, Jul 7, 1940
    John's birthday: Wed, Oct 9, 1940
    George's birthday: Thu, Feb 25, 1943
    

    Note that abstract templates cannot have parameterized types, nor can subtemplates. However, if a template has a parameterized type, that type is available to any subtemplates of that template.

  19. Path aliases It is possible to create aliases for path-names. This can either be done in the template, or through jamon.properties . The basic syntax for doing it in a template is: <%alias> shortcut = /full/path; ... </%alias> Shortcut must be a single word, without slashes; the only exception to this is that "/" may be made an alias, refering to the "empty" shortcut. Already defined aliases can be used to declare the full path for other aliases. To use an alias, replace /full/path// with shortcut// when refering to other templates (note the double-slash after shortcut. Aliases may only be used for the leading part of a path. Note that the old style syntax of placing a => instead of a = between the shortcut and full path is deprecated.

    For example:

    <%alias>
      / = /com/foo/bar;
      nav = //navigation;
      legal = /attorneys/documents;
    </%alias>
    
    <& //Home &>  -- calls /com/foo/bar/Home
    <& nav//Left &> -- calls /com/foo/bar/navigation/Left
    <& legal/Disclaimer &> -- calls /attorneys/documents/Disclaimer
    
    To define the same aliases as above through a jamon.properties file, one would say:
    org.jamon.alias./=/com/foo/bar
    org.jamon.alais.nav=/com/foo/bar/navigation
    org.jamon.alais.legal=/attorneys/documents
    
    Note that aliases defined through jamon.properties files may not make reference to other aliases in their definitions; the aliased path must always be specified as a full path.
  20. Character encoding By default, Jamon template source files are read using the default encoding of the running Java platform. The specific character encoding can be specified in the template by including an <%encoding ...> declaration at the very beginning of the template. For example, the following declaration indicates that the source of the template should be parsed in UTF-8:
    <%encoding UTF-8>
    The available encodings are exactly those supported by the JRE in use.