org.antlr.stringtemplate
Class StringTemplate

java.lang.Object
  extended byorg.antlr.stringtemplate.StringTemplate

public class StringTemplate
extends java.lang.Object

A StringTemplate is a "document" with holes in it where you can stick values. StringTemplate breaks up your template into chunks of text and attribute expressions, which are by default enclosed in angle brackets: <attribute-expression>. StringTemplate ignores everything outside of attribute expressions, treating it as just text to spit out when you call StringTemplate.toString().

StringTemplate is not a "system" or "engine" or "server"; it's a lib rary with two classes of interest: StringTemplate and StringTemplat eGroup. You can directly create a StringTemplate in Java code or you can load a template from a file.

A StringTemplate describes an output pattern/language like an exemplar.

StringTemplate and associated code is released under the BSD licence. See source.

Copyright (c) 2003-2005 Terence Parr

A particular instance of a template may have a set of attributes that you set programmatically. A template refers to these single or multi- valued attributes when writing itself out. References within a template conform to a simple language with attribute references and references to other, embedded, templates. The references are surrounded by user-defined start/stop strings (default of <...>, but $...$ works well when referencing attributes in HTML to distinguish from tags).

StringTemplateGroup is a self-referential group of StringTemplate objects kind of like a grammar. It is very useful for keeping a group of templates together. For example, jGuru.com's premium and guest sites are completely separate sets of template files organized with a StringTemplateGroup. Changing "skins" is a simple matter of switching groups. Groups know where to load templates by either looking under a rootDir you can specify for the group or by simply looking for a resource file in the current class path. If no rootDir is specified, template files are assumed to be resources. So, if you reference template foo() and you have a rootDir, it looks for file rootDir/foo.st. If you don't have a rootDir, it looks for file foo.st in the CLASSPATH. note that you can use org/antlr/misc/foo() (qualified template names) as a template ref.

StringTemplateErrorListener is an interface you can implement to specify where StringTemplate reports errors. Setting the listener for a group automatically makes all associated StringTemplate objects use the same listener. For example,

  StringTemplateGroup group = new StringTemplateGroup("loutSyndiags");
  group.setErrorListener(
     new StringTemplateErrorListener() {
        public void error(String msg, Exception e) {
           System.err.println("StringTemplate error: "+
               msg+((e!=null)?": "+e.getMessage():""));
        }
    }
  );
  

IMPLEMENTATION

A StringTemplate is both class and instance like in Self. Given any StringTemplate (even one with attributes filled in), you can get a new "blank" instance of it.

When you define a template, the string pattern is parsed and broken up into chunks of either String or attribute/template actions. These are typically just attribute references. If a template is embedded within another template either via setAttribute or by implicit inclusion by referencing a template within a template, it inherits the attribute scope of the enclosing StringTemplate instance. All StringTemplate instances with the same pattern point to the same list of chunks since they are immutable there is no reason to have a copy in every instance of that pattern. The only thing that differs is that every StringTemplate Java object can have its own set of attributes. Each chunk points back at the original StringTemplate Java object whence they were constructed. So, there are multiple pointers to the list of chunks (one for each instance with that pattern) and only one back ptr from a chunk to the original pattern object. This is used primarily to get the grcoup of that original so new templates can be loaded into that group.

To write out a template, the chunks are walked in order and asked to write themselves out. String chunks are obviously just written out, but the attribute expressions/actions are evaluated in light of the attributes in that object and possibly in an enclosing instance.


Nested Class Summary
static class StringTemplate.Aggregate
          An automatically created aggregate of properties.
 
Field Summary
static java.lang.String VERSION
           
 
Constructor Summary
StringTemplate()
          Create a blank template with no pattern and no attributes
StringTemplate(java.lang.String template)
          Create an anonymous template.
StringTemplate(java.lang.String template, java.lang.Class lexer)
           
StringTemplate(StringTemplateGroup group, java.lang.String template)
          Create an anonymous template with no name, but with a group
 
Method Summary
 void addChunk(Expr e)
           
 void addEmbeddedInstance(StringTemplate embeddedInstance)
           
 void debug(java.lang.String msg)
           
 void defineEmptyFormalArgumentList()
           
 void defineFormalArgument(java.lang.String name)
           
 void error(java.lang.String msg)
           
 void error(java.lang.String msg, java.lang.Throwable e)
           
 java.lang.Object get(StringTemplate self, java.lang.String attribute)
          Resolve an attribute reference.
 java.util.Map getArgumentContext()
           
 StringTemplateAST getArgumentsAST()
           
 java.lang.Object getAttribute(java.lang.String name)
           
 java.util.Map getAttributes()
           
 java.util.List getChunks()
          Get a list of the strings and subtemplates and attribute refs in a template.
 StringTemplate getEnclosingInstance()
           
 java.lang.String getEnclosingInstanceStackTrace()
           
 StringTemplateErrorListener getErrorListener()
           
 FormalArgument getFormalArgument(java.lang.String name)
           
 java.util.Map getFormArguments()
           
 StringTemplateGroup getGroup()
           
 StringTemplate getInstanceOf()
          Make an instance of this template; it contains an exact copy of everything (except the attributes and enclosing instance pointer).
 java.lang.String getName()
           
 java.lang.String getOutermostName()
           
 java.lang.String getTemplate()
           
 java.lang.String getTemplateDeclaratorString()
           
 int getTemplateID()
           
