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にデータを代入しようとする場合、外側のコンテキストだけがその変更の対象となり、
内側のコンテキストにはデータが代入されません。