Destiny template system

Version 0.7
4/19/1999

java package com.destinysoftware.templates

new since the last version / new last time / old stuff

Overview
Example
Tag Vocabulary
Design Issues
Changes

This is an HTML template system for dynamic HTML content generation in java. It separates the HTML from java objects by providing a flexible pseudo-tag system for referencing java objects from the HTML template. It is not a java library for the generation of HTML. Even though this is the web, it still makes sense to build an application around an object model that describes a domain, and it is still desireable to separate this application from a particular user interface technology, particularly HTML. This system provides part of the foundation of a system that lets the front end to adapt to the application rather than the other way around.

Overview

An HTML template is a portion of HTML that contains special tags for the template system. Templates can be anything from one entire page to a single word. Templates are compiled at "startup" time and stored as hierarchical collections of java objects which model the behavior of the various pseudo-tags that comprise the template vocabulary. This allows efficient HTML construction as needed.

An HTML template contains special tags that reference the fields of a java object by name. The tags are of two kinds: atomic tags, such as <Field varname> which will substitute the tag with the result of varname.toString() in java; and collections, such as <List varname> .... </List> which expects varname to support the java method Enumeration elements() and process the stuff between the List tags for each element of the collection varname.

This dynamic lookup and execution is done via the java.lang.reflect package which allows the java object to remain independent of the templatization system - there are no object model or interface constraints.

Example

The out of date example "templateTest" demonstrates the basic features using the HTML template ttest.html. To run it, set your classpath to this directory (template system) and run the demo with "java templateTest". It is illustrated in some detail in example.html.

Tag vocabulary

All, Count, DElementField, DField, ElementField, EncodeHTML, Field, Include, IncludeIf, Insert, InvokeMethod, List, Name, RInput, UseContext, Value, XL Templatization is done within a context, that is, tags which reference objects find them within the current context. A context may either be a general java object or a java.util.Dictionary subclass (such as Hashtable). Phrases such as "gets the named object" generally also implies that and the results of its toString() method is inserted into the output. Tag names are case-insensitive; the italics R_ prefix on tag names indicates it is optional (both names with and without are in the default tag name dictionary).

The tags <RInput> and <XL> are different from the rest in that a) they produce HTML tags as output and b) except for the few attributes they know, attributes are "passed through" to the output tag. They provide an attribute tag which specifies the HTML tag name to use.

Changes since 0.6

  1. currentKey added to mergeInfo, set by <List> and <XL> when enumerating a java.util.Dictionary. mergeInfo is becoming a garbage can and will be "transparently" restructured soon.

  2. <Name> (com.destinysoftware.templates.Name) now uses mergeInfo.currentKey if mergeInfo.currentItemCount >= 0, that is, if we are counting the list. This is superceded by..

  3. new tag <Key>, class com.destinysoftware.templates.Key, valid within <List> or <XL>

  4. <Count>, class com.destinysoftware.templates.Count, valid within <List> or <XL>

Changes since 0.5

  1. added java classes com.destinysoftware.templates.input and com.destinysoftware.templates.compositeList. Added to the templateParser default vocabulary as "RInput" and "XL" respectively. Input is a subclass of ObjectField (<Field>) and acts accordingly.

  2. the attribute parsing method of class com.destinysoftware.templates.field (superclass of ObjectField and DictionaryField) modified to invoke setAttribute() so it can be extended, as imput and compositeList required. But since it parses for the syntax "a.b" meaning field b of field a, when this is found, it presumes that when there is a b component, that field.subFieldName should be set to it. setAttribute(String, String) possibly should be modified to be setAttribute(String, String[])

Changes since 0.4

  1. tag class all creates a "big string" -- templateParser.loadDefaultClasses() adds this as "All".
  2. class htmlEncode -- templateParser.loadDefaultClasses() adds this as "EncodeHTML". implements the new abstract class transform for doing such things, even postprocessing the output of other tags.
  3. mergeInfo: methods are looked up by java.lang.Class.getMethod() instead of getDeclaredMethod()
  4. mergeInfo: fields are looked up by java.lang.Class.getField() instead of getDeclaredField()

Changes since 0.3

  1. Prefix restriction of "R_" is removed. Trie is used for parsing
  2. tags support named attributes in the style of HTML or XML. this is the recommended use; see the above template vocabulary
  3. default tag vocabulary has been split into two groups; one the recommended set and its variations, the other the original set defined by Destiny's Granite Foundation way back when; they are invoked by templateParser.loadDefaultClasses() and templateParser.loadOriginalVocabulary() respectively.
  4. templateObject is responsible for parsing the attribute list. templateObjects like ObjectField can override the parsing of the attribute value, for example, to avoid rescanning.
  5. mergeInfo can be told whether it should be treat the current object as a java.util.Dictionary or a generic object
  6. new tag functionality:
  7. the class Trie has been slightly modified (access method added)

Changes since 0.2

  1. moved to package com.destinysoftware.templates
  2. added tag <R_DField x>, the equivalent of <R_Field> (and <R_TEXT>) for getting x from within a java.util.Dictionary. This is the templateObject class DictionaryField
  3. added tag <R_DElementField x> ; in a List of Dictinary objects, this gets x from the Dictionary. for example

<R_List theList> <R_DElementField a> </R_List>

could be used for this code:

Vector theList;
Hashtable h1, h2;

h1.add("a", "hey!");
h2.add("a", "yow!");

theList.add(h1);
theList.add(h2);

would simply display "hey! yow!".

Changes since 0.1

  1. Classes renamed: StringVar is now ObjectField, Call is now ElementField
  2. class ElementField (tag <R_CALL varname>) is implemented. This tag is valid only inside an R_LIST or R_CLIST which returns the toString() of a field of an element object in the collection. It's called R_CALL for backwards reasons, and I will also provide an additional and more appropriate tag name like I've done with <R_SessionID> (better than <APPID>).
  3. Tag names are now case insensitive, that is <R_TEXT x> is equivalent to <R_Text x>. This is done by storing objectTemplate Class objects by uppercase key names, and converting parsed tag names to uppercase prior to lookup.
  4. more javadoc documentation

Russell Holt
March, April 1999