static boolean inLintMode()
           
static boolean isDebugMode()
           
static boolean isRecursiveEnclosingInstance(StringTemplate st)
          Look up the enclosing instance chain (and include this) to see if st is a template already in the enclosing instance chain.
 FormalArgument lookupFormalArgument(java.lang.String name)
          From this template upward in the enclosing template tree, recursively look for the formal parameter.
 ASTExpr parseAction(java.lang.String action)
           
 void printDebugString()
           
 void rawSetAttribute(java.util.Map attributes, java.lang.String name, java.lang.Object value)
          Map a value to a named attribute.
 void removeAttribute(java.lang.String name)
           
 void reset()
           
static void resetTemplateCounter()
          reset the template ID counter to 0; public so that testing routine can access but not really of interest to the user.
 void setArgumentContext(java.util.Map ac)
           
 void setArgumentsAST(StringTemplateAST argumentsAST)
           
 void setAttribute(java.lang.String name, int value)
          Convenience method to box ints
 void setAttribute(java.lang.String name, java.lang.Object value)
          Set an attribute for this template.
 void setAttribute(java.lang.String aggrSpec, java.lang.Object v1, java.lang.Object v2)
          Set an aggregate attribute with two values.
 void setAttribute(java.lang.String aggrSpec, java.lang.Object v1, java.lang.Object v2, java.lang.Object v3)
           
 void setAttribute(java.lang.String aggrSpec, java.lang.Object v1, java.lang.Object v2, java.lang.Object v3, java.lang.Object v4)
           
 void setAttribute(java.lang.String aggrSpec, java.lang.Object v1, java.lang.Object v2, java.lang.Object v3, java.lang.Object v4, java.lang.Object v5)
           
 void setAttributes(java.util.Map attributes)
           
static void setDebugMode(boolean debug)
          DEBUG MODE IS PRETTY MUCH USELESS AT THE MOMENT!
 void setEnclosingInstance(StringTemplate enclosingInstance)
           
 void setErrorListener(StringTemplateErrorListener listener)
           
 void setFormalArguments(java.util.Map args)
           
 void setGroup(StringTemplateGroup group)
           
static void setLintMode(boolean lint)
          Make StringTemplate check your work as it evaluates templates.
 void setName(java.lang.String name)
           
 void setPredefinedAttributes()
           
 void setTemplate(java.lang.String template)
           
 java.lang.String toDebugString()
          UNUSED
 java.lang.String toString()
           
 void warning(java.lang.String msg)
           
 int write(StringTemplateWriter out)
          Walk the chunks, asking them to write themselves out according to attribute values of 'this.attributes'.
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

VERSION

public static final java.lang.String VERSION
See Also:
Constant Field Values
Constructor Detail

StringTemplate

public StringTemplate()
Create a blank template with no pattern and no attributes


StringTemplate

public StringTemplate(java.lang.String template)
Create an anonymous template. It has no name just chunks (which point to this anonymous template) and attributes.


StringTemplate

public StringTemplate(java.lang.String template,
                      java.lang.Class lexer)

StringTemplate

public StringTemplate(StringTemplateGroup group,
                      java.lang.String template)
Create an anonymous template with no name, but with a group

Method Detail

resetTemplateCounter

public static void resetTemplateCounter()
reset the template ID counter to 0; public so that testing routine can access but not really of interest to the user.


getInstanceOf

public StringTemplate getInstanceOf()
Make an instance of this template; it contains an exact copy of everything (except the attributes and enclosing instance pointer). So the new template refers to the previously compiled chunks of this template but does not have any attribute values.


getEnclosingInstance

public StringTemplate getEnclosingInstance()

setEnclosingInstance

public void setEnclosingInstance(StringTemplate enclosingInstance)

addEmbeddedInstance

public void addEmbeddedInstance(StringTemplate embeddedInstance)

getArgumentContext

public java.util.Map getArgumentContext()

setArgumentContext

public void setArgumentContext(java.util.Map ac)

getArgumentsAST

public StringTemplateAST getArgumentsAST()

setArgumentsAST

public void setArgumentsAST(StringTemplateAST argumentsAST)

getName

public java.lang.String getName()

getOutermostName

public java.lang.String getOutermostName()

setName

public void setName(java.lang.String name)

getGroup

public StringTemplateGroup getGroup()

setGroup

public void setGroup(StringTemplateGroup group)

setTemplate

public void setTemplate(java.lang.String template)

getTemplate

public java.lang.String getTemplate()

setErrorListener

public void setErrorListener(StringTemplateErrorListener listener)

getErrorListener

public StringTemplateErrorListener getErrorListener()

reset

public void reset()

setPredefinedAttributes

public void setPredefinedAttributes()

removeAttribute

public void removeAttribute(java.lang.String name)

setAttribute

