ST (StringTemplate) is a java template engine (with ports for C#, Python, and Objective-C coming) for generating source code

Overview

ST (StringTemplate) is a java template engine (with ports for C#, Python, and Objective-C coming) for generating source code, web pages, emails, or any other formatted text output. ST is particularly good at multi-targeted code generators, multiple site skins, and internationalization / localization. It evolved over years of effort developing jGuru.com and then ANTLR v3.

Given day-job constraints, my time working on this project is limited so I'll have to focus first on fixing bugs rather than changing/improving the feature set. Likely I'll do it in bursts every few months. Please do not be offended if your bug or pull request does not yield a response! --parrt

The main website is:

http://www.stringtemplate.org

Its distinguishing characteristic is that it strictly enforces model-view separation, unlike other engines. See:

http://www.cs.usfca.edu/~parrt/papers/mvc.templates.pdf

The documentation is in this repo

https://github.com/antlr/stringtemplate4/tree/master/doc/index.md

Per the BSD license in LICENSE.txt, this software is not guaranteed to work and might even destroy all life on this planet.

INSTALLATION

Manual Installation

All you need to do is get the StringTemplate jar into your CLASSPATH. See Java StringTemplate.

Maven

To reference StringTemplate from a project built using Maven, add the following to the element in your pom.xml file.

<dependency>
  <groupId>org.antlrgroupId>
  <artifactId>ST4artifactId>
  <version>4.3version>
  <scope>compilescope>
dependency>

Gradle

In build.gradle, add the following dependency:

dependecies {
    // ...

    // https://mvnrepository.com/artifact/org.antlr/ST4
    compile group: 'org.antlr', name: 'ST4', version: '4.3'
}

Make sure you are using the mavenCentral repository by adding it if necessary:

repositories {
    // ...
    mavenCentral()
}

Other

Select a version on mvnrepository, and copy the snippet relevant to your build tool.

BUILDING FROM SOURCE

The source is at github.com:

https://github.com/antlr/stringtemplate4

If you would like to make changes to ST and build it yourself, just run mvn compile from the root directory of the repo.

You can also run ant from the root dir.

Comments
  • Thread safety issue

    Thread safety issue

    We use StringTemplate in multi-threaded configuration, where we create a single STGroup instance, and multiple threads call group.getInstanceOf and render.

    The problem is we (sometimes) get attribute XYZ isn't defined error, although the attribute XYZ (which is a map/dictionary template) is clearly defined in an imported template.

    My guess is that StringTemplate has thread safety issues when (but not limited to) a dictionary that is defined in an imported template file is accessed.

    I went over the source code and found a few places that potentially have thread safety issue.

    1. Lazy initialization of STGroup (STGroupFile) object. STGroupFile calls load() method lazily when necessary, so multiple thread can simultaneously initialize the object (which may or may not be a problem). I think probably load() should be synchronized.
    2. CompiledST object is being modified after added to the synchronized templates dictionary. For example, in STGroup.java in defineRegion method code.defineArgDefaultValueTemplates(this) and code.defineImplicitlyDefinedTemplates(this) is called after the invocation of the rawDefineTemplate method, which puts CompiledST object into the synchronized map. Thus another thread may see an incomplete CompiledST object.

    I did not check all the code, so there might be other places with thread safety issues. I made STGroup.getInstanceOf, STGroup.getEmbeddedInstanceOf, and ST.render to be synchronized with respect to the STGroup instance, and the attribute error went away. I suggest that those three methods to be synchronized; but also someone should go over all the code and check if any other thread-safety issue is there. Any code that does lazy evaluation should be examined for thread safety.

    type:bug status:not-fixing 
    opened by seojiwon 18
  • Attribute not made available to inner scopes

    Attribute not made available to inner scopes

    Given a hashmap 'var' added as an attribute to ST, and the following template.

    $["0","1"]:{ x |
       $x$
       $if(x)$y$endif$
       $if({$x$})$y$endif$
       $if(({$x$}))$z$endif$
    
       $var.(x)$
       $var.({$x$})$      $!  <---- error here !$
       $var.(({$x$}))$
    
       $if(var.(x))$OK$else$NO$endif$
       $if(var.({$x$}))$OK$else$NO$endif$    $!  <---- error here !$
       $if(var.(({$x$})))$OK$else$NO$endif$  $!  <---- error here !$
    }$
    

    I get the following errors (also marked out)

    context [/_sub4] 8:11 attribute x isn't defined
    context [/_sub6] 12:14 attribute x isn't defined
    context [/_sub7] 13:15 attribute x isn't defined
    

    This is a complete showstopper for me using v4 of stringtemplate. Is this easily fixable, and if possible, is there also currently a workaround for this?

    status:invalid 
    opened by magicl 14
  • Loading template group from STGroupDir in app running on Tomcat 8 fails

    Loading template group from STGroupDir in app running on Tomcat 8 fails

    StringTemplate version: 4.3.1

    I'm migrating a web application from Tomcat 7 to Tomcat 8. It appears something in the class loader behavior has changed between the versions.

    My app calls STGroupDir group = new STGroupDir("com/example/app/path/to/templates");

    When running on Tomcat 7, after the line root = cl.getResource(dirName); at STGroupDir.java:72 the variable root has the value

    jar:file:/path/to/exploded/app/WEB-INF/lib/my-component.jar!/com/example/app/path/to/templates

    Running on Tomcat 8, root has the value

    jar:file:/path/to/exploded/app/WEB-INF/lib/my-component.jar!/com/example/app/path/to/templates/

    My app then calls ST st = group.getInstanceOf("/TemplateGroup/someTemplate"); to load someTemplate from ...path/to/templates/TemplateGroup.stg.

    When load() calculates groupFileURL on line STGroupDir.java:128, the value is

    jar:file:/path/to/exploded/app/WEB-INF/lib/my-component.jar!/com/example/app/path/to/templates//TemplateName.stg

    The double slash prevents it from successfully loading the template group file, and getInstanceOf() returns null.

    type:bug 
    opened by Mooninaut 12
  • Loading templates in containers

    Loading templates in containers

    To facilitate getting this in I applied the patch attached to issue #191 and put in a pull request for it.

    I also built the jar and tested it with our external products; the patch fixed the issues without introducing others.

    Fixes #191

    type:enhancement 
    opened by drealeed 12
  • Test execution on Linux (*nix)

    Test execution on Linux (*nix)

    Currently test files are created using tmpdir + "dir" + randomValue.

    On Linux (and most other *nix systems like Mac OS) tmpdir mostly yields /tmp (note no trailing slash) and above concatenation results in e.g. /tmpdir0123456. However, regularly you do not have access rights to write directly in the filesystem root and thus several of the tests fail. Writing in /tmp/dir0123456 would work, tho.

    The following pull request contains this fix with two additions:

    • Changing from random folder numbers to a counter for the "number part" of the test directory. Doing so will prevent the tests from flickering.
    • I've added another directory layer, so all test files are in one directory (makes deleting easier)

    This results in e.g. /tmp/st-tmp-dir/56on my machine.

    Something else: In my test environments I usually clear such temp directories in a create method, so I am sure no files from previous test runs are present. Should we add this here as well?

    opened by mpdeimos 11
  • clone ST and add attributes cause an ArrayIndexOutOfBoundsException

    clone ST and add attributes cause an ArrayIndexOutOfBoundsException

    Hello,

    i'm using ST4 (4.0.8) and if i want to clone a ST two times; the second clone, st3, may cause an ArrayIndexOutOfBoundsException when i call the method add() on it.

            ST st1 = new ST("$key$");
            st1.add("toto", "tata");
            ST st2 = new ST(st1);
            st2.add("key", "value2");
            ST st3 = new ST(st1);
            st3.add("key", "value3");
    

    Exception :

    java.lang.ArrayIndexOutOfBoundsException: 1
        at org.stringtemplate.v4.ST.add(ST.java:246)
            at com.###(###.java:85)
    

    The clone operation doesn't allow add operations ?

    type:bug 
    opened by herau 10
  • STGroupString does not honor delimeter stanza in a string definition

    STGroupString does not honor delimeter stanza in a string definition

    When the following text is loaded into a String and used to create a STGroupString, the "delimiters" line is not honored and you get the default "<", ">" delimiters instead.

    I am loading my templates from the Google App Engine Blob store and the easiest way to get them into ST is with STGroupString.

    delimiters "$", "$"
    
    li(it) ::= "<li>$it.fname$ $it.lname$</li>"
    ul(ulid, list) ::= "<ul$if(ulid)$ id=\"$ulid$\"$endif$>$list:li()$</ul>"
    div(divid, ulid, content) ::= "<div$if(divid)$ id=\"$divid$\"$endif$>$ul(list=content, ulid=ulid)$</div>"
    
    status:cannot-reproduce 
    opened by jarrodhroberson 10
  • ST4-testjar not found

    ST4-testjar not found

    When including ST4 V 4.3.2 in project pom it isnt pulling in ST4-testjar Running mvn dependency:tree throws the below warning message

    [WARNING] The POM for org.antlr:ST4:jar:4.3.2 is invalid, transitive dependencies (if any) will not be available, enable debug logging for more details

    type:bug build 
    opened by mamtananavati 9
  • Bug: ST is NOT threadsafe, even using new ST(ST) doesn't seem to prevent attribute conflicts.

    Bug: ST is NOT threadsafe, even using new ST(ST) doesn't seem to prevent attribute conflicts.

    "Javadoc.stg"

    //
    // Javadoc helper functions
    //
    docName(name) ::= <<
         * @param <name> .
    >>
    docStart(name) ::= <<
         * @param <name>Start must be more than or equals to 0.
    >>
    docEnd(name) ::= <<
         * @param <name>End must be more that or equals to <name>Start.
    >>
    docLen(name) ::= <<
         * @param <name>Len must be more that or equals to 0, and less than or equals to <name> length - targetStart.
    >>
    //
    doc(of,name,suffixes) ::= <<
         * @param <name> .
    <suffixes: {suffix |
    <(["doc",suffix])(name)>}>
    >>
    

    TypeStrings.stg

    import "def.stg"
    import "Start.stg"
    import "End.stg"
    import "Len.stg"
    import "Len2.stg"
    import "get.stg"
    import "Javadoc.stg" // Is listed in  STGroup::.getImportedGroups()
    
    ofFunctions(type,of) ::= <<
        //
        // <Type(type,of)> startsWith <Type(type,of)>
        //
        /**
    <doc(of,"target",["Start","Len"])>
         */
        private static boolean startsWith0(<def0(type,of,"source",[])>,
                                           <def0(type,of,"target",["Start","Len"])>,
                                           int fromIndex) {
    ...
    

    Error Message:

    context [/ofsFunctions /_sub2 /ofFunctions] 14:1 passed 3 arg(s) to template null with 1 declared arg(s)
    

    Why can't "TypeStrings.stg" line 14 see "doc" template in "Javadoc.stg"?

    The issue disappears when I comment out the Javadoc.stg import line and paste Javadoc.stg content below the import line, hmm!

    opened by rwperrott 9
  • Use an AtomicInteger for subtemplateCount to avoid race condition

    Use an AtomicInteger for subtemplateCount to avoid race condition

    Right now, the way subtemplateCount is implemented is not thread safe since the ++ operator in java does not atomically read and write the incremented integer value. Even if each thread gets it's own STGroup, etc. we can get race conditions since the subtemplateCount field is static. This can lead to a template redefinition since a given thread may read the same for the integer twice, causing two subtemplates to have the same generated name if another thread reads the value before and writes the stale value afterwards.

    I tracked this down while debugging an issue which spit out the error message like:

    common.stg 8:125: redefinition of template SUBTEMPLATE
    

    There are similar reports in https://github.com/antlr/stringtemplate4/issues/61

    type:enhancement 
    opened by seanabraham 9
  • Trailing slash on the root dir leads to an IOException when calling URL.openstream()

    Trailing slash on the root dir leads to an IOException when calling URL.openstream()

    Instantiating a STGroupDir(URL root, ...), where root contains a trailing slash (/), leads to an Java IOException when calling URL.openstream() in the method public CompiledST loadTemplateFile(String prefix, String unqualifiedFileName). The reason is a doubleslash // coming from the expression f = new URL(root+prefix+unqualifiedFileName). Maybe URI normalizing could fix the problem, i.e. f = f.toURI().normalize().toURL(). This situation occurs (for example) after updating Apache Felix Framework to version 7.0.0 because of https://issues.apache.org/jira/browse/FELIX-6294.

    type:bug 
    opened by alexgast 8
  • Multiple special characters in a single <...> does not work as documented

    Multiple special characters in a single <...> does not work as documented

    In the documentation https://github.com/antlr/stringtemplate4/blob/master/doc/cheatsheet.md is the following:

    <\ >, <\n>, <\t> | special character(s): space, newline, tab. Can have multiple in single <...> expression, e.g. <\t\t>. -- | --

    I tried to use '<\n\t' and ST4 produced the error: expecting '>', found '\' Replacement with '<\n><\t>' works as expected.

    type:bug 
    opened by phreed 1
  • Separator not emitted for nulls until a value is hit

    Separator not emitted for nulls until a value is hit

    We use string templates for a variety of data exports. One of which is simple CSV.

    If we have an input from a table of data where as long as the first value in each row is non null then the CSV is correctly formed. When the first value is a null a separator is not emitted until there is a value.

    Imagine the following table of data

    Name, Age, Color Ron, 10, Pink Paul,15,Brown

    and the template

      printRow(row) ::= <%
        <items.Columns:{ k | <row.(k)>}; separator=","><\n>
      %>
      
      outputTemplate(items) ::= <%
        <items.Columns; separator=","><\n>
        <items.Rows:printRow()>
      %>
    

    this will output Name, Age, Color Ron, 10, Pink Paul,15,Brown

    if however the input data was Name, Age, Color Ron, 10, Pink null,15,Brown

    Then the output would be

    Name, Age, Color Ron, 10, Pink 15,Brown

    and not

    Name, Age, Color Ron, 10, Pink ,15,Brown

    I can see it is because of this section of code

    image

    because the seenAValue is false until the first value in the enumerable is non null.

    In this case there is a work around, which is to substitute nulls with "" which will generate for the example above

    Name, Age, Color Ron, 10, Pink "",15,Brown

    However I was looking at the possibility of adding another option like emitAll="true" or something like that which would be used along with the separator option to still output, something like

    boolean needSeparator = (seenAValue || (emitAll && separator!=null)) &&
                   separator!=null &&            // we have a separator and
                   (iterValue!=null ||           // either we have a value
                       options[Option.NULL.ordinal()]!=null); // or no value but null option
    
    

    However I do not have a clear idea of the impact this could have and was hoping someone for familiar with the code could advise me

    type:bug 
    opened by rrs 4
  • Use Class.getDeclaredField instead of Class.getField

    Use Class.getDeclaredField instead of Class.getField

    Hi,

    I encountered that issue with v3 but I believe the problem exists also in v4.

    Basically in https://github.com/antlr/stringtemplate4/blob/9a439491acc5b17d191316c9b3a99ab7bd340477/src/org/stringtemplate/v4/misc/ObjectModelAdaptor.java#L150 you call Class.getField and then try to make it visible via Field.setAccessible, but this is incorrect by design as Class.getField only return public fields!

    Instead you should be using Class.getDeclaredField.

    In practice, it means that it is always impossible to access private fields from templates.

    In v3, the issue was in ASTExpr but I guess this won't be fixed there? :)

    type:bug 
    opened by victornoel 2
  • Test failure: ClassCastException In DateRenderer

    Test failure: ClassCastException In DateRenderer

    for this toString method in picture below image

    when the type of first parameter is not Calendar or Date, there will be ClassCastException; So when cast to Date, should add

    if (value intanceof Date)
    

    image-20211013125710012

    opened by suoyi123wang 2
  • Interpreter.getAttribute scans attributes of parent scopes but ignores dictionaries

    Interpreter.getAttribute scans attributes of parent scopes but ignores dictionaries

    I found an unexpected behavior on resolving dictionaries and tracked it down to attribute resolution.

    I found this code:

            // got to root scope and no definition, try dictionaries in group and up
            final ST self = scope.st;
            STGroup g = self.impl.nativeGroup;
            Object o = getDictionary(g, name);
            if ( o!=null ) return o;
    
            // not found, report unknown attr
            throw new STNoSuchAttributeException(name, scope);
    

    According to the comment ("try dictionaries in group and up") dictionaries of parent scopes should have been resolved, but the code does not.

    Now what is wrong? The comment or the code?

    Actually I cannot reduce my code to a reproducing example, but I can try to provide a new example if the code is considered wrong.

    opened by almondtools 1
  • Feature request: stand-alone tool for class ST.

    Feature request: stand-alone tool for class ST.

    I looked through this repo, and there is no static void main() method on any class. Therefore, I don't think this has been considered: It would be nice to have a stand-alone tool for ST. E.g., a static void main() method on class ST, which takes: (1) a file to read stdin (or a file, or a content string on the command line), render(content), then writes to stdout the rendered contents; (2) a JSON file, specified on the command line, e.g., -args attribute-list.json, an arbitrary list of args to ST.add(). I spent a few days getting ST for C# working, but it hasn't been updated with the changes in this repo since July 16, 2016.

    type:enhancement 
    opened by kaby76 3
Releases(4.3.3)
Owner
Antlr Project
The Project organization for the ANTLR parser generator.
Antlr Project
jte is a secure and lightweight template engine for Java.

jte is a secure and lightweight template engine for Java. All jte templates are compiled to Java class files, meaning jte adds essentially zero overhe

Andreas Hager 457 Dec 22, 2022
Java 8 optimized, memory efficient, speedy template engine producing statically typed, plain java objects

Rocker Templates by Fizzed Fizzed, Inc. (Follow on Twitter: @fizzed_inc) Sponsored by Rocker is proudly sponsored by Greenback. We love the service an

Fizzed, Inc. 669 Dec 29, 2022
Java modern template engine

Jtwig Project Documentation Project Status Coverage Version jtwig-reflection jtwig-core jtwig-web jtwig-pluralization jtwig-spring jtwig-translate-ext

Jtwig 298 May 19, 2022
Multiproject template for ForgeGradle development environments

ForgeGradle Multiproject Template This repository provides a template for multiproject development environments using ForgeGradle. Project structure T

Néstor Amador 10 Jun 3, 2022
A little template project to

FX Modules This is a little project that can be used as a template for modularized JavaFX projects. The main branch is based on JDK17, other version c

Gerrit Grunwald 27 Dec 12, 2022
Pebble is a java templating engine inspired by Twig

Pebble Pebble is a java templating engine inspired by Twig. It separates itself from the crowd with its inheritance feature and its easy-to-read synta

null 985 Dec 23, 2022
a pug implementation written in Java (formerly known as jade)

Attention: jade4j is now pug4j In alignment with the javascript template engine we renamed jade4j to pug4j. You will find it under https://github.com/

neuland - Büro für Informatik 700 Oct 16, 2022
Te4j (Template Engine For Java) - Fastest and easy template engine

Te4j About the project Te4j (Template Engine For Java) - Fastest and easy template engine Pros Extremely fast (127k renders per second on 4790K) Easy

Lero4ka16 19 Nov 11, 2022
A mod for Fabric that ports Bedrock Edition mechanics to Java Edition. 1.16.x

bedrock-mechanics A mod for Fabric that ports Bedrock Edition mechanics to Java Edition. The controller support should be working on any controller by

Pedro Henrique 6 Oct 24, 2021
Bank Statement Analyzer Application that currently runs in terminal with the commands: javac Application.java java Application [file-name].csv GUI coming soon...

Bank Statement Analyzer Application that currently runs in terminal with the commands: javac Application.java java Application [file-name].csv GUI coming soon...

Hayden Hanson 0 May 21, 2022
JavaFX or Swing + jpackage + Maven template project for generating native desktop applications.

Java + Maven + GitHub Actions = Native Desktop Apps JavaFX or Swing + jpackage + Maven template project for generating native desktop applications. Go

Will Iverson 243 Dec 24, 2022
Minecraft minigame (on working, not a final nor alpha version) HUGE UPDATE COMING SOON

This project is a little minecraft minigame where the goal is either to capture all the ennemies flags or killing all the ennemies, the core gameplay

Laforge 4 Oct 6, 2022
Drools is a rule engine, DMN engine and complex event processing (CEP) engine for Java.

An open source rule engine, DMN engine and complex event processing (CEP) engine for Java™ and the JVM Platform. Drools is a business rule management

KIE (Drools, OptaPlanner and jBPM) 4.9k Dec 31, 2022
A Java API for generating .java source files.

JavaPoet JavaPoet is a Java API for generating .java source files. Source file generation can be useful when doing things such as annotation processin

Square 10k Dec 29, 2022
A Java API for generating .java source files.

JavaPoet JavaPoet is a Java API for generating .java source files. Source file generation can be useful when doing things such as annotation processin

Square 10k Jan 5, 2023
A static analyzer for Java, C, C++, and Objective-C

Infer Infer is a static analysis tool for Java, C++, Objective-C, and C. Infer is written in OCaml. Installation Read our Getting Started page for det

Facebook 13.7k Dec 28, 2022
A Java to iOS Objective-C translation tool and runtime.

J2ObjC: Java to Objective-C Translator and Runtime Project site: https://j2objc.org J2ObjC blog: https://j2objc.blogspot.com Questions and discussion:

Google 5.9k Dec 29, 2022
React Native wrapper around Indy SDK Java and Objective-C wrappers.

React Native Indy SDK React Native Indy SDK wrapper. Installation with npm: $ npm install indy-sdk-react-native --save with Yarn: $ yarn add indy-sdk-

Hyperledger 21 Dec 5, 2022
React 0.68+ Turbo Module starter using codegen with typescript for Objective-C and Java/Kotlin with C++ shared library. 🚀🚀🚀

React 0.68+ Turbo Module starter using codegen with typescript for Objective-C and Java/Kotlin with C++ shared library. ?? ?? ?? Features React Native

Nagish Inc. 358 Jan 3, 2023