Tutorial on Java code generation with CodeModel – Javadoc

This part of the tutorial is about Javadoc generation with CodeModel.

What is Java code without Javadoc? Surely none of you will ever think to write a class or a method without a properly formatted and meaningful documentation… or not ?

Well, of course CodeModel does not leave you alone in this task; let’s see how.
Here’s the source of JDocCommentable interface:

package com.sun.codemodel;

/**
 * Program elements that can have Javadoc
 * 
 * @author Jonas von Malottki
 */
public interface JDocCommentable {
    /**
     * @return the JavaDoc of the Element
     */
    JDocComment javadoc();
}

As the smartest of you may have already guessed, JDocComment returned by javadoc() method is the class to use to create javadocs. Note that this interface is implemented by all the classes that generate *javadoc-able* elements (classes, enums, variables, methods, packages).
To write something in the created comment we use the method JDocComment.append(Object).
So, the code needed to comment a class declaration is something like this:

String className = "net.cardosi.MyNewClass";
JDefinedClass definedClass = codeModel._class(className);
JDocComment comment = definedClass.javadoc();
String commentString = "My wonderful class";
comment.append(commentString);

and here’s the generated code, in all its splendor:

package net.cardosi;

/**
 * My wonderful class
 * 
 */
public class MyNewClass {
   ...
}

The same goes for variables:

String fieldName = "intVar";
String fieldNameWithFirstLetterToUpperCase = "IntVar";
JFieldVar field = definedClass.field(JMod.PRIVATE, int.class, fieldName);
JDocComment comment = field.javadoc();
String commentString = "My int variable";
comment.append(commentString);

But, ehy! What about parameters, returned values and stuff like that?
No worry, guys. JDocComment has different methods to retrieve a JCommentPart specifically suited for each one.
For example, this is to write a simple setter method documentation, with a single parameter description:

JMethod setterMethod = definedClass.method(JMod.PUBLIC, Void.TYPE, setterMethodName);
JDocComment comment = setterMethod.javadoc();
String commentString = "Method to set " + fieldName + "";
comment.append(commentString);
String setterParameter = "intVarParam";
JCommentPart commentPart = javadoc.addParam(setterParameter);
commentString = "The " + fieldName + " to set.";
commentPart.append(commentString);

For return descriptions we have just to retrieve JCommentPart with JDocComment.addReturn():

JMethod getterMethod = definedClass.method(JMod.PUBLIC, int.class, getterMethodName);
JDocComment comment = getterMethod.javadoc();
String commentString = "Method to get " + fieldName + "";
comment.append(commentString);
JCommentPart commentPart = javadoc.addReturn();
commentString = "The " + fieldName + ".";
commentPart.append(commentString);

JDocComment has also methods to retrieve JCommentPart to generate Deprecated, Throws, and XDoclet parts, but they works the same way, so I won’t describe them here.

Now, if you followed the tutorial from the beginning, you should have something like this (well, I know it’s getting ugly…)

JCodeModel codeModel = new JCodeModel();
		try {
			String className = "net.cardosi.MyNewClass";
			JDefinedClass definedClass = codeModel._class(className);
			JDocComment comment = definedClass.javadoc();
			String commentString = "My wonderful class";
			comment.append(commentString);
			String fieldName = "intVar";
			String fieldNameWithFirstLetterToUpperCase = "IntVar";
			JFieldVar field = definedClass.field(JMod.PRIVATE, int.class,
					fieldName);
			comment = field.javadoc();
			commentString = "My int variable";
			comment.append(commentString);
			String getterMethodName = "get"
					+ fieldNameWithFirstLetterToUpperCase;
			JMethod getterMethod = definedClass.method(JMod.PUBLIC, int.class,
					getterMethodName);
			comment = getterMethod.javadoc();
			commentString = "Method to get " + fieldName + "";
			comment.append(commentString);
			JCommentPart commentPart = javadoc.addReturn();
			commentString = "The " + fieldName + ".";
			commentPart.append(commentString);
			JBlock block = getterMethod.body();
			block._return(field);
			String setterMethodName = "set"
					+ fieldNameWithFirstLetterToUpperCase;
			JMethod setterMethod = definedClass.method(JMod.PUBLIC, Void.TYPE,
					setterMethodName);
			comment = setterMethod.javadoc();
			commentString = "Method to set " + fieldName + "";
			comment.append(commentString);
			String setterParameter = "intVarParam";
			commentPart = javadoc.addParam(setterParameter);
			commentString = "The " + fieldName + " to set.";
			commentPart.append(commentString);
			setterMethod.param(int.class, setterParameter);
			setterMethod.body().assign(JExpr._this().ref(fieldName),
					JExpr.ref(setterParameter));
			codeModel.build(new File("."));
		} catch (JClassAlreadyExistsException e) {
			// ...
		} catch (IOException e) {
			// ...
		}

