CodeModelの使い方(その1)

WEB+DB PRESS Vol.50を読んでいたら、Sun(Oracle?)の川口耕介さんの新連載の中で「CodeModel」というプロダクトの名前が出てきました。
http://codemodel.dev.java.net

記事の内容自体はJavaアノテーション(というかAPT)の話なのですが、アノテーションの使い方のひとつとしてコードジェネレーションがあり、それを簡単にするためのツールとしてこの「CodeModel」があげられています。

どうやらこのプロダクトは川口さんがJAXB RIを作る中で出来たツールをスピンオフさせたもののようです。


とりあえずこの辺から「codemodel-2.1.jar」をダウンロードしてみました。
サイトをうろうろしてもドキュメントらしきものが見つからないので、JavaDocとにらめっこしながらいろいろいじってみました。

で、超簡単だけど、とりあえずこんな感じ。

import java.io.*;
import com.sun.codemodel.*;

class CodeModelTest{
    public static void main(String[] a) throws Exception{
        JCodeModel cm = new JCodeModel();

        //生成するクラス定義
        JDefinedClass clazz = cm._class("jp.co.hoge.Hoge");
        clazz.constructor(JMod.PUBLIC);  //コンストラクタはpublicで
        
        //privateなインスタンス変数
        JFieldVar name = clazz.field(JMod.PRIVATE, String.class, "name");

        //getter
        JMethod getname = clazz.method(JMod.PUBLIC, String.class, "getName");
        JBlock block = getname.body();
        block._return(name);  //上記で定義したインスタンス変数をreturnする
        
        //setter
        JMethod setname = clazz.method(JMod.PUBLIC, cm.VOID, "setName");
        JVar name_ = setname.param(String.class, "name_");  //メソッド引数
        JBlock block2 = setname.body();
        block2.assign(name, name_);  //ローカル変数からインスタンス変数へセット

        //ソース生成
        cm.build(new File("."));

    }
}

こんな風に書くと

package jp.co.hoge;

public class Hoge {

    private String name;

    public Hoge() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name_) {
        name = name_;
    }

}

こんなソースファイルが生成されます。

自動的にインデントが付いてくれるので良い感じ。
assignメソッドに見られるようにほぼ全ての定義がメソッド化されているので、可変のところ以外は全てコーディングで(=タイプセーフで)出来る、というのが一番のメリットなのかなと。
メソッドで対応できない場合はJFormatterというのでガンガン文字列で書くことも出来るようです。

その他、アノテーションとかJavaDocとか内部クラスとか、いろいろ複雑なことをやるにはどうするのかもう少しいじってみる予定です。