The best way to explain the API is to use an example. In this section we will create a class which has a main method which prints the familiar greeting "Hello World!".
The base object factory is the VirtualMachine. Once you have the VM, all object creation occurs through it or derived from it.
// Fetch the VirtualMachine. VirtualMachine vm = VirtualMachine.getVirtualMachine(); |
Using the VM, create a new CompilationUnit object. The CompilationUnit directly corresponds to the .java source file. The CompilationUnit can introduce a package statement and import statements. We'll put our class in a package and import java.io.Serializable explicitly to illustrate.
// 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 (codebase). CompilationUnit unit = vm.newCompilationUnit("/tmp"); // Set the package namespace. unit.setNamespace("com.example.jenesis"); // 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"); |
Now create a new top-level class. The argument to the class factory method is the name of the class. After it is constructed, set the access level to public (making it a public class rather than package private).
// 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). cls.setComment(Comment.D, "The HelloWorld example class."); |
Now make the Method object and make it static. The arguments to the Method factory construction are the return type of the method and the name of the method.
// 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"); |
Finally we add the print statement.
// Create a new Method Invocation expression. Invoke println = vm.newInvoke("System.out", "println"); // 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); |
The last step is to generate the file. This is behavior encapsulated by the CompilationUnit.
// Encode the file unit.uncode(); |
Here is a fancier alternative last step. Rather than just writing the file, we will encode the file, compile it, load the class, and call it's main method using Java's reflection mechanisms.
// Encode the file, compile it, and load the class java.lang.Class hello = cls.load(); // Get the main method java.lang.reflect.Method main = hello.getMethod("main", new Class[]{String[].class}); // Invoke it main.invoke(hello.newInstance(), new Object[]{ new String[]{} }); |