public void setAttribute(java.lang.String name,
                         java.lang.Object value)
Set an attribute for this template. If you set the same attribute more than once, you get a multi-valued attribute. If you send in a StringTemplate object as a value, it's enclosing instance (where it will inherit values from) is set to 'this'. This would be the normal case, though you can set it back to null after this call if you want. If you send in a List plus other values to the same attribute, they all get flattened into one List of values. If you send in an array, it is converted to a List. Works with arrays of objects and arrays of {int,float,double}.


setAttribute

public void setAttribute(java.lang.String name,
                         int value)
Convenience method to box ints


setAttribute

public void setAttribute(java.lang.String aggrSpec,
                         java.lang.Object v1,
                         java.lang.Object v2)
Set an aggregate attribute with two values. The attribute name must have the format: "name.{propName1,propName2}".


setAttribute

public void setAttribute(java.lang.String aggrSpec,
                         java.lang.Object v1,
                         java.lang.Object v2,
                         java.lang.Object v3)

setAttribute

public void setAttribute(java.lang.String aggrSpec,
                         java.lang.Object v1,
                         java.lang.Object v2,
                         java.lang.Object v3,
                         java.lang.Object v4)

setAttribute

public void setAttribute(java.lang.String aggrSpec,
                         java.lang.Object v1,
                         java.lang.Object v2,
                         java.lang.Object v3,
                         java.lang.Object v4,
                         java.lang.Object v5)

rawSetAttribute

public void rawSetAttribute(java.util.Map attributes,
                            java.lang.String name,
                            java.lang.Object value)
Map a value to a named attribute. Throw NoSuchElementException if the named attribute is not formally defined in this specific template and a formal argument list exists. This is public because eval.g needs to use it. :(


getAttribute

public java.lang.Object getAttribute(java.lang.String name)

write

public int write(StringTemplateWriter out)
          throws java.io.IOException
Walk the chunks, asking them to write themselves out according to attribute values of 'this.attributes'. This is like evaluating or interpreting the StringTemplate as a program using the attributes. The chunks will be identical (point at same list) for all instances of this template.

Throws:
java.io.IOException

get

public java.lang.Object get(StringTemplate self,
                            java.lang.String attribute)
Resolve an attribute reference. It can be in three possible places: 1. the attribute list for the current template 2. if self is an embedded template, somebody invoked us possibly with arguments--check the argument context 3. if self is an embedded template, the attribute list for the enclosing instance (recursively up the enclosing instance chain) Attribute references are checked for validity. If an attribute has a value, its validity was checked before template rendering. If the attribute has no value, then we must check to ensure it is a valid reference. Somebody could reference any random value like $xyz$; formal arg checks before rendering cannot detect this--only the ref can initiate a validity check. So, if no value, walk up the enclosed template tree again, this time checking formal parameters not attributes Map. The formal definition must exist even if no value. To avoid infinite recursion in toString(), we have another condition to check regarding attribute values. If your template has a formal argument, foo, then foo will hide any value available from "above" in order to prevent infinite recursion. This method is not static so people can overrided functionality.


parseAction

public ASTExpr parseAction(java.lang.String action)

getTemplateID

public int getTemplateID()

getAttributes

public java.util.Map getAttributes()

getChunks

public java.util.List getChunks()
Get a list of the strings and subtemplates and attribute refs in a template.


addChunk

public void addChunk(Expr e)

setAttributes

public void setAttributes(java.util.Map attributes)

getFormArguments

public java.util.Map getFormArguments()

setFormalArguments

public void setFormalArguments(java.util.Map args)

lookupFormalArgument

public FormalArgument lookupFormalArgument(java.lang.String name)
From this template upward in the enclosing template tree, recursively look for the formal parameter.


getFormalArgument

public FormalArgument getFormalArgument(java.lang.String name)

defineEmptyFormalArgumentList

public void defineEmptyFormalArgumentList()

defineFormalArgument

public void defineFormalArgument(java.lang.String name)

error

public void error(java.lang.String msg)

warning

public void warning(java.lang.String msg)

debug

public void debug(java.lang.String msg)

error

public void error(java.lang.String msg,
                  java.lang.Throwable e)

setLintMode

public static void setLintMode(boolean lint)
Make StringTemplate check your work as it evaluates templates. Problems are sent to error listener. Currently warns when you set attributes that are not used.


inLintMode

public static boolean inLintMode()

isDebugMode

public static boolean isDebugMode()

setDebugMode

public static void setDebugMode(boolean debug)
DEBUG MODE IS PRETTY MUCH USELESS AT THE MOMENT!


isRecursiveEnclosingInstance

public static boolean isRecursiveEnclosingInstance(StringTemplate st)
Look up the enclosing instance chain (and include this) to see if st is a template already in the enclosing instance chain.


getEnclosingInstanceStackTrace

public java.lang.String getEnclosingInstanceStackTrace()

getTemplateDeclaratorString

public java.lang.String getTemplateDeclaratorString()

toDebugString

public java.lang.String toDebugString()
UNUSED


printDebugString

public void printDebugString()

toString

public java.lang.String toString()