argius note

プログラミング関連

Apache Velocity

汎用テンプレートエンジン。近々、ソースコードジェネレータを作ることになりそうなので調べておこうかな、と思いました。割と前から気になってはいたんですが、なかなか手をつけられずにいたんですよ。
どの辺が汎用かっていうと、データを決める部分はjava.util.Mapに似た構造のクラスで、合成結果の出力先はjava.io.Writerで、テンプレートはスクリプト風の独自テンプレート言語(VTL)で記述するところです。最後のは汎用じゃないように見えますが、独自言語と言っても、既存のスクリプト系言語をベースにしたようなものなので、余程複雑なことをやるのでなければ一瞬で理解できるでしょう。

では練習をしてみます。テキストファイル"test.vm"に次のテンプレートを記述します。

#set($v = "123")
name = $name
$v
#if ($number == 3) three! #else not three. #end

 #foreach ($i in $list) element = $i #end

実行するJavaのコードはこんな感じで。(このブロック全体は"throws Exception"が必要です。)

Velocity.init();
VelocityContext context = new VelocityContext();
context.put("name", "argius");
context.put("number", new Integer(3));
context.put("list", Arrays.asList(new Object[]{"@", "*"}));
Template template = Velocity.getTemplate("test.vm");
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
template.merge(context, out);
out.flush();

"VelocityContext"は、インタフェースとしてはMapのような感じで使えば良いようです。コンストラクタにMapのインスタンスを渡せば、Mapからの変換もできます。"Writer"には、PrintWriterやFileWriterなどの標準クラスが使用できます。最後に、"Template"に、"context"と"Writer"を渡せば合成完了となります。
実行結果です。ここでは標準出力に結果を印字しています。ここでは、PrintWriter#flush()を実行しないと出力されませんので注意。

name = argius
123
 three! 
  element = @  element = * 

はい、できました。物凄くとっつき易い仕様ですね。例えば、WriterにServletResponse#getWriter()を使えば、サーブレットJSPの代わりに使えたりします。実際、Velocityを採用しているフレームワークも多いようですね。