In this example the generator is used to generate a simple bean.
The model.xml defines one class "Person" in a package "example-1". The Person has one attribute "name".
The config.xml defines a simple template to generate a bean.
To start the example-1 go into the root-Directory "example" and start
ant example-1
This should generate the bean into the src/java folder.
jaCG reads the model from a simple xml file. This file is mostly called model.xml for simplicity. For this simple example the xml file is quite small. You can edit it by hand. In a real project it is a good idea to generate the xml file from another source. This could be a UML-Model or a Word dokument. The idea is to transform the structured documentation with a tool into the model.xml for the generator. This step makes the generator independent from a specific documentation tool.
Let's have a look into the small xml file for this model.
<?xml version="1.0" encoding="ISO-8859-1" ?> <model name="Bean-Model"> <class package="example" name="Person" stereotype="Bean"> <attribute name="name" type="String"/> </class> </model>
The document opens with a model element as the root of the document. Inside of this element is a class element. The class has two attributes package and name. The stereotype attribute has a special meaning. This comes later. The class element contains one attribute element with the attributes name and type.
This structure is easy to understand. It represents the structure of a class in java.
The file config.xml configures the generator. It describes how to translate the templates and how to handle the elements in the model.xml.
Here is the config.xml of the first example:
<?xml version="1.0" encoding="ISO-8859-1" ?> <config> <property name="templates.dir" value="src/templates"/> <property name="src.dir" value="src/java"/> <property name="src-gen.dir" value="src/java-gen"/> <ejt-compiler output="./bin" source="${templates.dir}" temp="./tmp" compilerImpl="jacg.CBGCompiler14Impl"> <classpath-element path="./bin"/> <classpath-element path="./lib/generator-1.0.jar"/> </ejt-compiler> <generator rootTemplate="BeanRoot" overwrite="true" outputPath="${src.dir}" stereotype="Bean"> <templates directory="${templates.dir}"> <template name="BeanRoot" file="bean/SimpleBeanTemplate.java"/> </templates> </generator> </config>
The document starts with a config element. The first three property elements define some directories. The properties can be used inside the file as constants. This is the same as in a build.xml of a ant script.
The second part starts with an element ejt-compiler. This element configure a java compiler to translate the templates into class files. jaCG has no special template language. Templates are written in java and the standard java compiler is used to translate them to class files. For the moment just trust me, that this will work.
The third part defines our first generator. A generator is a collection of templates working on model classes with a specific stereotype. As described above the stereotype attribute has a special meaning. It clues a class and a generator together. That means: A generator with stereotype Bean runs on every class in the model with the same stereotype. So the generator will run on the Person class because the Person class has the stereotyp Bean.
The templates of the generator are defined inside of the templates element. This example only has one template. But it is possible to define more the one template inside of a generator. But that comes later. It is important to notice, that each template inside of a generator has a unique name. The generator start the generation with the name of the rootTemplate attribute.
The last thing we need for the first example is a template. This template must be in the directory bean and must be named SimpleBeanTemplate. This is described in the config.xml of the example. You can find the whole source of the template in the src/templates/bean/SimpleBeanTemplate.java of the examples directory.
Just have a look at a part of the java class to get an idea.
package bean; import jacg.CompiledJavaTemplate; import jacg.Generator; import jacg.model.Attribute; import jacg.model.Reference; import java.util.Iterator; public class SimpleBeanTemplate extends CompiledJavaTemplate implements GeneratorConstants { public void generate() { defineProperty( "name", myClass.getName() ); defineProperty("package", myClass.getPackage() ); println("//"+GENERATE_MARKER_LINE); println("package ${package};" ); println( "" ); ...
The first lines are simple java code as you see it many times. Lets look at the class istself. It is derived from a class CompiledJavaTemplate. This makes the class to a template usable for jaCG. It implements a interface GeneratorConstants. This is because the example defines some constants in this interface.
Every template MUST implement the method generate. This is the call back method of the generator framework when the template is used to do its job. Inside of the method generate are two statements to define a property. Look at the first call to the defineProperty method. The first argument is the name of the property. The second argument is the properties value. The class member variable myClass is a reference to the class this template is actually working on. And the call to myClass.getName() gives the value of the Attribute name of the class element inside of the model. This means that the property name is set to the name of the class we are generating for. In our example this should be Person.
The println statements printing some text into the output buffer. This is how you should generate code. The statement
println( "package ${package};" );
prints a package decplaration into the output buffer. The string $pacjage refers to the value of the propery package. In out example this should be example
What about the line
println("//"+GENERATE_MARKER_LINE);
This line marks the file as generated. jaCG will always re generate the file if it finds this line in the first 5 rows of the output file. If not, the file is left untouched. So if you want to migrate a file from status generated to had written, than you should remove this line from the source and jaCG will never more touch the file. If you decide to let jaCG generate the file later, just delete the file. This is a simple, but very handy method to deal with generated parts of the code which must be refined by a developer.
Here is the result of all this fiddling.
//THIS CODE IS GENERATED package example; public class Person { private String name; public Person() { super(); } public void setName( String value ) { this.name = value; } public String getName() { return this.name; } }
So many trouble for just one class!
jaCG uses a simple xml format to describe models. The configuration file clues templates to stereotypes. Templates are written in java. The meber variable myClass give access to the model class the template is actually generating for. Output is done by calling the println method.
The next example will use java mechanisms to enhance the template. It will generate a bean, that fires a property change event.