During many projects you feel the need to generate some code, to make the Runtime code simpler and clean of meta-informations.
Most of the time programmers rather live with the "dirty" and or complex runtime code instead of writing a small code generator, mostly with the argumentation the code generators are so difficult to write. But this is not true, as the following example will show you.
Writing a Maven-plugin (Mojo) that generates Java source code is a easy thing with jenesis4Java. First of all, do we need a Project structure:
+ExampleMojo +--src | +--main | +--java | +--JenesisMojo.java +--pom.xml
The pom file can be very compact and should look like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.sourceforge.jenesis4java</groupId>
<artifactId>Jenesis-mojo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<dependencies>
<!-- The dependency to the maven API -->
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.0</version>
</dependency>
<!-- The dependency to the Jenesis4Java -->
<dependency>
<groupId>net.sourceforge.jenesis4java</groupId>
<artifactId>jenesis4java</artifactId>
<version>2.0</version>
</dependency>
<!-- We will use Jalopy to format the Generated source code -->
<dependency>
<groupId>jalopy</groupId>
<artifactId>jalopy</artifactId>
<version>1.5rc3</version>
</dependency>
</dependencies>
</project>As usual in Maven the Mojo Java class speaks for it self.
import java.io.File;
import java.io.IOException;
import net.sourceforge.jenesis4java.Access;
import net.sourceforge.jenesis4java.ClassMethod;
import net.sourceforge.jenesis4java.Comment;
import net.sourceforge.jenesis4java.CompilationUnit;
import net.sourceforge.jenesis4java.Invoke;
import net.sourceforge.jenesis4java.PackageClass;
import net.sourceforge.jenesis4java.Type;
import net.sourceforge.jenesis4java.VirtualMachine;
import net.sourceforge.jenesis4java.jaloppy.JenesisJalopyEncoder;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/**
* @goal jenesis4java
* @phase generate-sources
* @description generate the java source code
*/
public class JenesisMojo extends AbstractMojo {
/**
* @parameter expression="${project}"
* @required
*/
protected MavenProject project;
/**
* @parameter expression=
* "${project.build.directory}/generated-sources/jenesis4java"
* @required
*/
protected File outputJavaDirectory;
/**
* @parameter
*/
protected String title;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
if (this.project != null) {
this.project.addCompileSourceRoot(this.outputJavaDirectory.getAbsolutePath());
}
if (!this.outputJavaDirectory.mkdirs()) {
getLog().error("Could not create source directory!");
} else {
try {
generateJavaCode();
} catch (IOException e) {
throw new MojoExecutionException("Could not generate Java source code!", e);
}
}
}
private void generateJavaCode() throws IOException {
System.setProperty("jenesis.encoder", JenesisJalopyEncoder.class.getName());
// Get the VirtualMachine implementation.
VirtualMachine vm = VirtualMachine.getVirtualMachine();
// Instantiate a new CompilationUnit. The argument to the
// compilation unit is the "codebase" or directory where the
// compilation unit should be written.
//
// Make a new compilation unit rooted to the given sourcepath.
CompilationUnit unit = vm.newCompilationUnit(this.outputJavaDirectory.getAbsolutePath());
// Set the package namespace.
unit.setNamespace("net.sourceforge.jenesis4java.example");
// Add an import statement for fun.
unit.addImport("java.io.Serializable");
// Comment the package with a javadoc (DocumentationComment).
unit.setComment(Comment.D, "Auto-Generated using the Jenesis Syntax API");
// Make a new class.
PackageClass cls = unit.newClass("HelloWorld");
// Make it a public class.
cls.setAccess(Access.PUBLIC);
// Extend Object just for fun.
cls.setExtends("Object");
// Implement serializable just for fun.
cls.addImplements("Serializable");
// Comment the class with a javadoc (DocumentationComment).
unit.setComment(Comment.D, "The HelloWorld example class.");
// Make a new Method in the Class having type VOID and name "main".
ClassMethod method = cls.newMethod(vm.newType(Type.VOID), "main");
// Make it a public method.
method.setAccess(Access.PUBLIC);
// Make it a static method
method.isStatic(true);
// Add the "String[] argv" formal parameter.
method.addParameter(vm.newArray("String", 1), "argv");
// Create a new Method Invocation expression.
Invoke println = vm.newInvoke("System.out", "println");
if (this.title != null) {
// Add the Moja parameter string literal as the sole argument.
println.addArg(vm.newString(this.title));
} else {
// Add the Hello World string literal as the sole argument.
println.addArg(vm.newString("Hello World!"));
}
// Add this expression to the method in a statement.
method.newStmt(println);
// Write the java file.
unit.encode();
}
}That's all now we can use it in our other projects. You can build the plugin / Mojo with your other modules maven will sort out the order for you. An example:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.sourceforge.jenesis4java</groupId>
<artifactId>Jenesis-mojo-use</artifactId>
<version>1.0.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>net.sourceforge.jenesis4java</groupId>
<artifactId>Jenesis-mojo</artifactId>
<version>1.0.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
<goal>jenesis4java</goal>
</goals>
<configuration>
<title>Jenesis 4 Java</title>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>