Canvas

Cedric Beust
March 7, 2004

Canvas is a template generator based on the Groovy language.  It uses the familiar Velocity Java API to bind variables and allows you to use the full expressivity of Groovy inside your templates.  You can download Canvas here.

API

To create a template, you need to:

Here is an example:

Context ctx = new Context();
ctx.put("firstName", "Cedric");
Template tmpl = Canvas.getTemplate("mytemplate.canvas");
StringBuffer sb = new StringBuffer();
tmpl.merge(ctx, sb);
// The merged template is now available in sb

Template files

Template files, typically suffxed with ".canvas" contain a mix of your own text, which will be reproduced verbatim in the merged template, and Groovy code.  Groovy code is surrounded with "<%" and "%>", to reuse the familiar JSP syntax.  Here is an example:

Hello, <% firstName %>.

The Groovy code is evaluated and its value is equal to the last value returned by the code fragment.  Here is another example of a more complex expression, using a Groovy hash table:

<%
data = ["Cedric": "San Francisco", "Alois": "Paris"]
result = ""
for (e in data) {
  result += ("${e.key} lives in ${e.value}\n")
}
result
%>

Supported types

You can put arbitrary objects in a Canvas context, but some classes receive a special treatment:  Java Beans, java.util.Collection, java.util.Map.

Java Beans

A JavaBean that contains getters and setters can be addressed with a shorthand notation in the Groovy fragment.  For example, if you have the following Java class:

public class Company {
  private String m_name;
  private String m_location;

  public String getLocation() {
    return m_location;
  }

  public String getName() {
    return m_name;
  }
}

and that you put an instance of this class in your context:

Context ctx = new Context();
Company c = new Company();
c.setName("Cedric");
ctx.put("me", c);

You can access the property in the Canvas template like this:

Hello, <% me.name %>

Collections

Collections are translated into Groovy lists.  For example:

Context ctx = new Context();
Company c = new Company();
c.setName("Cedric");
Company c2 = new Company();
c2.setName("Alois");
List l = new ArrayList();
l.add(c);
l.add(c2);
ctx.put("brothers", l);

In the template:

Brothers: <%
fam = ""
for (b in brothers) { fam = fam + b + " " }
fam%>

which will return "Brothers:  Cedric Alois ".

Maps

Similarly, Java maps are turned into Groovy maps:

Context ctx = new Context();
Map m = new HashMap();
m.put("Cedric", "San Francisco");
m.put("Alois", "Paris");
ctx.put("workplaces", m);

Template:

Workplaces are <%
workplaces.get("Cedric") + " " + workplaces.get("Alois")
%>

will produce "Workplaces are:  San Francisco Paris ".


Back to my weblog.