Template Reference Manual
- Static content
- Emit statements
- Flow control
- Arbitrary Java code
- Inheritance
- Class code
- Comments
- Imports
- Implements
- Annotations
- Arguments
- Invoking other templates
- Subtemplates
- Fragment arguments
- Parametrized fragment arguments
- Context
- jamon.properties
- Generics
- Path aliases
- Character encoding
- 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 ...%>
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. - 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
producesthis & 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
producingthis & 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("\"<b>this\n\'n\nthat</b>\"")">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 theorg.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
-
HTML (use
- 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.
- Basic for statement:
- 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.
- 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>
- 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.
- Comments
Any template content between
<%doc>
and</%doc>
is considered "documentation", and ignored by the template processor - 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 thestatic
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>
- 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 assetFoo()
andmakeRenderer()
.For example, given
interface RenderableWithInt { Renderer makeRenderer(int i); }
it's possible to declareMyTemplate.jamon
with<%implements> RenderableWithInt; </%implements> <%args> int i; </%args>
and then use it likeRenderableWithInt t = new MyTemplate(); i.makeRenderer(3);
- 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 %>
- 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, theAddress
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 tofavoriteFood
's argument to/parent
without referencing it in an<%xargs>...<%/xargs>
block. - 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 likeYou 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. - 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> </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> </td> <td align="center"> 46 </td> </tr> <tr> <td align="left">Junior</td> <td> </td> <td align="center" bgcolor="red"> 8 </td> </tr> <tr> <td align="left">Minnie</td> <td> </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 adef , 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>
- 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>
- 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>
- 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 theorg.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 asetJamonContext
method on their proxies, and a variable namedjamonContext
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. - 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
orstrict
. 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.
- org.jamon.emitMode - can be one of
- 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) %></|> </&>
producesPaul'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.
- 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. - 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.