7. TemplateクラスとVelocityContextクラス
2006.01.12 株式会社四次元データ 里見玲爾
この章ではVelocityの核となるTemplateクラスとVelocityContextクラスについて説明します。ちなみに執筆時のバージョンは1.3.1です。
7.1. org.apache.velocity.Template
Templateクラスはテンプレートの作業すべてを制御するために使うクラスです。
7.1.1. メソッド
Templateクラスでは、次の2つのメソッドが定義されています。
| メソッド | 解説 | 返り値 |
|---|---|---|
| initDocument() | 文書を初期化します | void |
| merge(Context context, Writer writer) | テンプレートオブジェクトとVelocityContextの値をマージするメソッドで、 マージした結果をWriterクラスのインスタンスに書き込みます | void |
mergeメソッドはVelocityで重要な役割を果たすメソッドです。以下のようにして使用します。
(略)
try{
Template template = Velocity.getTemplate("sample.vm");
template.merge(context, sw);
}catch(ResourceNotFoundException e){
//テンプレートが見つからなかった場合の処理
}catch(ParseErrorException e){
//テンプレート内の構文に関する例外などがあったときの処理
}catch(java.lang.Exception e){
//その他の例外があったときの処理
}
(略)
上の例で、mergeメソッドとgetTemplateメソッド(下で解説)は各種例外を投げる可能性があるため、 catchで例外を取得しています。
7.2. org.apache.velocity.VelocityContext
VelocityContextクラスは、テンプレートの変数部分に代入する値を格納するクラスです。 データの蓄積にはHashMapを使用しています。
7.2.1. メソッド
VelocityContextクラスはorg.apache.velocity.contextパッケージのContextインタフェースを実装したAbstractContextクラスのサブクラスで、 このAbstractContextではコンテキストの中身を制御するメソッドが定義されています。
| メソッド | 解説 | 返り値 |
|---|---|---|
| internalContainsKey(java.lang.Object key) | 引数のキーの値が存在するかどうか調べる | boolean |
| internalGet(String key) | 引数のキーと対応するデータの値をオブジェクトで返す | java.lang.Object |
| internalGetKeys() | キーの一覧のリストを配列で返す | java.lang.Object[] |
| internalPut(String key, java.lang.Object value) | 引数のキーと対応付けて データを格納する。返り値はそのキーで保管されていた以前のオブジェクト | java.lang.Object |
| internalRemove(java.lang.Object key) | 引数のキーとそれに対応するデータのペアを削除する。 返り値は削除したオブジェクト | java.lang.Object |
またjava.lang.Objectのclone()メソッドでコンテキストオブジェクトのコピーを生成します。
7.2.2. コンテキストのラッピング
VelocityContextにはデフォルトのコンストラクタの他にもオーバーロードされたコンストラクタがいくつかあり、 その中のひとつに、
VelocityContext(Context context)
の形のコンストラクタがあります。このコンストラクタは他のコンテキストをラッピング(包み込み)するものです。
コンテキストのラッピングとは、コンテキストを別のコンテキストに接続するための仕組みで、よくコンテキストのチェーンとも呼ばれます。
このチェーンの概念はVelocityのコンテキスト設計の画期的な機能で、階層化されたデータアクセスなどに使えます。
次の例により説明します。
(略)
VelocityContext context1 = new VelocityContext();
context1.put("office", "4DD");
context1.put("description", "This is context1");
VelocityContext context2 = new VelocityContext( context1 );
context2.put("lang", "Java");
context2.put("description", "This is context2");
template.merge(context2, writer);
(略)
上の例のようにしてマージされた場合に、テンプレート内ではcontext1とcontext2のどちらに格納されたアイテムにもアクセスできます。
これは当然2つのコンテキストに同一のキーがないということが前提となりますが、上の例では"description"キーが重複しています。
このような場合にテンプレートで$descriptionにアクセスすると外側のコンテキスト、つまり上の例ではcontext2の値"This is context2"が取り出されます。
しかしラッピングをしてcontext2を生成した時点で値が上書きされるわけではなく、
テンプレートがマージされ、レンダリングする前には"This is context1"の値も保持されていますので、
context1.get("description")によってアクセスすることができます。
またテンプレート内から#setなどにより$descriptionにデータを代入しようとする場合、外側のコンテキストだけがその変更の対象となり、
内側のコンテキストにはデータが代入されません。

