Class 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. StringTemplate ignores everything outside of attribute expressions, treating it as just text to spit out when you call StringTemplate.toString().
    • Field Detail

      • ANONYMOUS_ST_NAME

        public static final java.lang.String ANONYMOUS_ST_NAME
        See Also:
        Constant Field Values
      • referencedAttributes

        protected java.util.List referencedAttributes
      • name

        protected java.lang.String name
        What's the name of this template?
      • templateID

        protected int templateID
      • enclosingInstance

        protected StringTemplate enclosingInstance
        Enclosing instance if I'm embedded within another template. IF-subtemplates are considered embedded as well.
      • argumentContext

        protected java.util.Map argumentContext
        If this template is an embedded template such as when you apply a template to an attribute, then the arguments passed to this template represent the argument context--a set of values computed by walking the argument assignment list. For example, would result in an argument context of {[item=name], [foo="x"]} for this template. This template would be the bold() template and the enclosingInstance would point at the template that held that template call. When you want to get an attribute value, you first check the attributes for the 'self' template then the arg context then the enclosingInstance like resolving variables in pascal-like language with nested procedures. With multi-valued attributes such as attribute "i" is set to 1..n.
      • argumentsAST

        protected StringTemplateAST argumentsAST
        If this template is embedded in another template, the arguments must be evaluated just before each application when applying template to a list of values. The "it" attribute must change with each application so that $names:bold(item=it)$ works. If you evaluate once before starting the application loop then it has a single fixed value. Eval.g saves the AST rather than evaluating before invoking applyListOfAlternatingTemplates(). Each iteration of a template application to a multi-valued attribute, these args are re-evaluated with an initial context of {[it=...], [i=...]}.
      • formalArguments

        protected java.util.LinkedHashMap formalArguments
        When templates are defined in a group file format, the attribute list is provided including information about attribute cardinality such as present, optional, ... When this information is available, rawSetAttribute should do a quick existence check as should the invocation of other templates. So if you ref bold(item="foo") but item is not defined in bold(), then an exception should be thrown. When actually rendering the template, the cardinality is checked. This is a Map.
      • numberOfDefaultArgumentValues

        protected int numberOfDefaultArgumentValues
        How many formal arguments to this template have default values specified?
      • passThroughAttributes

        protected boolean passThroughAttributes
        Normally, formal parameters hide any attributes inherited from the enclosing template with the same name. This is normally what you want, but makes it hard to invoke another template passing in all the data. Use notation now: to say "pass in all data". Works great. Can also say
      • nativeGroup

        protected StringTemplateGroup nativeGroup
        What group originally defined the prototype for this template? This affects the set of templates I can refer to. super.t() must always refer to the super of the original group. group base; t ::= "base"; group sub; t ::= "super.t()2" group subsub; t ::= "super.t()3"
      • group

        protected StringTemplateGroup group
        This template was created as part of what group? Even if this template was created from a prototype in a supergroup, its group will be the subgroup. That's the way polymorphism works.
      • groupFileLine

        protected int groupFileLine
        If this template is defined within a group file, what line number?
      • pattern

        protected java.lang.String pattern
        The original, immutable pattern/language (not really used again after initial "compilation", setup/parsing).
      • attributes

        protected java.util.Map attributes
        Map an attribute name to its value(s). These values are set by outside code via st.setAttribute(name, value). StringTemplate is like self in that a template is both the "class def" and "instance". When you create a StringTemplate or setTemplate, the text is broken up into chunks (i.e., compiled down into a series of chunks that can be evaluated later). You can have multiple
      • attributeRenderers

        protected java.util.Map attributeRenderers
        A Map that allows people to register a renderer for a particular kind of object to be displayed in this template. This overrides any renderer set for this template's group. Most of the time this map is not used because the StringTemplateGroup has the general renderer map for all templates in that group. Sometimes though you want to override the group's renderers.
      • chunks

        protected java.util.List chunks
        A list of alternating string and ASTExpr references. This is compiled to when the template is loaded/defined and walked to write out a template instance.
      • regionDefType

        protected int regionDefType
        If someone refs <@r()> in template t, an implicit
      • isRegion

        protected boolean isRegion
        Does this template come from a <@region>...<@end> embedded in another template?
      • regions

        protected java.util.Set regions
        Set of implicit and embedded regions for this template
    • 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
      • StringTemplate

        public StringTemplate​(StringTemplateGroup group,
                              java.lang.String template,
                              java.util.HashMap attributes)
    • 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.
      • dup

        protected void dup​(StringTemplate from,
                           StringTemplate to)
        Make the 'to' template look exactly like the 'from' template except for the attributes. This is like creating an instance of a class in that the executable code is the same (the template chunks), but the instance data is blank (the attributes). Do not copy the enclosingInstance pointer since you will want this template to eval in a context different from the examplar.
      • 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.
      • getOutermostEnclosingInstance

        public StringTemplate getOutermostEnclosingInstance()
      • setEnclosingInstance

        public void setEnclosingInstance​(StringTemplate enclosingInstance)
      • getArgumentContext

        public java.util.Map getArgumentContext()
      • setArgumentContext

        public void setArgumentContext​(java.util.Map ac)
      • getName

        public java.lang.String getName()
      • getOutermostName

        public java.lang.String getOutermostName()
      • setName

        public void setName​(java.lang.String name)
      • getGroupFileLine

        public int getGroupFileLine()
        Return the outermost template's group file line number
      • setGroupFileLine

        public void setGroupFileLine​(int groupFileLine)
      • setTemplate

        public void setTemplate​(java.lang.String template)
      • getTemplate

        public java.lang.String getTemplate()
      • 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. This will be a new list object so that incoming objects are not altered. If you send in an array, it is converted to an ArrayIterator.
      • 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)
      • setAttribute

        protected void setAttribute​(java.lang.String aggrSpec,
                                    java.lang.Object[] values)
        Create an aggregate from the list of properties in aggrSpec and fill with values from values array. This is not publically visible because it conflicts semantically with setAttribute("foo",new Object[] {...});
      • parseAggregateAttributeSpec

        protected java.lang.String parseAggregateAttributeSpec​(java.lang.String aggrSpec,
                                                               java.util.List properties)
        Split "aggrName.{propName1,propName2}" into list [propName1,propName2] and the aggrName. Space is allowed around ','.
      • rawSetAttribute

        protected 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 self's specific template and a formal argument list exists.
      • rawSetArgumentAttribute

        public void rawSetArgumentAttribute​(StringTemplate embedded,
                                            java.util.Map attributes,
                                            java.lang.String name,
                                            java.lang.Object value)
        Argument evaluation such as foo(x=y), x must be checked against foo's argument list not this's (which is the enclosing context). So far, only eval.g uses arg self as something other than "this".
      • 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 four 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) 4. if nothing is found in the enclosing instance chain, then it might be a map defined in the group or the its supergroup etc... 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 override functionality.
      • breakTemplateIntoChunks

        protected void breakTemplateIntoChunks()
        Walk a template, breaking it into a list of chunks: Strings and actions/expressions.
      • 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)
      • getFormalArguments

        public java.util.Map getFormalArguments()
      • setFormalArguments

        public void setFormalArguments​(java.util.LinkedHashMap args)
      • setDefaultArgumentValues

        public void setDefaultArgumentValues()
        Set any default argument values that were not set by the invoking template or by setAttribute directly. Note that the default values may be templates. Their evaluation context is the template itself and, hence, can see attributes within the template, any arguments, and any values inherited by the template. Default values are stored in the argument context rather than the template attributes table just for consistency's sake.
      • 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)
      • defineFormalArguments

        public void defineFormalArguments​(java.util.List names)
      • defineFormalArgument

        public void defineFormalArgument​(java.lang.String name,
                                         StringTemplate defaultValue)
      • setPassThroughAttributes

        public void setPassThroughAttributes​(boolean passThroughAttributes)
        Normally if you call template y from x, y cannot see any attributes of x that are defined as formal parameters of y. Setting this passThroughAttributes to true, will override that and allow a template to see through the formal arg list to inherited values.
      • setAttributeRenderers

        public void setAttributeRenderers​(java.util.Map renderers)
        Specify a complete map of what object classes should map to which renderer objects.
      • registerRenderer

        public void registerRenderer​(java.lang.Class attributeClassType,
                                     AttributeRenderer renderer)
        Register a renderer for all objects of a particular type. This overrides any renderer set in the group for this class type.
      • getAttributeRenderer

        public AttributeRenderer getAttributeRenderer​(java.lang.Class attributeClassType)
        What renderer is registered for this attributeClassType for this template. If not found, the template's group is queried.
      • error

        public void error​(java.lang.String msg)
      • warning

        public void warning​(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()
      • trackAttributeReference

        protected void trackAttributeReference​(java.lang.String name)
        Indicates that 'name' has been referenced in this template.
      • 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()
      • getTemplateHeaderString

        protected java.lang.String getTemplateHeaderString​(boolean showAttributes)
      • checkNullAttributeAgainstFormalArguments

        protected void checkNullAttributeAgainstFormalArguments​(StringTemplate self,
                                                                java.lang.String attribute)
        A reference to an attribute with no value, must be compared against the formal parameter to see if it exists; if it exists all is well, but if not, throw an exception. Don't do the check if no formal parameters exist for this template; ask enclosing.
      • checkForTrouble

        protected void checkForTrouble()
        Executed after evaluating a template. For now, checks for setting of attributes not reference.
      • getEnclosingInstanceStackString

        public java.lang.String getEnclosingInstanceStackString()
        If an instance of x is enclosed in a y which is in a z, return a String of these instance names in order from topmost to lowest; here that would be "[z y x]".
      • isRegion

        public boolean isRegion()
      • setIsRegion

        public void setIsRegion​(boolean isRegion)
      • addRegionName

        public void addRegionName​(java.lang.String name)
      • containsRegionName

        public boolean containsRegionName​(java.lang.String name)
        Does this template ref or embed region name?
      • getRegionDefType

        public int getRegionDefType()
      • setRegionDefType

        public void setRegionDefType​(int regionDefType)
      • toDebugString

        public java.lang.String toDebugString()
      • toStructureString

        public java.lang.String toStructureString()
        Don't print values, just report the nested structure with attribute names. Follow (nest) attributes that are templates only.
      • toStructureString

        public java.lang.String toStructureString​(int indent)
      • getDOTForDependencyGraph

        public StringTemplate getDOTForDependencyGraph​(boolean showAttributes)
        Generate a DOT file for displaying the template enclosure graph; e.g., digraph prof { "t1" -> "t2" "t1" -> "t3" "t4" -> "t5" }
      • getDependencyGraph

        public void getDependencyGraph​(java.util.Map edges,
                                       boolean showAttributes)
        Get a list of n->m edges where template n contains template m. The map you pass in is filled with edges: key->value. Useful for having DOT print out an enclosing template graph. It finds all direct template invocations too like but not indirect ones like <(name)()>. Ack, I just realized that this is done statically and hence cannot see runtime arg values on statically included templates. Hmm...someday figure out to do this dynamically as if we were evaluating the templates. There will be extra nodes in the tree because we are static like method and method[...] with args.
      • putToMultiValuedMap

        protected void putToMultiValuedMap​(java.util.Map map,
                                           java.lang.Object key,
                                           java.lang.Object value)
        Manage a hash table like it has multiple unique values. Map.
      • printDebugString

        public void printDebugString()
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • toString

        public java.lang.String toString​(int lineWidth)