To design your RTF model, you can use following RTF element :
A merge field can be used too to insert an image (which could be generated) in your RTF model.
name of your merge field must respect the name of your JAVA object and getters (your context).
Design of your RTF model can be done with MS Word. Today it'snot possible to use OpenOffice. Click here for more d'informations.
Following sections describes rules to respect when you design your RTF model swith your JAVA context. Sections explains :
you can find samples of RTF model into rtftemplate-usecases-<version> distribution into the usecases/model folder. jakarta-velocity-model.rtf is the RTF model source which use the almost use case of RTFtemplate.
Samples describes below will use JAVA context composed by a liste of 2 developers. A developer has name. Here the code used when list is putted into the context :
List developers = new ArrayList(); Developer developer = new Developer(); developer.setName("Developer 1"); developers.add(developer); developer = new Developer(); developer.setName("Developer 2"); developers.add(developer); context.put("developers", developers );
Simples values are designed with merge fields (MERGEFIELD) and hyperlink fields (HYPERLINK). You can apply on those RTF elements a style (Bold, Color,...) by using standard fonctionnality of your tool (MS Word,...).
ATTENTION when you apply a style on a field,you must select the whole of the field, otherwise you can have trouble after merging.
When you create a filed, use ABSOLUTELY fonctionnalities for create field (with MS Word or RTFTemplate.dot). Don't update the name of the field in the RTF model!!! Several people wrote me for trouble with RTFTemplate and their problem comming from taht.
Name of your field must respect a syntax. For instance to display the value of JAVA object Project :
public class Project { private String name; public Project(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
putted into context with key project :
context.put("project", new Project("Jakarta Velocity"));
name of the field must be nammed in your RTF model like this :
$project.Name
You can use java.util.Map if you don't want use POJO object (works only with Velocity). Map key is the getter name, and Map value is the value getter. Project POJO sample can be done with Map like this :
// Prepare Project context Map projectMap = new HashMap(); projectMap.put("Name", "Jakarta Velocity"); // Put the Map into the context context.put("project", projectMap);
ATTENTION, it's important to respect the case in the key of the Map and the name of filed used into RTF model.
You can find samples here.
Display of simple value is done when JAVA object have getter type of :
It's possible to format value returned by getters by creating class which implement java.text.Format interface. Formatter class is linked to a class type.
For instance, to format all getters type of java.util.Date with dd/MM/yyyy pattern, you must set into rtftemplate instance with setDefaultFormat method, the formatter for java.util.Date class type like this :
Format format = new SimpleDateFormat("dd/MM/yyyy"); rtfTemplate.setDefaultFormat(java.util.Date.class, format);
By default RTFtemplate register formatters :
IRTFCode interface is particular RTFTemplate object type. Here IRTFCode signature :
public interface IRTFCode { /** * Return true if content must be escaped * (replace '{' character with "\{" and '}' with "\}") * @return */ public boolean isEscaped(); /** * Return RTF content. * @return */ public String getContent(); }
IRTFcode is used like JAVA primitif type into RTF model. If you put your IRTFCode object into context with myRTFCode key, you must call your merge field like this :
$myRTFCode
and NOT like this :
$myRTFCode.content
By default RTFTemplate provides net.sourceforge.rtf.format.rtfcode.RTFCodeString class which implements IRTFcode. It is linked to net.sourceforge.rtf.format.DefaultRTFCodeStringFormat formatter. Here formatteur code :
package net.sourceforge.rtf.format; import java.text.FieldPosition; import java.text.Format; import java.text.ParsePosition; import net.sourceforge.rtf.format.rtfcode.IRTFCode; import net.sourceforge.rtf.util.StringUtils; public class DefaultRTFCodeStringFormat extends Format { public StringBuffer format(Object obj, StringBuffer stringbuffer, FieldPosition fieldposition) { if (obj == null) return null; String content = null; if (obj instanceof IRTFCode) content = ((IRTFCode) obj).getContent(); else if (obj instanceof String) content = (String) obj; if (content == null) return null; // Replace \n\r with \\par String formattedContent = StringUtils.sub(content, "\n\r", "\\par "); // Replace \n with \\par formattedContent = StringUtils.sub(formattedContent, "\n", "\\par "); // Replace \t with \\tab formattedContent = StringUtils.sub(formattedContent, "\t", "\\tab "); return new StringBuffer(formattedContent); } public Object parseObject(String s, ParsePosition parseposition) { // Do nothing return null; } }
If your getter can return tabulation (\t), (\n,\r) you should use RTFCodeString in order to transform thoses characters into RTF code :
If you put RTFCodeString instance into RTFTemplate context like this :
context.put("myRTFCode", new RTFCodeString("\n\n\t\r\nvalue\n\n"));
RTF code will be generated :
\par \par \tab \par value \par\par
to display tabulation,... correctly into your RTF model.
If your getter can return '{' or '}' character, you must escape it like this :
context.put("myRTFCode", new RTFCodeString("\n\n\t\r\nvalue\n\n{", true);
When you have data list, it's possible to display in your RTF model. Sometimes you want display your list into RTF table (which will generate sevenral rows), sometimes you want display your items of the list separated with , character.
Loop are often managed with bookmarks (BOOKMARK). It exist some exception with RTF table.
The rule used by RTFtemplate is to iterate on the first field list type found after a start loop. A field is list type, if his JAVA object linked is stored into a JAVA list (java.util.Collection, java.util.List,...).
If you use RTFTemplate.dot, when you select a field, you can see if the field is type list or not. If field is list type, it must be included between start and end loop.
To set a start/end loop, you must create (except some exception) bookmarkes like this :
For isntance if you want display the list of develpers separated with , characters :
Developer 1, Developer 2,
RTF model must be designed like this :
START_LOOP_1 $developers.Name , END_LOOP_1
Since 1.0.1-b10 version, the rule is NOT use start/end bookmarks to loop for rows of RTF table. RTFTemplate is able to detect RTF rows and iterate on the first field type of list found in the row of RTF Table.
You can find samples here.
If you use old version, you must distinguish following use cases.
RTF tables have some exceptions. Switch design of RTF table, start/end bookmarks are required or not.
------------------------------------------------ |$developers.Name | | | ------------------------------------------------
After merge, the RTF target is :
------------------------------------------------ |Developer 1 | | | ------------------------------------------------ |Developer 2 | | | ------------------------------------------------
------------------------------------------------ |Header row WHICH HAVE A STYLE | | | ------------------------------------------------ |$developers.Name | | | ------------------------------------------------
After merge, the RTF target is :
------------------------------------------------ |Header row WHICH HAVE A STYLE | | | ------------------------------------------------ |Developer 1 | | | ------------------------------------------------ |Developer 2 | | | ------------------------------------------------
Since 1.0.1-b10 version, you can ignore this case.
When your RTF table is composed with header row WHICH HAVE NOT A STYLE and row which contains field (type list) :
------------------------------------------------ |Header row WHICH HAVE NOT A STYLE | | | START_LO0P_1 ------------------------------------------------ |$developers.Name | | | END_LO0P_1 ------------------------------------------------
After merge, the RTF target is :
------------------------------------------------ |Header row WHICH HAVE NOT A STYLE | | | ------------------------------------------------ |Developer 1 | | | ------------------------------------------------ |Developer 2 | | | ------------------------------------------------
Another use cases described below are sample to show what we can do with RTFTemplate :
MyTitle ------------------------------------------------ |Developer 1 | | | ------------------------------------------------ MyTitle ------------------------------------------------ |Developer 2 | | | ------------------------------------------------
You must design your RTF model like this :
START_LOOP_1 MyTitle ------------------------------------------------ |$developers.Name | | | ------------------------------------------------ END_LOOP_1
---------------------------------------------------------- |Developer 1, Developer 2 | | | ----------------------------------------------------------
You must design your RTF model like this :
---------------------------------------------------------- | START_LOOP_1 $developers.Name , END_LOOP_1 | | | ----------------------------------------------------------
With RTFTemplate you can insert images (which could be dynamicly generated) in your RTF model. To set the image in your RTF model, use a merge field. The JAVA object linked with the merge field must returns the InpuStream of the image to insert.
Image formats supported by RTFtemplate are PNG, JPG, EMF et BPM.
You can found samples with RTF model which manage images into rtftemplate-usecases-<version> distribution into the folder usecases/model/image. and JAVA classes into the package net.sourceforge.rtf.usecases.image.
With RTFTemplate it's possible to iterate on items of list and add a page break after each item. RTFTemplate don't generate a page break after the last item (to avoid to have a blank page).
To manage page break, you must design your RTF model like this :
START_LOOP_1 (set at start of your RTF model) .... $developers.Name .... Page break END_LOOP_1
It's possible to group items of the list and generate a page break after each group. You can do that with JAVA code. For more information click here.
You can found samples with RTF model which manage page break into rtftemplate-usecases-<version> distribution into the folder usecases/model/page. and JAVA classes into the package net.sourceforge.rtf.usecases.page.
With MS Word it's possible to create user properties. To do that, you must go to the menu File/Properties. In Customization tab, you can create your user properties (name, type, value).
You can manage user properties with RTFTemplatre like merge field :
You can found samples with RTF model which manage images into rtftemplate-usecases-<version> distribution into the folder usecases/model/jakartavelocityproject. and JAVA classes into the package net.sourceforge.rtf.usecases.userproperties.