Introduction To Tek271 Template

A Java open source template library.

By Abdul Habra
Email ahabra@yahoo.com
URL www.tek271.com
Version  1.00
Date 2008.01.03

Downloads
This software is open source, free, and uses LGPL license.
tek271.template.2008.01.03.zip: Source, JAR, JavaDocs.
Java Docs.

Why?
Tek271 Template is a templating library with many features that are missing from most other templating libraries.
  1. Tag values can be assigned by name.
  2. Tag values can be assigned from a Java class properties or fields.
  3. Tag values can be assigned from a map object.
  4. Tag markers start and end (e.g. ${ and } ) are programmable.
  5. Supports an eval() function that can evaluate any Java expression.
  6. A template can include() other template files.
  7. A template can includeFromGroup(), which include portions from other template files.

The following sections show examples of different features.

1. A template with direct tag name access
/** A template example with direct tag name access */
public class Example01 extends TestCase {

  private static final String TEXT= 
    "Hello ${name}, your age is ${age}, and you look ${look}.";
  
  private static final String EXPECTED=
    "Hello Jane Doe, your age is 69, and you look bad.";
  
  public void test() throws IOException {
    Template template= new Template();
    template.initFromString(TEXT);
    
    template.setTagValue("name", "Jane Doe");
    template.setTagValue("age", 69);
    template.setTagValue("look", "bad");
    
    String t= template.toString();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows how to create a template object from a string and assign values to the tags by their name.

2. Using a Map for tag values
/** A template example using a Map for tag values */
public class Example02 extends TestCase {
  private static final String TEXT= 
    "Hello ${name}, your age is ${age}, and you look ${look}.";
  
  private static final String EXPECTED=
    "Hello Jane Doe, your age is 69, and you look good.";
  
  public void test() throws IOException {
    Template template= new Template();
    template.initFromString(TEXT);
    
    Map map= new HashMap();
    map.put("name", "Jane Doe");
    map.put("age", 69);
    map.put("look", "good");
    
    template.setAll(map);
    
    String t= template.toString();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows how to create a template object from a string and assign values to the tags from a map object using the setAll(Map) method.

3. Using a bean for tag values
/** A template example using a bean for tag values */
public class Example03 extends TestCase {
  private static final String TEXT= 
    "Hello ${name}, your age is ${age}, and you look ${look}.";

  private static final String EXPECTED=
    "Hello Jane Doe, your age is 69, and you look very bad.";
  
  /** This class must be public, but does not have to be an inner class */
  public static class Bean {
    private String name= "Jane Doe";
    private int age=69;
    public String look= "very bad";  // just a public field
    
    public String getName() { return name; }
    public void setName(String aName) { name= aName; }
    
    public int getAge() { return age; }
    public void setAge(int aAge) { age= aAge;}
  }
  
  public void test() throws IOException {
    Template template= new Template();
    template.initFromString(TEXT);
    
    Bean bean= new Bean();
    template.setAll(bean);
    
    String t= template.toString();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows how to create a template object from a string and assign values to the tags from a Java bean using the setAll(Object) method. Note that the bean object can expose either properties or just simple fields.

4. Using nested beans for tag values
/** Example using nested beans for tag values */
public class Example04 extends TestCase {
  private static final String TEXT=
    "Name is ${name}, addrss is " +
    "${address.street} - ${address.city}, and phone is ${address.telephones[0]}.";

  private static final String EXPECTED=
    "Name is Bill, addrss is 100 Main St - Tempville, and phone is 200.123.4444.";
  
  /** This class must be public, but does not have to be an inner class */
  public static class Address {
    public String street, city;
    public String[] telephones;
  }

  /** This class must be public, but does not have to be an inner class */
  public static class Person {
    public String name;
    public Address address= new Address();  // this could be a property get/set
  }
  
  public void test() throws IOException {
    Person p= new Person();
    p.name= "Bill";
    p.address.street= "100 Main St";
    p.address.city= "Tempville";
    p.address.telephones= new String[] {"200.123.4444", "200.123.5555"};
    
    Template template= new Template();
    template.initFromString(TEXT);
    template.setAll(p);

    String t= template.toString();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows:

  1. How to create a template object from a string.
  2. Assign values to the tags from a Java bean using the setAll(Object) method.
  3. Bean properties can refer to other other bean properties, e.g. ${address.street}.
  4. If a property is an array, it can be referenced by index, e.g. ${address.telephones[0]}.
5. Using the eval() function
/** Example using the eval() function. You can pass to eval() any valid Java expression.
 * IMPORTANT: When you use the eval() function, you must use the setAll() method to
 * set tag values. You cannot use the setTagValue() methods when using the eval()
 * function. **/
public class Example05 extends TestCase {
  private static final String TEXT= 
    "In Java the maximum Integer value is ${.eval(Integer.MAX_VALUE)}.\n" +
    "If your were born in ${dob} then your age is ${.eval(year-dob)}.";
  
  private static final String EXPECTED=
    "In Java the maximum Integer value is 2147483647.\n" +
    "If your were born in 1990 then your age is ?.";
  
  public void test() throws IOException {
    Template template= new Template();
    template.initFromString(TEXT);

    int dob= 1990;
    int year= Calendar.getInstance().get(Calendar.YEAR);
    Map map= new HashMap();
    map.put("dob", dob);
    map.put("year", year); 
    
    // IMPORTANT: When you use the eval() function, you must use the setAll() method to
    // set tag values. You cannot use the setTagValue() methods when using the eval()
    // function
    template.setAll(map);
    String t= template.getText();
    System.out.println(t);
    String exptected= Printf.p(EXPECTED, year-dob);
    assertEquals(exptected, t);
  }
}

The above example shows:

  1. How to create a template object from a string.
  2. Useing the eval() function to evaluate any valid Java expression. For example eval(Integer.MAX_VALUE) or eval(year-dob).
  3. When using the eval() function you should use the setAll() method to set tag values. You cannot use the setTagValue() methods. This restrictions is cause by the fact that the eval() function can use more that one variable which all need to be available during the evaluation.
6. Using a simple include
/** Example using a simple include */ 
public class Example06 extends TestCase {
  private static final String TEXT= 
    "Hello ${.include(Example06.inc.txt)}";
  // The file Example06.inc.txt contains:
  // World
  
  private static final String EXPECTED= "Hello World";
  
  public void test() throws IOException {
    // Create a template using the given path to included files directory
    Template template= new Template("examples/examples");
    template.initFromString(TEXT);

    String t= template.getText();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows:

  1. How to create a template using a given path as the root for included templates.
  2. Use the include() function in a template to include another file.
7. Using include with tags
/** Example using include with tags */
public class Example07 extends TestCase {
  private static final String TEXT= 
    "${name}'s copyright statement: ${.include(Example07.inc.txt)}";
    // The file Example07.inc.txt contains:
    // Copyright (c) ${year} - ${company}
  
  private static final String EXPECTED=
    "Abdul's copyright statement: Copyright (c) 2007 - Technology Exponent";
  
  public void test() throws IOException {
    Template template= new Template("examples/examples");
    template.initFromString(TEXT);

    Map map= new HashMap();
    map.put("name", "Abdul");
    map.put("year", 2007);
    map.put("company", "Technology Exponent");
    
    template.setAll(map);

    String t= template.getText();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows:

  1. How to create a template using a given path as the root for included templates.
  2. Use the include() function in a template to include another file.
  3. Use values that get assigned in the included text.
8. Using include with tags and a context parameter
/** Example using include with tags and a context parameter */
public class Example08 extends TestCase {
  private static final String TEXT=
    "${name} lives in ${.include(Example08.inc.txt, address)}";
    // The file Example08.inc.txt contains:
    // ${city}, ${state}.

  private static final String EXPECTED=
    "Abdul lives in Dayton, Ohio.";
  
  public void test() throws IOException {
    Template template= new Template("examples/examples");
    template.initFromString(TEXT);

    Map address= new HashMap();
    address.put("city", "Dayton");
    address.put("state", "Ohio");
    
    Map person= new HashMap();
    person.put("name", "Abdul");
    person.put("address", address);

    template.setAll(person);

    String t= template.getText();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows:

  1. How to create a template using a given path as the root for included templates.
  2. Use a different variation of the include() function in a template to include another file.
  3. The include() function takes a second parameter, which is called a "context parameter". This parameter is simply a map or a bean whose values will be used with the included file.
  4. Using this context parameter saves us from having to repeat it in the included file. For example, in the above code, if we did not use the address context parameter, the included text would have to be: ${address.city}, ${address.state}.
9. Using includeFromGroup
/** Example using includeFromGroup() */
public class Example09 extends TestCase {
  private static final String TEXT=
    "Header: ${.includeFromGroup(Example09.inc.group.txt, header)}\n" +
    "Footer: ${.includeFromGroup(Example09.inc.group.txt, footer)}";
  
    /* The file Example09.inc.group.txt contains:
       template header {<
       Welcome ${userName}
       >}

       template footer {< 
       Copyright (c) ${year} - ${company}
       >}
     */
  private static final String EXPECTED=
    "Header: Welcome Abdul\n" +
    "Footer: Copyright (c) 2007 - Technology Exponent";

  public void test() throws IOException {
    Template template= new Template("examples/examples");
    template.initFromString(TEXT);

    Map map= new HashMap();
    map.put("userName", "Abdul");
    map.put("company", "Technology Exponent");
    map.put("year", "2007");
    template.setAll(map);

    String t= template.getText();
    System.out.println(t);
    assertEquals(EXPECTED, t);
  }
}

The above example shows:

  1. How to create a template using a given path as the root for included templates.
  2. Using a template group file which can contain many template sections, each section can be included individually in a template file.
  3. In a template group file, each template section consists of
    template name {<
    whatever text ...
    <}
    The name of the section must be unique in the template group file
  4. The template group file is helpful to avoid creating many small include files.
Changes

Version 1.00, 2008.01.03
First public release

Comments



ċ
tek271.template.2008.01.03.zip
(2628k)
Abdul Habra,
Mar 28, 2011, 3:21 PM
Comments