- [Seeing everything in action](#seeing-everything-in-action)
- [Tea Break](#tea-break)
### Goals
One of the most common coding tasks involves generating textual artefacts. Employing a template engine is one of the most popular ways to do that in practice. By the way, text and code are two different things, but from a generative point of view they're not really any different at all.
My casual exploration tries to create a template based POC solution that meets the following goals:
1. To create a cognitively lightweight solution for simple use cases - no learning beyond what can be achieved in a brief tutorial for a Java developer.
2. To generate **<spanstyle="text-decoration:underline;">multiple files</span>** from a single template file - this is a pet peeve of mine.
Code generation is a well trodden field. There are better alternatives than doing DIY code generation from scratch. The whole exercise I present here is really about exploring ”cognitively lightweight” code generation within the span of an afternoon.
### Serious Code Generation
I've used a few different code generation stacks in the past, and they're all good for different purposes. These are all better alternatives to what I demonstrate here:
3. Visual programming language driven code generation/VM. E.g., Scratch and Marama [https://tinyurl.com/y9no2u5p](https://tinyurl.com/y9no2u5p)
4. Macro (supported by any LISP like language)
## Proof of Concept Walkthrough
### Step 1
With the goal of creating something that is both lightweight and easy to use, I've decided on mixing Java and non-Java bits. By doing this, I will be able to get the full power of Java within my reach and delegate commonly occurring text output tasks to a few non-Java bits - from this point on the non-Java bits are called **_generative functions_**.
The first part is to create models that drive text output; the second half involves file and text related things such as file creation and text output.
Consider the following template that I created for POC:
`<<:function-symbol arg0 arg1 … argN>>` expressions that appear in the above template are generative functions. Each generative function is mapped into Java code when a template is loaded for code generation.
What the template does here is self-explanatory:
1. Creates a file at ./text whose name is a concatenation of a freshly generated UUID and ".txt".
2. If the name of the model object is "Lorem Ipsum" then writes the literal string and evaluated values as specified in Line X - Y.
3. If the name of the model object is not "Lorem Ipsum" then
1. Creates a file at ./ whose name is a concatenation of "something-else", a freshly generated UUID and ".txt".
2. Writes "Hello," and an uppercased name of the model object.
### Step 2
The next step, which happens during run-time, is to load a template file. The loaded template file is turned into Java code by mapping generative functions into Java code.
Text Output (./something-else-8ed3c1fa-43b8-4cd3-8072-ea36c7327939.txt)
```
Hello, NOT LOREM IPSUM!
```
## Implementation Walkthrough
### Processing Template
Each line of a template file can only be either Java code or generative function.
```java
Template Line := Java Code | Generative-Function
```
The template loader can easily detect a generative function line by looking for generative function start and end markers; “<<:”and“>>”. When the template loader gets a generative function line then the loader invokes a corresponding Java code mapper for the function symbol of the generative function.
Generative Functions:
*`begin`
*`end`
*`file`
*`creates a new file.`
*`method`
*`a unary generative method that takes a model as an argument; a template needs to have one generative method.`
*`out (a workhorse function that directs the text to file)`
The initial design was limited so that a single generative function could not take over more than one line. After a few tries, it became apparent the limitation had to go - so changes were made!
out - The workhorse function has been modified so that it can spread over multiple lines as shown below:
```java
<<:outx
Line 1 \n
Line 2 \n
Line 3 \n
>>
```
Not
```java
<<:outxLine1 \n>>
<<:outxLine2 \n>>
<<:outxLine3 \n>>
```
So the line detection - primitive lexer - of the template loader had to change to deal with the multi-line out function. A simple solution was when a “<<:out”linedoesnotendwith“>>” then “delayed evaluation” kicks in until we have the whole out file function.
### Code Generation - Text Output
At the end of the line detection and code mapping, we get a String value which is Java code. We hand over a collection of String values to a reflection facility, turning the text input into live Java code at runtime - the whole process has been completed!
FYI: I am using jOOR to build Java code during runtime: [https://www.jooq.org/products/jOOR/javadoc/latest/org.jooq.joor/org/joor/Reflect.html](https://www.jooq.org/products/jOOR/javadoc/latest/org.jooq.joor/org/joor/Reflect.html)
## Seeing everything in action
Let's create a template so that you can personalise your greeting message for each person.
### Goal - Timezone aware greeting text
Given a list of people, for each one of them we want to generate a timezone appropriate greeting text output.
Assuming it is 3:30 pm CEST and we want to generate a greeting for someone in NY, we would print out “Good morning, Mary.” If the person lives in London, we would print out “Good afternoon, Mary.” And if the person lives in Perth, we would print out “Good evening, Mary.” This can be done by using a simple function that takes in the current time and the person's location and outputs the appropriate greeting.
Now that I have a domain class to feed to a template. Let’s sketch out a template.
Firstly, we need to create a list of "Person" objects. The list is fed to CodeGenerator, and the ZoneId of the Person object is used for each Person to find out what greeting to use.