I'm doing something very similar. The basic idea is that your model must expose a list of some object, and you use that list within your string templates. For instance, let's say I have a very braindead implementation. I'm going to use Java because that's what I know best; you should get the idea.
https://gist.github.com/894632
public class GeneratedClass {
private String accessModifier;
private String name;
private String superClass;
private List<Method> methods;
}
public class Method {
private String comments;
private String name;
private String accessModifier;
private Type returnType;
private List<Argument> arguments;
private String body;
}
public class Argument {
private Type type;
private String name;
}
public class Type {
private String name;
}
For my template I might have the following:
group Java;
class(accessModifier, name, superclass, methods)::=<<
$accessModifier$ class $name$ extends $superclass$ {
$methods:method(); separator="\n"$
}
>>
method(method)::=<<
/**
$method.comments$
*/
$method.accessModifier$ $method.returnType.name$ $name$ ($method.arguments:argument(); separator=","$) {
$method.body$
}
>>
argument(argument)::=<<
$argument.type.name$ $argument.name$
>>
The key is that I functionally apply a template for each method object I have; that's what $methods:method()
does. If I had an empty list, no template would be invoked at all. This handles the variable size problem. I do a similar thing within the method definition; ($method.arguments:argument(); separator=","$)
. This is going to create a comma separated list of method parameters in between parentheses, just like you'd expect.