JGEN - examples

Printer-friendly versionPrinter-friendly version
How to use the JGEN template engine

JGEN is designed to generate Java source files from templates by information gathered from Java class files and other information provided by generator presets. JGEN might be extended in the future to support futher file types as well. JGEN is based on pure Java and when we configure it by defining own generator setups and presets, we do that in pure Java as well (unless we implement in a preset to gather information from externalized configurations). This way we can enjoy the full power of Java to configure JGEN, that is, we are not restricted by the capabilities of a DSL, script language or whatsoever, and moreover we do not need to learn a complex proprietary DSL or another script language and keep that knowledge in our developer team over the years even if we need new configurations or changes just seldom. Of course, every tool needs some learning how to use it, but thats not comparable to the efforts to learn and maintain a complex proprietary DSL or the like.

The JGEN source files are also used to demonstrate how to use the Navigator framework (as one possibility out of many), since Navigators are also ideal for parsers or the like.

We create a template file with any file extension, but the standard is to use "jgen", e.g. "HelloWorld.jgen". The content should be exactly what we want to generate into each generated file, except those parts which we want to replace dynamically with gathered values. Those replacements are marked in the template by specific symbols.

Hello §$ ADDRESSEE !

Here we want to replace "§$ ADDRESSEE $§" with "world" as a fixed replacement value or maybe we gather other addressee names from resources to replace it on a per-resource basis. As you can see "§$" is the symbol that marks the start of the replacement and "" is the symbol that marks the end of the replacement. These symbols can be changed in the GeneratorPreset. JGEN differs start and end solely for better readability of templates. For the same reason you can add as many spaces as you want before and after the symbol that denotes the replacement (here "ADDRESSEE"). We can use as symbol any text we want, but uppercase is better visible again. If a symbol that denotes the replacement is used more than one time in the template then all these occurrences of that same symbol will be replaced with the same value.

Replacements can also be nested, that is, a certain symbol will be replaced by the results of a previous run of the generator (using another template). So we can define complex replacement structures with templates used for parts of other templates. This comes in handy if we want to generate repetitive contents like a list of constructors and methods, where we have one template for the entire Java source file and one constructor template and one method template.

 

In general we can use JGEN in three ways: as an external tool, invoked via "JGen.main(String[])" or we invoke JGEN from our own application code using one of the static "generate"-methods, to actually generate files, or using one of the static "getGeneratedContent"-methods, to just get the generated contents for our own further processing.

Note: the method "JGen.main(String[])" takes as arguments one or several GeneratorSetup class names, something like "com.my.company.project.jgen.Setup".

Either way we have to provide some information to JGEN how to generate the contents and files. The overall configuration for a generation is organized in a GeneratorSetup, which contains the GeneratorPreset as well as properties for the overall behavior, e.g. indicators if JGEN is allowed to write to files or if JGEN is allowed to print to the standard print stream (console). The GeneratorPreset is the configuration for the generation of the contents itself, where we define for instance

  • the template file
  • start and end symbol
  • custom path to look up (recursively)
  • classpath selectors (classpath look up)
  • class file & filename selectors
  • class file validators (to filter classes)
  • symbol references (to assign values to symbols)
  • output file strategy (how to write files)

 

 

Seiten