/*
* Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com)
* Licensed under the Apache License, Version 2.0 (the "License")
* $Id: Template.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.template;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import com.uwyn.rife.config.Config;
import com.uwyn.rife.template.exceptions.TemplateException;
/**
* A template is used to construct, manipulate and produce text content.
* <p>Templates can be used for a variety of text types, including XHTML,
* plain text, XML, SQL and even Java source. Each template type has similar
* features, the biggest difference is the syntax of the invisible tag which
* takes the form of a comment in the corresponding language (<code><!--
* --> </code>for XHTML and XML, <code>/* -* /</code> for Java and SQL,
* ...).
* <h2>Using templates</h2>
* <p>Templates are most commonly used to produce web pages, which is why a
* method like {@link com.uwyn.rife.engine.Element#getXhtmlTemplate(String)} is used. By obtaining
* a template instance from the active {@link com.uwyn.rife.engine.Element}, features that are
* related to the web engine are added. To print a template for page output,
* {@link com.uwyn.rife.engine.Element#print(Template)} is usually used. However, the content of
* any template instance can be retrieved with the {@link #getContent} method
* which produces a regular <code>String</code> that is usable anywhere.
* <h2>Components of a template</h2>
* <p>Templates are controlled by external code (usually a {@linkplain
* com.uwyn.rife.engine.ElementSupport RIFE element}), but communication is bidirectional between a
* template and the logic that controls it. A template can provide content to
* the controller through <em>blocks</em>, and the controller can insert or
* replace text in the template through <em>template values</em>. The
* controller can also provide the template with <em>expression variables</em>
* and <em>resource bundles</em>.
* <h3>Values</h3>
* <p>A value is the simplest concept in a template. It is the placeholder for
* text somewhere in a block or in the page itself. In a HTML template, a
* value called "<code>name</code>" is created using a declaration like:
* <pre><code><!--!V 'name'/--></code></pre>
* <p>The controller can then fill this value with any of the {@link
* #setValue(String, String) setValue} and {@link #appendValue(String, String)
* appendValue} methods.
* <p>Values are mainly a one-way communication channel from the logic to the
* template. However, values may contain a default value which can be
* {@linkplain #getDefaultValue read} by the controller:
* <pre><!--V 'name'-->Some default<!--/V--></pre>
* <p>Values are automatically filled in many ways aside from calling {@link
* #setValue} and {@link #appendValue} directly. We will discuss this later.
* <h3>Blocks</h3>
* <p>Blocks represent the other direction of communication between a
* controller and a template. A HTML template can define a block called "<code>greeting</code>"
* like this:
* <pre><!--B 'greeting'-->Welcome, <!--V 'name'/--><!--/B--></pre>
* <p>The literal text in the block is not accessible by the controller. It is
* evaluated when the block is used. For example by {@linkplain #getBlock
* reading it from the controller}, {@linkplain #setBlock assigning it to a
* value} or {@linkplain #appendBlock appending it to a value} in the template
* itself. The evaluation is based on the values that are currently present in
* the template. If a block contains a value that hasn't been set yet, the
* value placeholder will be remembered, unpopulated. It will be evaluated
* against another value context the next time the content of the block is
* used.
* <p>As soon as value placeholders exist when a block is used, they are
* captured from the template and replaced with their available content. They
* will become immutable in the result of the operation that used the block.
* This means that repeated calls to {@link #appendBlock} can append a block
* to a value multiple times with different values each time. This feature
* allows blocks to be used for producing repeating constructs such as tables,
* using a pattern like this:
* <pre>template.removeValue("people", "");
*Iterator it = people.iterator();
*while (it.hasNext()) {
* Person person = (Person)it.next();
* template.setValue("name", person.getName());
* template.setValue("age", person.getAge());
* template.appendBlock("people", "person");
*}</pre>
* <p>Nested loops and corresponding nested blocks may be used to produce more
* complex constructs.
* <h3>Expressions</h3>
* <p>Templates may contain small boolean expressions that are written in JVM
* scripting languages like OGNL, Groovy, or Janino. These expressions will be
* automatically evaluated and allow certain blocks to be assigned
* automatically to a value according to the scripted conditions. The
* controller does not execute the scripts itself, but it may provide
* variables to which the scripts have access, using the {@link
* #setExpressionVar setExpressionVar} method. For example, if a template
* contains:
* <pre><!--V 'GROOVY:welcome'--><!--/V-->
*<!--V 'GROOVY:welcome:[[ showWelcome ]]'-->Welcome,
*<!--V 'name'/--><!--/V--></pre>
* <p>A controller could decide whether the welcome block should be shown
* using:
* <pre>template.setExpressionVar("showWelcome", person != null);</pre>
* <p>Apart from the expression variables, each expression is evaluated
* against a current root object whose methods and properties you can access
* using the regular scripting language syntax. This root object is by default
* the template instance that you are processing.
* <p>To make it easy to write expressions against commonly used contexts,
* RIFE also provides specialized scripted tags that set different root
* objects. Currently the <code>language:ROLEUSER</code> and
* <code>language:CONFIG</code> tags are provided.
* <h3>Localization</h3>
* <p>It's possible to easily localize templates through the standard {@link
* ResourceBundle} mechanism that is available in Java. The strings that are
* localized are automatically filtered and replace values tags. The format
* for localized values is:
* <pre><!--V 'L10N:key'-->default value<!--/V--></pre>
* <p>Of course, before replacement, the template instance has to know where
* to look for the key. Therefore, the {@link
* #addResourceBundle(ResourceBundle)} method needs to be called to make the
* template aware of it.
* <p>For example, consider the following resource bundles:
* <p><b>text_nl.properties</b>
* <pre>hello = Hallo</pre>
* <p><b>text_fr.properties</b>
* <pre>hello = Bonjour</pre>
* <p>and the following template:
* <pre>Hey mister, I said: <!--V 'L10N:hello'/-->!"</pre>
* <p>The following Java code:
* <pre>Template template_html = TemplateFactory.HTML.get("text");
*ResourceBundle bundle = Localization.getResourceBundle("text", "fr");
*template_html.addResourceBundle(bundle);
*System.out.println(template.getContent());</pre>
* <p>will output:
* <pre>Hey mister, I said: "Bonjour!"</pre>
* <p>Just replacing the second line with the following:
* <pre>...
*ResourceBundle bundle = Localization.getResourceBundle("text", "nl");
*...</pre>
* <p>will output:
* <pre>Hey mister, I said: "Hallo!"</pre>
* <p>Very often, resourcebundle are used for the whole application.
* Therefore, application-wide default resource bundles can be specified for
* each template type through the {@link com.uwyn.rife.config RIFE
* configuration}, for example:
* <pre><list name="TEMPLATE_DEFAULT_RESOURCEBUNDLES_ENGINEHTML">
* <item>l10n/graphics</item>
* <item>l10n/text</item>
* <item>l10n/descriptions</item>
*</list></pre>
* <p>This will automatically add these resourcebundles to any template
* instance of the corresponding type, calling {@link
* #addResourceBundle(ResourceBundle)} is thus not needed anymore and
* localization will happen without any intervention from the controller.
* <p>While resource bundles offer a good method to isolate localized text
* snippets, it's sometimes interesting to be able to conditionally display
* parts of templates with lots of markup. For this purpose, resource bundles
* are actually awkward to use. Templates are therefore able to set blocks
* automatically to values, according to the default localization language (<code>L10N_DEFAULT_LANGUAGE</code>
* configuration parameter). This can be done with the <code><!--B
* 'LANG:id:language'--></code> block syntax.
* <p>For example:
* <pre><!--V 'LANG:value1'-->default<!--/V--> [!V 'LANG:value2'/]
*<!--B 'LANG:value1:nl'-->ja ja<!--/B-->
*[!B 'LANG:value2:fr']oui oui[!/B]
*[!B 'LANG:value2:en ']yes yes[!/B]</pre>
* <p>will display this when the default language is '<code>en</code>':
* <pre>default yes yes</pre>
* <p>or this when the default language is '<code>fr</code>':
* <pre>default oui oui</pre>
* <p>or this when the default language is '<code>nl</code>':
* <pre>ja ja [!V 'LANG:value2'/]</pre>
* <h3>Value renderers</h3>
* <p>Besides the main manipulation logic of a template, value content needs
* to be sometimes created that is solely presentation related. This doesn't
* actually have its place in elements and sometimes even creates a burden.
* For these purposes, we created the {@link ValueRenderer} interface. Classes
* that implement this interface can be specified in any template like this:
* <pre><!--V 'RENDER:pakkage.classname'/--></pre>
* <p>An instance of the class will be created and the {@link
* ValueRenderer#render} method will be called if the value hasn't been set
* yet. This has as side-effect that if you have several occurances of this
* value ID, they will all have the same renderer value and the renderer will
* only be called once.
* <p>If you need to have different results of the same renderer, you need to
* use a differentiator, like this:
* <pre><!--V 'RENDER:pakkage.classname:differentiator'/--></pre>
* <h3>Encoding</h3>
* <p>Templates automatically encode values to the appropriate format (HTML,
* XHTML, etc.) when using forms, {@linkplain #evaluateConfigTags
* configuration tags}, localization tags, and when {@linkplain
* #setBean(Object, String, boolean) setting values from bean properties}.
* However, in many cases it is necessary to encode values manually, to
* prevent malicious content from being inserted into your site, or simply to
* display text correctly if it may contain illegal characters (like
* <code><</code> in HTML). You can encode text using the template's
* encoder after calling the {@link #getEncoder} method.
* <h2>Other features</h2>
* <p>Templates are powerful and some features are not described here. The <a
* href="http://rifers.org/wiki/display/RIFE/Templates">Templates</a> wiki
* page describes several other features, including filtered values,
* alternative means of localization, and other forms of templates.
*
* @author Keith Lea (keith[remove] at cs dot oswego dot edu)
* @author Geert Bevin (gbevin[remove] at uwyn dot com)
* @version $Revision: 3918 $
* @since 1.0
*/
public interface Template extends Cloneable
{
/**
* Appends the content of a block to a value. The values used by the block
* will be captured when this method is called, so any future changes to
* template values will not affect text which was appended when this
* method is called.
*
* @param valueId the ID of the value
* @param blockId the ID of the block
* @exception TemplateException when the <code>valueId</code> or
* <code>blockId</code> aren't known
* @see #setBlock
* @see #getBlock
* @see #getContent
* @see #hasBlock
* @since 1.0
*/
public void appendBlock(String valueId, String blockId) throws TemplateException;
/**
* Replaces the specified value with the content of the specified block.
* The values used by the block will be captured when this method is
* called, so any future changes to template values will not affect the
* specified value text.
*
* @param valueId the ID of the value
* @param blockId the ID of the block
* @exception TemplateException when the <code>valueId</code> or
* <code>blockId</code> aren't known
* @see #appendBlock
* @see #getBlock
* @see #getContent
* @see #hasBlock
* @since 1.0
*/
public void setBlock(String valueId, String blockId) throws TemplateException;
/**
* Returns the evaluated content of the specified block as a text.
*
* @param id the ID of the block in the template
* @return the evaluated textual content of the specified block
* @exception TemplateException when the block ID isn't known
* @see #appendBlock
* @see #setBlock
* @see #getContent
* @see #hasBlock
* @since 1.0
*/
public String getBlock(String id) throws TemplateException;
/**
* Returns the entire content of the template and finalize all non
* evaluated values. The content is the root block with has an empty
* string as identifier.
* <p>Values without content will either use their default value if it has
* been provided, or the tag that was used to declare the value will be
* output as-is.
* <p>All specialized tags will also be evaluated (resourcebundle
* localization, block localization, value renderers, expressions, ...).
*
* @return the entire textual content of the template
* @exception TemplateException when an error occurred during the
* processing of the specialized tags
* @see #appendBlock
* @see #setBlock
* @see #getBlock
* @see #hasBlock
* @since 1.0
*/
public String getContent() throws TemplateException;
/**
* Writes the {@linkplain #getBlock(String) evaluated contents} of the
* specified block to the given output stream, using <code>UTF-8</code>
* encoding.
*
* @param id the ID of the block
* @param out the stream to write to
* @exception IOException when errors occur during the manipulation of the
* output stream
* @exception TemplateException when the block ID isn't known
* @see #writeContent(OutputStream)
* @see #writeContent(OutputStream, String)
* @see #write
* @since 1.0
*/
public void writeBlock(String id, OutputStream out) throws IOException, TemplateException;
/**
* Writes the {@linkplain #getContent() complete evaluated template
* content} to the given stream, using UTF-8 encoding.
*
* @param out the stream to which the template contents should be written
* @exception IOException when errors occur during the manipulation of the
* output stream
* @exception TemplateException when an error occurs during the template
* content evaluation
* @see #writeBlock
* @see #writeContent(OutputStream, String)
* @see #write
* @since 1.0
*/
public void writeContent(OutputStream out) throws IOException, TemplateException;
/**
* Writes the {@linkplain #getContent() complete evaluated template
* content} to the given stream, using the specified charset for encoding.
*
* @param out the stream to which the template contents should be written
* @param charsetName the name of the charset to use
* @exception IOException when errors occur during the manipulation of the
* output stream; or
* <p>when the character set isn't valid
* @exception TemplateException when an error occurs during the template
* content evaluation
* @see #writeBlock
* @see #writeContent(OutputStream)
* @see #write
* @since 1.0
*/
public void writeContent(OutputStream out, String charsetName) throws IOException, TemplateException;
/**
* This method is a shorthand for {@link #writeContent(OutputStream)}.
*
* @param out the stream to which the template contents should be written
* @exception IOException when errors occur during the manipulation of the
* output stream; or
* <p>when the character set isn't valid
* @exception TemplateException when an error occurs during the template
* content evaluation
* @see #writeBlock
* @see #writeContent(OutputStream)
* @see #writeContent(OutputStream, String)
* @since 1.0
*/
public void write(OutputStream out) throws IOException, TemplateException;
/**
* Returns the content of the specified block as a list with all the
* individual parts.
* <p>This list is the internal representation of all content with
* placeholders for the values that aren't filled in yet. This structure
* is mainly used internally by the framework. The list structure also
* makes it possible to optimize performance and memory usage.
*
* @param id the ID of a block in this template
* @return a list of the contents of the specified block
* @exception TemplateException if no such block exists; or
* <p>if an error occurred during the retrieval
* @see #getDeferredContent
* @since 1.0
*/
public List<CharSequence> getDeferredBlock(String id) throws TemplateException;
/**
* Returns the content of this template as a list with all the individual
* parts.
* <p>This list is the internal representation of all content with
* placeholders for the values that aren't filled in yet. This structure
* is mainly used internally by the framework. The list structure also
* makes it possible to optimize performance and memory usage.
*
* @return a list of the contents of this template
* @exception TemplateException if an error occurred during the retrieval
* @see #getDeferredBlock
* @since 1.0
*/
public List<CharSequence> getDeferredContent() throws TemplateException;
/**
* Returns an anonymous value that can be used to construct complex
* content for use within this template. See {@link InternalValue} for
* details.
* <p>The returned internal value is tied closely to the template it was
* obtained from, methods like {@link InternalValue#appendBlock(String)
* InternalValue.appendBlock} reference blocks within this template.
*
* @return a new internal value instance for constructing more complex
* parts of this template
* @see InternalValue
* @since 1.0
*/
public InternalValue createInternalValue();
/**
* Sets the specified value in this template to content that's structured
* in the internal format.
*
* @param id the ID of the value in this template
* @param deferredContent content in the internal format
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, List<CharSequence> deferredContent) throws TemplateException;
/**
* Sets the specified value in this template to the value of the given
* {@linkplain #createInternalValue() internal value}.
*
* @param id the ID of the value in this template
* @param internalValue an internal value, <code>null</code> set the value
* content to blank content
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, InternalValue internalValue) throws TemplateException;
/**
* Sets the specified value in this template to the result of calling
* {@link String#valueOf(Object) String.valueOf} on the given
* <code>value</code>.
*
* @param id the ID of the value in this template
* @param value an object
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, Object value) throws TemplateException;
/**
* Sets the specified value in this template to <code>true</code> or
* <code>false</code> depending on the given <code>value</code>.
*
* @param id the ID of the value in this template
* @param value a boolean value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, boolean value) throws TemplateException;
/**
* Sets the specified value in this template to the single specified
* character.
*
* @param id the ID of the value in this template
* @param value a character
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, char value) throws TemplateException;
/**
* Sets the specified value in this template to the given characters. The
* given value must not be <code>null</code>.
*
* @param id the ID of the value in this template
* @param value a string of characters
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, char[] value) throws TemplateException;
/**
* Sets the specified value in this template to the specified range of the
* given character string. The specified number of bytes from
* <code>value</code> will be used, starting at the character specified by
* <code>offset</code>.
*
* @param id the ID of the value in this template
* @param value a character string
* @param offset the index in <code>value</code> of the first character to
* use
* @param count the number of characters to use
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, char[] value, int offset, int count) throws TemplateException;
/**
* Sets the specified value in this template to the given double precision
* floating point value. This method uses the {@linkplain
* String#valueOf(double) String.valueOf} method to print the given value,
* which probably prints more digits than you like. You probably want
* {@link String#format String.format} or {@link NumberFormat} instead.
*
* @param id the ID of the value in this template
* @param value a floating point value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
*
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, double value) throws TemplateException;
/**
* Sets the specified value in this template to the given floating point
* value. This method uses the {@linkplain String#valueOf(float)
* String.valueOf} method to print the given value, which probably prints
* more digits than you like. You probably want {@link String#format
* String.format} or {@link NumberFormat} instead.
*
* @param id the ID of the value in this template
* @param value a floating point value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, float value) throws TemplateException;
/**
* Sets the specified value in this template to the given integer.
*
* @param id the ID of the value in this template
* @param value an integer
* @exception TemplateException if the specified value does not exist in
* this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, int value) throws TemplateException;
/**
* Sets the specified value in this template to the given long.
*
* @param id the ID of the value in this template
* @param value a long
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, long value) throws TemplateException;
/**
* Sets the specified value in this template to the given string, or an
* empty string if <code>value</code> is <code>null</code>.
*
* @param id the ID of the value in this template
* @param value a string, or <code>null</code>
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, String value) throws TemplateException;
/**
* Sets the specified value in this template to the given character sequence,
* or an empty character sequence if <code>value</code> is <code>null</code>.
*
* @param id the ID of the value in this template
* @param value a character sequence, or <code>null</code>
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.5
*/
public void setValue(String id, CharSequence value) throws TemplateException;
/**
* Sets the specified value in this template to the current {@linkplain
* #getContent() content} of the given template. The given template's
* value will be evaluated immediately, instead of being stored to be
* evaluated later.
* <p>If the given template is <code>null</code>, the specified value will
* be set to an empty string.
*
* @param id the ID of the value in this template
* @param template a template
* @exception TemplateException if the specified value ID does not exist
* in this template; or
* <p>if an error occurred during the evaluation of the template parameter
* @see #appendValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void setValue(String id, Template template) throws TemplateException;
/**
* Sets all values in this template whose identifiers match names of
* properties in the given bean.
* <p>For example, given a class:
* <pre>
* class Person {
* private String first;
* private String last;
*
* public String getFirstName() { return first; }
* public void setFirstName(String name) { this.first = name; }
*
* public String getLastName() { return last; }
* public void setLastName(String name) { this.last = name; }
* </pre>
* <p>And given a template:
* <pre>
* Hello <!--V 'firstName'/--> <!--V 'lastName'/-->.
* </pre>
* <p>Calling this method with an instance of Person where
* <code>first</code> was "Jim" and <code>last</code> was "James", would
* produce:
* <pre>Hello Jim James.</pre>
* <p>Calling this method is equivalent to calling {@link
* #setValue(String, String) setValue} individually for each property of
* the bean.
* <p>This method uses this template's {@linkplain #getEncoder encoder} to
* encode the bean properties before setting the values. To prevent this,
* use {@linkplain #setBean(Object, String, boolean) the other form of
* setBean}.
* <p>Only <em>bean properties</em> will be considered for insertion in
* the template. This means only properties with a <em>getter and a setter</em>
* will be considered.
*
* @param bean a bean whose properties will be used to fill in values in
* the template
* @exception TemplateException if this template has no bean handling
* capability; or
* <p>an error occurred during the introspection of the bean
* @see #removeBean
* @since 1.0
*/
public void setBean(Object bean) throws TemplateException;
/**
* Sets all values in this template whose names match names of properties
* in the given bean, preceded by the given prefix.
* <p>For example, given a class:
* <pre>
* class Person {
* private String first;
* private String last;
*
* public String getFirstName() { return first; }
* public void setFirstName(String name) { this.first = name; }
*
* public String getLastName() { return last; }
* public void setLastName(String name) { this.last = name; }
* </pre>
* <p>And given a template:
* <pre>
* Hello <!--V 'NAME:firstName'/--> <!--V 'NAME:lastName'/-->.
* </pre>
* <p>Calling this method with an instance of Person where
* <code>first</code> was "Jim" and <code>last</code> was "James", and the
* prefix "NAME:", would produce:
* <pre>Hello Jim James.</pre>
* <p>Calling this method is equivalent to calling {@link
* #setValue(String, String) setValue} individually for each property of
* the bean prefixed with the given prefix.
* <p>This method uses this template's {@linkplain #getEncoder encoder} to
* encode the bean properties before setting the values. To prevent this,
* use {@linkplain #setBean(Object, String, boolean) the other form of
* setBean}.
* <p>Only <em>bean properties</em> will be considered for insertion in
* the template. This means only properties with a <em>getter and a setter</em>
* will be considered.
*
* @param bean a bean whose properties will be used to fill in values in
* the template
* @param prefix the prefix of values which will be filled with the given
* bean's property values
* @exception TemplateException if this template has no bean handling
* capability; or
* <p>an error occurred during the introspection of the bean
* @see #removeBean
* @since 1.0
*/
public void setBean(Object bean, String prefix) throws TemplateException;
/**
* Sets all values in this template whose names match names of properties
* in the given bean, preceded by the given prefix, if present. If the
* given prefix is <code>null</code>, it is ignored.
* <p>For example, given a class:
* <pre>
* class Person {
* private String first;
* private String last;
*
* public String getFirstName() { return first; }
* public void setFirstName(String name) { this.first = name; }
*
* public String getLastName() { return last; }
* public void setLastName(String name) { this.last = name; }
* </pre>
* <p>And given a template:
* <pre>
* Hello <!--V 'NAME:firstName'/--> <!--V 'NAME:lastName'/-->.
* </pre>
* <p>Calling this method with an instance of Person where
* <code>first</code> was "Jim" and <code>last</code> was "James", and the
* prefix "NAME:", would produce:
* <pre>Hello Jim James.</pre>
* <p>Calling this method is equivalent to calling {@link
* #setValue(String, String) setValue} individually for each property of
* the bean prefixed with the given prefix.
* <p>If <code>encode</code> is <code>true</code>, this method will use
* this template's {@linkplain #getEncoder encoder} to encode the bean
* properties before setting the values.
* <p>Only <em>bean properties</em> will be considered for insertion in
* the template. This means only properties with a <em>getter and a setter</em>
* will be considered.
*
* @param bean a bean whose properties will be used to fill in values in
* the template
* @param prefix the prefix of values which will be filled with the given
* bean's property values
* @param encode <code>true</code> if the bean poroperty values have to be
* encoded; or
* <p><code>false</code> otherwise
* @exception TemplateException if this template has no bean handling
* capability; or
* <p>an error occurred during the introspection of the bean
* @see #removeBean
* @since 1.0
*/
public void setBean(Object bean, String prefix, boolean encode) throws TemplateException;
/**
* Reverts all values to their defaults when the identifiers match
* properties of the given bean, whether or not those values were set with
* a previous call to {@link #setBean(Object) setBean}. The values of the
* bean's properties are ignored.
* <p>Calling this method is equivalent to calling {@link #removeValue
* removeValue} once for the name of each property of the given bean.
*
* @param bean a bean
* @exception TemplateException if this template has no bean handling
* capability; or
* <p>an error occurred during the introspection of the bean
* @see #setBean
* @since 1.0
*/
public void removeBean(Object bean) throws TemplateException;
/**
* Reverts all values to their defaults when the identifiers match
* properties of the given bean preceded by the given prefix, whether or
* not those values were set with a previous call to {@link
* #setBean(Object) setBean}. The values of the bean's properties are
* ignored.
* <p>Calling this method is equivalent to calling {@link #removeValue
* removeValue} once for the name of each property of the given bean,
* prefixed with the given prefix.
*
* @param bean a bean whose properties will be used to determine which
* values to remove from the template
* @param prefix a prefix
* @exception TemplateException if this template has no bean handling
* capability; or
* <p>an error occurred during the introspection of the bean
* @see #setBean
* @since 1.0
*/
public void removeBean(Object bean, String prefix) throws TemplateException;
/**
* Appends the result of calling {@link String#valueOf(Object)
* String.valueOf} on the given <code>value</code> to the specified value
* in this template.
*
* @param id the ID of the value in this template
* @param value an object
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, Object value) throws TemplateException;
/**
* Appends <code>"true"</code> or <code>"false"</code> to the specified
* value in this template, depending on the given <code>value</code>.
*
* @param id the ID of the value in this template
* @param value a boolean value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, boolean value) throws TemplateException;
/**
* Appends the single specified character to the specified value in this
* template.
*
* @param id the ID of the value in this template
* @param value a character
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, char value) throws TemplateException;
/**
* Appends the given characters to the specified value in this template.
* The given value must not be <code>null</code>.
*
* @param id the ID of the value in this template
* @param value a string of characters
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, char[] value) throws TemplateException;
/**
* Appends the specified range of the given character string to the
* specified value in this template. The specified number of bytes from
* <code>value</code> will be used, starting at the character specified by
* <code>offset</code>.
*
* @param id the ID of the value in this template
* @param value a character string
* @param offset the index in <code>value</code> of the first character to
* use
* @param count the number of characters to use
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, char[] value, int offset, int count) throws TemplateException;
/**
* Appends the given double precision floating point value to the
* specified value in this template. This method uses the {@linkplain
* String#valueOf(double) String.valueOf} method to print the given value,
* which probably prints more digits than you like. You probably want
* {@link String#format String.format} or {@link NumberFormat} instead.
*
* @param id the ID of the value in this template
* @param value a floating point value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, double value) throws TemplateException;
/**
* Appends the given floating point value to the specified value in this
* template. This method uses the {@linkplain String#valueOf(float)
* String.valueOf} method to print the given value, which probably prints
* more digits than you like. You probably want {@link String#format
* String.format} or {@link NumberFormat} instead.
*
* @param id the ID of the value in this template
* @param value a floating point value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, float value) throws TemplateException;
/**
* Appends the given integer to the specified value in this template.
*
* @param id the ID of the value in this template
* @param value an integer
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, int value) throws TemplateException;
/**
* Appends the given long to the specified value in this template.
*
* @param id the ID of the value in this template
* @param value a long
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, long value) throws TemplateException;
/**
* Appends the given string, or an empty string if <code>value</code> is
* <code>null</code>, to the specified value in this template.
*
* @param id the ID of the value in this template
* @param value a string, or <code>null</code>
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public void appendValue(String id, String value) throws TemplateException;
/**
* Returns the current content of the specified value as a string.
*
* @param id the ID of a value in this template
* @return the current content value of the specified value
* @exception TemplateException if the specified value ID does not exist
* in this template
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public String getValue(String id) throws TemplateException;
/**
* Returns the original text of the specified value, before any
* modification that may have been made using {@link #setValue} or similar
* methods.
* <p>If no default value was specified for the given value, this method
* will return <code>null</code>.
*
* @param id the ID of a value in this template, or <code>null</code>
* @return the original text value of the specified value
* @see #hasDefaultValue
* @since 1.0
*/
public String getDefaultValue(String id);
/**
* Returns whether a {@linkplain #getDefaultValue default value} was
* specified in this template for the specified value.
*
* @param id the ID of a value in this template
* @return whether the specified value has a default value
* @see #getDefaultValue
* @since 1.0
*/
public boolean hasDefaultValue(String id);
/**
* Each template type supports a set of special block tags that are used
* for adding automated features like localization, block value scripting,
* config value setting, ... Instead of having to parse all template block
* identifiers each time these features are used, RIFE filters them out at
* template compilation and keeps them available in a separate collection.
* <p>This method is mainly used by the framework itself, the supported
* filter regular expressions are available from {@link TemplateFactory}
* and {@link TemplateFactoryEngineTypes}.
*
* @param filter a template factory regular expression
* @return a list of captured groups for matching block ID's
* @see #hasFilteredBlocks
* @since 1.0
*/
public List<String[]> getFilteredBlocks(String filter);
/**
* Returns whether any block matched a particular filter at template
* compilation.
*
* @param filter a template factory regular expression
* @return whether any matching blocks exist in this template
* @see #getFilteredBlocks
* @since 1.0
*/
public boolean hasFilteredBlocks(String filter);
/**
* Each template type supports a set of special value tags that are used
* for adding automated features like embedded elements, localization,
* block value scripting, config value setting, ... Instead of having to
* parse all template value identifiers each time these features are used,
* RIFE filters them out at template compilation and keeps them available
* in a separate collection.
* <p>This method is mainly used by the framework itself, the supported
* filter regular expressions are available from {@link TemplateFactory}
* and {@link TemplateFactoryEngineTypes}.
*
* @param filter a template factory regular expression
* @return a list of captured groups for matching value ID's
* @see #hasFilteredValues
* @since 1.0
*/
public List<String[]> getFilteredValues(String filter);
/**
* Returns whether any value matched a particular filter at template
* compilation.
*
* @param filter a template factory regular expression
* @return whether any matching values exist in this template
* @see #getFilteredValues
* @since 1.0
*/
public boolean hasFilteredValues(String filter);
/**
* Fills all values in this template which match "<code>L10N:<em>key</em></code>",
* where "<code>key</code>" is a {@linkplain
* ResourceBundle#getObject(String) key} in a {@linkplain
* #addResourceBundle(ResourceBundle) resource bundle} registered for this
* template. Each value will be filled with the value in the resource
* bundle with the corresponding key.
* <p>This method is normally called automatically during template
* initialization. You should call it if you wish to re-evaluate the tags
* at any time during the template's life.
*
* @return the list of names of the template values that were generated
* @since 1.0
*/
public List<String> evaluateL10nTags();
/**
* Fills all values in this template which match "<code>CONFIG:<em>key</em></code>",
* where "<code>key</code>" is a configuration value name in the {@link
* Config} instance returned by {@link Config#getRepInstance()}. Each
* valuev will be filled with the value of the configuration option with
* the corresponding key.
* <p>This method is normally called automatically during template
* initialization. You should call it if you wish to re-evaluate the tags
* at any time during the template's life.
*
* @return the list of names of the template values that were generated
* @since 1.0
*/
public List<String> evaluateConfigTags();
/**
* Fills the value "<code>LANG:<em>id</em></code>" with the value of the
* block "<code>LANG:<em>id</em>:<em>langid</em></code>", where "<code>id</code>"
* is the given ID, and "<code>langid</code>" is this template's
* {@linkplain #getLanguage() current language ID}.
* <p>If no matching block for the current language is found, the content
* of the specified value will not be modified.
* <p>This method is called automatically when the output is generated
* (such as when calling {@link #getContent()}). You can manually call
* this method to force evaluation of the tags earlier than that.
*
* @param id the ID whose language tag should be filled with the
* appropriate block
* @return the list of names of the template values that were generated
* @since 1.0
*/
public List<String> evaluateLangTags(String id);
/**
* Evaluates the specified OGNL, Groovy, or Janino expression tag. For
* example, if a value exists with ID "<code>OGNL:<em>id</em>:[[<em>script</em>]]</code>",
* where "<code>id</code>" is the given ID and "<code>script</code>" is
* some OGNL expression, this method will replace this value with the
* value of the evaluated OGNL expression, using the current set of
* {@linkplain #getExpressionVars() expression variables}.
* <p>The prefix for OGNL is "OGNL:", the prefix for Groovy is "GROOVY:"
* and the prefix for Janino is "JANINO:".
* <p>This method is called automatically when the output is generated
* (such as when calling {@link #getContent()}). You can manually call
* this method to force evaluation of the tags earlier than that.
*
* @param id the ID whose expression tag will be replaced with the value
* of the evaluated expression in the tag ID
* @return the list of names of the template values that were generated
* @since 1.0
*/
public List<String> evaluateExpressionTags(String id);
/**
* Evaluates the specified OGNL, Groovy, or Janino configuration
* expression tag. For example, if a value exists with ID "OGNL:CONFIG:<em>id</em>:[[<em>script</em>]]",
* where "id" is the given ID and "script" is some OGNL expression, this
* method will replace this value with the value of the evaluated OGNL
* expression, using the current set of {@linkplain #getExpressionVars()
* expression variables}.
* <p>The prefix for OGNL is "<code>OGNL:</code>", the prefix for Groovy
* is "<code>GROOVY:</code>" and the prefix for Janino is "<code>JANINO:</code>".
* <p>The context for the expressions will be the {@link Config} object
* returned by {@link Config#getRepInstance()}.
* <p>Expression config tags are evaluated automatically when the output
* is generated (such as when calling {@link #getContent()}). You can
* manually call this method to force evaluation of the tags earlier than
* that.
*
* @param id the ID whose expression tag will be replaced with the value
* of the evaluated expression in the tag ID
* @return the list of names of the template values that were generated
* @since 1.0
*/
public List<String> evaluateExpressionConfigTags(String id);
/**
* Evalutes all values in this template with ID's of the form "<code>RENDER:<em>class</em></code>"
* or "<code>RENDER:<em>class</em>:<em>differentiato</em></code><em>r</em>",
* where "<code>class</code>" is the fully-qualified name of a class which
* extends {@link ValueRenderer}, the result of calling {@link
* ValueRenderer#render(Template, String, String) ValueRenderer.render} on
* a new instance of the class. The class must contain a zero-argument
* ("no-arg") constructor.
* <p>For example, given a class <code>MyRenderer</code> in the package "<code>org.rifers.something</code>",
* which extends {@link ValueRenderer}, a value "<code>RENDER:org.rifers.something.MyRenderer:test</code>"
* would create a new instance of <code>MyRenderer</code> (using its
* no-arg constructor), call <code>render(this,
* "RENDER:org.rifers.something.MyRenderer:test", "test")</code>, and set
* the value in this template to whatever value the call returns.
* <p>Value renderer tags are evaluated automatically when the output is
* generated (such as when calling {@link #getContent()}). You can
* manually call this method to force evaluation of the tags earlier than
* that.
*
* @exception TemplateException if a class in a render tag cannot be
* instantiated
* @return the list of names of the template values that were generated
* @since 1.0
*/
public List<String> evaluateRenderTags() throws TemplateException;
/**
* Returns whether this template contains a block with the given ID.
*
* @param id the prospective ID of a block
* @return whether this template contains a block with the given ID
* @see #appendBlock
* @see #setBlock
* @see #getBlock
* @see #getContent
* @since 1.0
*/
public boolean hasBlock(String id);
/**
* Returns whether the specified value has been set. If this method
* returns <code>false</code>, the value has its original default value.
* <p>If no such value exists in this template, this method will not throw
* an exception, it will return <code>false</code>.
*
* @param id the ID of a value in this template
* @return whether the specified value has been set
* @see #appendValue
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public boolean isValueSet(String id);
/**
* Returns the number of values in this template which {@linkplain
* #isValueSet(String) have been set}.
*
* @return the number of values in this template which have been set
* @since 1.0
*/
public int countValues();
/**
* Reverts the specified value back to its default value.
*
* @param id the ID of a value in this template
* @see #appendValue
* @see #setValue
* @see #isValueSet
* @see #hasValueId
* @since 1.0
*/
public void removeValue(String id);
/**
* Reverts the specified values back to their default value.
*
* @param ids the IDs of values in this template
* @see #appendValue
* @see #setValue
* @see #isValueSet
* * @see #removeValue
* @see #hasValueId
* @since 1.6
*/
public void removeValues(List<String> ids);
/**
* Set the content of the specified value to an empte string.
*
* @param id the ID of a value in this template
* @see #appendValue
* @see #setValue
* @see #isValueSet
* @see #hasValueId
* @see #removeValue
* @see #removeValues
* @since 1.4
*/
public void blankValue(String id);
/**
* Resets all values in this template and removes any resource bundles.
* Configuration and localization tags are re-evaluated.
*
* @since 1.0
*/
public void clear();
/**
* Returns a list of the ID's of all values present in this template,
* including set and unset values.
*
* @return a list of ID's of all set and unset value
* @since 1.0
*/
public String[] getAvailableValueIds();
/**
* Returns a list of the ID's of all values in this template which
* {@linkplain #isValueSet(String) have not been set}.
*
* @return a list of ID's of values in this template which have not been
* set
* @since 1.0
*/
public Collection<String> getUnsetValueIds();
/**
* Returns whether this template contains a value with the given ID.
*
* @param id the potential ID of a value in this template
* @return whether this template contains a value with the given ID
* @see #appendValue
* @see #setValue
* @see #isValueSet
* @see #removeValue
* @see #removeValues
* @see #blankValue
* @see #hasValueId
* @since 1.0
*/
public boolean hasValueId(String id);
/**
* Returns when the file corresponding to this template was modified, in
* milliseconds since the Unix epoch.
*
* @return the time at which the underlying template file was modified
* @since 1.0
*/
public long getModificationTime();
/**
* Returns this template's {@linkplain BeanHandler bean handler}. The bean
* handler is used for filling bean values into template values, and for
* building forms.
*
* @return this template's bean handler
* @since 1.0
*/
public BeanHandler getBeanHandler();
/**
* Returns the encoder that this template uses to convert strings to
* values in the template's generated text output. In an HTML template,
* for example, this encoder may be used to convert text which may contain
* HTML special characters like <code><></code> to corresponding
* escaped strings.
*
* @return this template's encoder
* @since 1.0
*/
public TemplateEncoder getEncoder();
/**
* Adds a resource bundle to this template. Resource bundles are used in
* many places, including when generating labels for forms, generating
* options for <code><select></code> tags, and {@linkplain
* #evaluateL10nTags() using localized text}.
*
* @param resourceBundle a resource bundle
* @see #getResourceBundles
* @see #hasResourceBundles
* @since 1.0
*/
public void addResourceBundle(ResourceBundle resourceBundle);
/**
* Returns a list of the resource bundles used by this template. This will
* contain any bundles added through {@link #addResourceBundle
* addResourceBundle} as well as any default resource bundles.
*
* @return a list of this template's resource bundles
* @see #addResourceBundle
* @see #hasResourceBundles
* @since 1.0
*/
public Collection<ResourceBundle> getResourceBundles();
/**
* Returns whether this template has any resource bundles {@linkplain
* #addResourceBundle registered}.
*
* @return whether this template contains any resource bundles
* @see #addResourceBundle
* @see #getResourceBundles
* @since 1.0
*/
public boolean hasResourceBundles();
/**
* Sets this template's current language code, such as "en".
* <p>This is used when {@link #evaluateL10nTags filling localized text
* values}.
*
* @param lang a 2-letter language code for the language to be used by
* this template
* @see #getLanguage
* @since 1.0
*/
public void setLanguage(String lang);
/**
* Returns this template's current 2-letter language code. This code is
* used when {@link #evaluateL10nTags filling localized text values}. If
* the language has not been {@linkplain #setLanguage set}, it defaults to
* the language set by the RIFE configuration parameter "<code>L10N_DEFAULT_LANGUAGE</code>".
*
* @return the 2-letter language code currently used by this template
* @see #setLanguage
* @since 1.0
*/
public String getLanguage();
/**
* Sets a variable which can be accessed by {@linkplain
* #evaluateExpressionTags expression tags} in OGNL, Groovy, or Janino.
*
* @param name the name of the variable
* @param value the value to associate with the given variable name
* @see #setExpressionVars
* @see #getExpressionVars
* @since 1.0
*/
public void setExpressionVar(String name, Object value);
/**
* Sets the given variables to the given corresponding values, for use in
* {@linkplain #evaluateExpressionTags expression tags}. Calling this
* method is equivalent to calling {@link #setExpressionVar
* setExpressionVar} for each entry in the given map.
*
* @param map a map from variable name to variable value
* @see #setExpressionVar
* @see #getExpressionVars
* @since 1.0
*/
public void setExpressionVars(Map<String, Object> map);
/**
* Returns the name and value of all of the expression variables which
* have been {@linkplain #setExpressionVar set} in this template.
*
* @return the expression variables currently set in this template
* @see #setExpressionVar
* @see #setExpressionVars
* @since 1.0
*/
public Map<String, Object> getExpressionVars();
/**
* Stores the given value in a cache, associated with the given key. This
* is mainly used by OGNL, Groovy, and Janino expression evaluation system
* to store caches to classes. You should probably not use the template
* caching system to avoid conflicting with the expression evaluation
* system.
*
* @param key a name under which the given value should be stored
* @param value an object
* @since 1.0
*/
public void cacheObject(String key, Object value);
/**
* Returns the value corresponding to the given key in this template's
* cache, or <code>null</code> if no such cached object exists. As noted
* in {@link #cacheObject}, you should probably not use this method to
* avoid conflicting with RIFE's internal use of the cache.
*
* @param key a key whose associated cached object should be returned
* @return the value associated with the given key, or <code>null</code>
* if none exists
* @since 1.0
*/
public Object getCacheObject(String key);
/**
* Returns a list of URL's that this template depends on, and their last
* modification dates (in milliseconds since the Unix epoch). This method
* should return templates which are included by this template, and any
* other resources which are required to fully render the template.
*
* @return a list of URL's and last modification dates of resources on
* which this template depends
* @since 1.0
*/
public Map<URL, Long> getDependencies();
/**
* Returns this template's name, without path information or file
* extension. For example, for /Users/me/Something/templates/xyz.html,
* this method will return "xyz".
*
* @return this template's name, without path or file extension
* @since 1.0
*/
public String getName();
/**
* Returns this template's full name, as it was used to instantiate it
* by a template factory.
*
* @return this template's full name
* @since 1.6
*/
public String getFullName();
/**
* Returns this template's default content type, for example <code>text/html</code>.
*
* @return this template's default content type; or
* <p><code>null</code> if no default content type is known for this template instance
* @since 1.3
*/
public String getDefaultContentType();
/**
* Returns a shallow copy of this template, with the same values,
* expression variables, and so on.
*
* @return a shallow copy of this template
* @since 1.0
*/
public Object clone();
}