Tutorial on Java code generation with CodeModel – Generics

This part of the tutorial is about Generics management with CodeModel.

Now that we have covered basics, javadoc and jexpressions, let’s take a look at how to manage Generics with CodeModel.

First of all, to make a class Generic you have to call the following method to the JDefinedClass created to build it:

 
     JDefinedClass.generify(String name); 

Let’s see actual code and result:

 
        String concreteName = "net.cardosi.MyNewGenericClass";
        String genericTypeName = "T";
	JClass genericT = codeModel.ref(genericTypeName);
        JDefinedClass concreteClass = codeModel._class(concreteName);
	concreteClass.generify(genericTypeName);
 
package net.cardosi;

public class MyNewGenericClass<T> {

}

Now, let’s add a “generic” field to it.. let’s see… maybe a List? For this we need a reference to:

  • A JClass representing the type parameter (“T” in our example);
  • A JClass representing the raw interface (“List” in our example);
  • A JClass representing the interface’ generic type (“List<T>” in our example);
  • A JClass representing the raw implementation of the interface (“ArrayList” in our example);
  • A JClass representing the implementation’ generic type of the interface (“ArrayList<T>” in our example);

With all that, we can define and instantiate a Generic field

 
        JClass genericT = codeModel.ref(genericTypeName);
	JClass rawLLclazz = codeModel.ref(List.class);
	JClass fieldClazz = rawLLclazz.narrow(genericT);
	JClass rawArrayListClass = codeModel.ref(ArrayList.class);
	JClass arrayListFieldClazz = rawArrayListClass.narrow(genericT);
	JExpression newInstance = JExpr._new(arrayListFieldClazz).arg(JExpr.lit(0));
	String listFieldString = "genericList";
	JFieldVar listFieldVar = concreteClass.field(JMod.PRIVATE, fieldClazz, listFieldString);
	listFieldVar.init(newInstance);

Here’s what we get (note that the imports are automatically generated by CodeModel:

 
package net.cardosi;

import java.util.ArrayList;
import java.util.List;

public class MyNewGenericClass<T>{

    private List<T> genericList = new ArrayList<T>(0);

}

Last thing to do, now, is to provide a method to insert something in our List. It is not different from what we saw in Basics, but we have to use the JClass representing the type parameter. More over, we have to “literally” invoke the method “add” on the reference to the list field:

 
	String adderParameterString = "toAddParam";
	JVar adderParam = method.param(genericT, adderParameterString);
	method.body().invoke(JExpr.ref(listFieldString), "add")
					.arg(adderParam);

Generated method:

 
	public void addGeneric(T toAddParam) {
             genericList.add(toAddParam);
        }

Here’s all the relevant code (javadoc generation included) and the generated class:

 
	String concreteName = "net.cardosi.MyNewGenericClass";
	String genericTypeName = "T";
	JClass genericT = codeModel.ref(genericTypeName);
	JDefinedClass concreteClass = codeModel._class(concreteName);
	concreteClass.generify(genericTypeName);
	JDocComment javadoc = concreteClass.javadoc();
	String commentString = "My wonderful Generic class";
	javadoc.append(commentString);
	JClass rawLLclazz = codeModel.ref(List.class);
	JClass fieldClazz = rawLLclazz.narrow(genericT);
	JClass rawArrayListClass = codeModel.ref(ArrayList.class);
	JClass arrayListFieldClazz = rawArrayListClass.narrow(genericT);
	JExpression newInstance = JExpr._new(arrayListFieldClazz).arg(JExpr.lit(0));
	String listFieldString = "genericList";
	JFieldVar listFieldVar = concreteClass.field(JMod.PRIVATE, fieldClazz, listFieldString);
	listFieldVar.init(newInstance);
	javadoc = listFieldVar.javadoc();
	commentString = "My Generic List<T>";
	javadoc.append(commentString);
	String methodName = "addGeneric";
	JMethod method = concreteClass.method(JMod.PUBLIC, void.class, methodName);
	javadoc = method.javadoc();
	commentString = "Method to add a Generic T to our List<T>";
	javadoc.append(commentString);
	String adderParameterString = "toAddParam";
	JCommentPart commentPart = javadoc.addParam(adderParameterString);
	JVar adderParam = method.param(genericT, adderParameterString);
	commentString = "The T to add.";
	commentPart.append(commentString);
	method.body().invoke(JExpr.ref(listFieldString), "add").arg(adderParam);
	codeModel.build(new File("."));
package net.cardosi;

import java.util.ArrayList;
import java.util.List;

/**
 * My wonderful Generic class
 * 
 */
public class MyNewGenericClass{

    /**
     * My Generic List<T>
     * 
     */
    private List genericList = new ArrayList(0);

    /**
     * Method to add a Generic T to our List<T>
     * 
     * @param toAddParam
     *     The T to add.
     */
    public void addGeneric(T toAddParam) {
        genericList.add(toAddParam);
    }

}

Don’t miss the next part about
Inheritance. C YA!!!

Advertisements

2 thoughts on “Tutorial on Java code generation with CodeModel – Generics

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s