and here’s the commented class:

package net.cardosi;

/**
 * My wonderful class
 * 
 */
public class MyNewClass {

    /**
     * My int variable
     * 
     */
    private int intVar;

    /**
     * Method to get intVar
     * 
     * @return
     *     The intVar.
     */
    public int getIntVar() {
        return intVar;
    }

    /**
     * Method to set intVar
     * 
     * @param intVarParam
     *     The intVar to set.
     */
    public void setIntVar(int intVarParam) {
        this.intVar = intVarParam;
    }

}

Don't miss the next part about JExpression!

Advertisements

3 thoughts on “Tutorial on Java code generation with CodeModel – Javadoc

  1. Hey,
    your blog is really helpful and thanks for that.
    Although I have a question: Is there a possibilty, that when I’m making a field in class using JFieldVar and class.fields(…), I may use a type that doesn’t exist yet? For example:
    JFieldVar fieldVar = definedClass.field(JMod.PRIVATE, TYPE_THAT_NOT_EXIST, fieldName);

    Like

    • Yep,
      JDefinedClass has four field() methods; two of them use Class as parameter (like in the given example) but the other two accept a JType, that is (indirectly) extended by JDefinedClass.
      So, the following snippet work (just for demo, it create a class with a field of the same type):

      JCodeModel codeModel = new JCodeModel();
      try {
      String className = "net.cardosi.ChildedClass";
      JDefinedClass definedClass = codeModel._class(className);
      JDocComment javadoc = definedClass.javadoc();
      String commentString = "My wonderful class with a child.";
      javadoc.append(commentString);
      String fieldName = "childedClassVar";
      String fieldNameWithFirstLetterToUpperCase = "ChildedClassVar";
      JFieldVar field = definedClass.field(JMod.PRIVATE, definedClass,
      fieldName);
      javadoc = field.javadoc();
      commentString = "My ChildedClass variable";
      javadoc.append(commentString);
      String getterMethodName = "get"
      + fieldNameWithFirstLetterToUpperCase;
      JMethod getterMethod = definedClass.method(JMod.PUBLIC,
      definedClass, getterMethodName);
      javadoc = getterMethod.javadoc();
      commentString = "Method to get " + fieldName + "";
      javadoc.append(commentString);
      JCommentPart commentPart = javadoc.addReturn();
      commentString = "The " + fieldName + ".";
      commentPart.append(commentString);
      JBlock block = getterMethod.body();
      block._return(field);
      String setterMethodName = "set"
      + fieldNameWithFirstLetterToUpperCase;
      JMethod setterMethod = definedClass.method(JMod.PUBLIC, Void.TYPE,
      setterMethodName);
      javadoc = setterMethod.javadoc();
      commentString = "Method to set " + fieldName + "";
      javadoc.append(commentString);
      String setterParameter = "childedClassVarParam";
      commentPart = javadoc.addParam(setterParameter);
      commentString = "The " + fieldName + " to set.";
      commentPart.append(commentString);
      setterMethod.param(definedClass, setterParameter);
      setterMethod.body().assign(JExpr._this().ref(fieldName),
      JExpr.ref(setterParameter));
      codeModel.build(new File("."));
      } catch (JClassAlreadyExistsException e) {
      // ...
      } catch (IOException e) {
      // ...
      }

      And here’s the result:

      package net.cardosi;

      /**
      * My wonderful class with a child.
      *
      */
      public class ChildedClass {

      /**
      * My ChildedClass variable
      *
      */
      private ChildedClass childedClassVar;

      /**
      * Method to get childedClassVar
      *
      * @return
      * The childedClassVar.
      */
      public ChildedClass getChildedClassVar() {
      return childedClassVar;
      }

      /**
      * Method to set childedClassVar
      *
      * @param childedClassVarParam
      * The childedClassVar to set.
      */
      public void setChildedClassVar(ChildedClass childedClassVarParam) {
      this.childedClassVar = childedClassVarParam;
      }

      }

      Best

      G.

      Like

  2. Pingback: Homepage

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