Friday, September 29, 2006

Java - Dynamic code generation using XDoclet

Usually XDoclet is used through Ant or an IDE that launches XDoclet, mainly for generating configuration files. But if you would like to generate source and descriptors at runtime from the user input, then here is the solution or hack, whatever you call it.

XDoclet finds all the tags and its attributes specified in the Javadoc section of the class and its methods.
An instance of SourceClass(found in XJavaDoc) holds all the details of the source file read. It contains collection of XMethods representing methods and XFields representing properties.
These xmethods and xfields contain all the details(return type, parameters) and tags defined in the source file for the corresponding method or property.

Instead of writing a Java source file with XDoclet tags, we have to create an instance of any of the implementation classes of XClass interface such as SourceClass and provide it to the XDoclet module which is going to handle the tags; for eg: HibernateSubTask.

Creating an instance of SourceClass

XTagFactory tagFoctory = new XTagFactory();
XJavaDoc jDoc = new XJavaDoc();
File sourceFile = new File(yourClassName+".java");
try {
sourceFile .createNewFile();
sourceFile .deleteOnExit();
SourceClass sourceClass = new SourceClass(jDoc, tempFile, tagFoctory);
sourceClass.setQualifiedName(qualifiedClassNameOfYourClass);
} catch (IOException e) {

e.printStackTrace();
}


A temporary SourceClass is ready, now we have to add the getter methods for the properties in the class to be generated. Properties or fields are generated based on the methods defined for the properties. MethodImpl is the implementation class for XMethod interface.

MethodImpl method = new MethodImpl(sourceClass, sourceClass.getTagFactory());
method.setReturnType(returnTypeOfMethod);
method.setName("get"+propertyName);
method.addModifier(0); // public access specifier

To access some of the package level properties and methods in these classes, you will have to create your source files under xjavadoc package.

method.getDoc().addTag(tagName,tagValues);
//eg: tagName - hibernate.id, tagValue - name="empid"
sourceClass.addMethod(method);

The method level tags are added to the method's xJavaDoc as shown above.
The class level tags such as hibernate.class are added to the sourceClass's xJavaDoc in the similar fashion.

So we are done with our SourceClass that holds all the tags required by XDoclet to generate code. Now you will have to create an instance of the XDoclet module ant subtask(eg: HibernateSubTask) and set the sourceclass to it.

task.setCurrentClass(sourceClass);
task.execute();

And execute the task! That's it.
(I have not discussed about the ant subtask configurations, please find the necessary things required for the particular module)

No comments: