Text Templates in CLIPS

Our first program will demonstrate how to use text templates in Java. We’ll use the Apache Velocity library for this purpose, as it provides similar functionality to Go’s text/template package.

First, let’s add the Velocity dependency to our project. If you’re using Maven, add this to your pom.xml:

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

Now, let’s look at the Java code:

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class TextTemplates {
    public static void main(String[] args) {
        // Initialize Velocity
        Velocity.init();

        // We can create a new template and parse its body from a string.
        // Templates are a mix of static text and "references" enclosed in
        // ${...} that are used to dynamically insert content.
        String template1 = "Value is ${value}\n";
        VelocityContext context = new VelocityContext();

        // By "merging" the template we generate its text with
        // specific values for its references.
        context.put("value", "some text");
        mergeTemplate(template1, context);

        context.put("value", 5);
        mergeTemplate(template1, context);

        context.put("value", Arrays.asList("Java", "Python", "C++", "C#"));
        mergeTemplate(template1, context);

        // If the data is an object we can use the ${object.field} reference to access
        // its fields. The fields should be public or have getter methods to be
        // accessible when a template is executing.
        String template2 = "Name: ${person.name}\n";
        context = new VelocityContext();
        context.put("person", new Person("Jane Doe"));
        mergeTemplate(template2, context);

        // The same applies to maps; with maps there is no restriction on the
        // case of key names.
        Map<String, String> map = new HashMap<>();
        map.put("name", "Mickey Mouse");
        context.put("person", map);
        mergeTemplate(template2, context);

        // #if/#else provide conditional execution for templates. A value is considered
        // false if it's null, an empty string, or zero.
        String template3 = "#if($value)yes#else no#end\n";
        context = new VelocityContext();
        context.put("value", "not empty");
        mergeTemplate(template3, context);
        context.put("value", "");
        mergeTemplate(template3, context);

        // #foreach blocks let us loop through collections. Inside
        // the foreach block $item is set to the current item of the iteration.
        String template4 = "Range: #foreach($item in $list)$item #end\n";
        context = new VelocityContext();
        context.put("list", Arrays.asList("Java", "Python", "C++", "C#"));
        mergeTemplate(template4, context);
    }

    private static void mergeTemplate(String template, VelocityContext context) {
        StringWriter writer = new StringWriter();
        Velocity.evaluate(context, writer, "log tag name", template);
        System.out.print(writer.toString());
    }

    static class Person {
        public String name;

        Person(String name) {
            this.name = name;
        }
    }
}

To run the program, compile and execute it:

$ javac TextTemplates.java
$ java TextTemplates
Value is some text
Value is 5
Value is [Java, Python, C++, C#]
Name: Jane Doe
Name: Mickey Mouse
yes
no
Range: Java Python C++ C# 

This example demonstrates how to use the Velocity template engine in Java to achieve similar functionality to Go’s text/template package. We create templates, populate them with data, and handle conditionals and loops within the templates.

The Velocity syntax is slightly different from Go’s. For example, it uses ${...} for variable substitution instead of {{...}}, #if/#else/#end for conditionals instead of {{if}}/{{else}}/{{end}}, and #foreach for loops instead of {{range}}.

While the API and syntax differ somewhat from Go’s text/template, the core concepts of creating templates, populating them with data, and rendering the results remain the same.