#macro スクリプト要素で、VTL
テンプレートで繰り返し出てくる部分を定義できます。
Velocimacro は、単純なものから複雑なものまで広範囲にわたるシナリオで非常に役立ちます。
次の Velocimacro は、
キーストロークを節約し、入力ミスを少なくするためだけに作られたものですが、
Velocimacro の概念を紹介するのに役立つでしょう。
 |
 |
 |
 |
#macro( d )
<tr><td></td></tr>
#end
|
 |
 |
 |
 |
この例で定義されている Velocimacro は d です。そして、
それは他の VTL 指示子 と同じような方法で呼び出すことができます:
このテンプレートが呼ばれると、Velocity は #d() を一つの、
空のデータセルを含んでいる列と置換します。
Velocimacro は任意の数の引数を取ることが出来ます
(最初の例で示したとおり引数なしでもかまいません)。
ただし、Velocimacro が呼び出されるとき、
定義されたのと同じ数の引数で呼ばれなければなりません。
多くの Velocimacro は、上で定義したものより多くの引数を含みます。
これは、色と配列という2つの引数をとる Velocimacro です。
 |
 |
 |
 |
#macro( tablerows $color $somelist )
#foreach( $something in $somelist )
<tr><td bgcolor=$color>$something</td></tr>
#end
#end
|
 |
 |
 |
 |
この例(tablerows)で定義されている Velocimacro は、2つの引数をとります。
最初の引数は、$color となり、2番目の引数は、$somelist となります。
VTL テンプレートに入れられるものは何でも、Velocimacro の本体に入れることができます。
tablerows Velocimacro は、foreach 文です。
2つの #end 文が、#tablerows Velocimacro の定義にありますが、
最初の end で #foreach が終了し、二番目の end で Velocimacro 定義が終了します。
 |
 |
 |
 |
#set( $greatlakes = ["Superior","Michigan","Huron","Erie","Ontario"] )
#set( $color = "blue" )
<table>
#tablerows( $color $greatlakes )
</table>
|
 |
 |
 |
 |
$greatlakes が $somelist に代わることに注意してください。
#tablerows Velocimacro が上記のように呼ばれるとき、以下の出力が生成されます。
 |
 |
 |
 |
<table>
<tr><td bgcolor="blue">Superior</td></tr>
<tr><td bgcolor="blue">Michigan</td></tr>
<tr><td bgcolor="blue">Huron</td></tr>
<tr><td bgcolor="blue">Erie</td></tr>
<tr><td bgcolor="blue">Ontario</td></tr>
</table>
|
 |
 |
 |
 |
Velocimacro は Velocity テンプレート内で インライン で定義できますが、
その場合は同じ Web サイトの他の Velocity テンプレートには利用できません。
全てのテンプレートで共有できるような Velocimacro を定義することには、
明らかにいくつかの利点があります。例えば、多数のテンプレートで
Velocimacro をいちいち定義する必要を減らせますし、それにより作業量が節約されたり、
エラーの可能性が減りますし、一つのマクロに対する一箇所の変更が複数のテンプレートに反映されることを保証します。
#tablerows($color $list) Velocimacro が Velocimacro
テンプレートライブラリで定義されている場合、
このマクロはどの通常のテンプレートでも使うこともできます。
それは、何度でも使えますし、どんな用途でも使うことが出来ます。
菌類百科専門の mushroom.vm テンプレートの中で、
#tablerows Velocimacro は、
典型的なキノコの各部分をリストするために呼び出すことができます:
 |
 |
 |
 |
#set( $parts = ["volva","stipe","annulus","gills","pileus"] )
#set( $cellbgcol = "#CC00FF" )
<table>
#tablerows( $cellbgcol $parts )
</table>
|
 |
 |
 |
 |
mushroom.vm の要求を満たすとき、Velocity は
#tablerows Velocimacro をテンプレートライブラリ
(velocity.properties ファイルにおいて定義されています) から見つけて、
以下の出力を生成します。
 |
 |
 |
 |
<table>
<tr><td bgcolor="#CC00FF">volva</td></tr>
<tr><td bgcolor="#CC00FF">stipe</td></tr>
<tr><td bgcolor="#CC00FF">annulus</td></tr>
<tr><td bgcolor="#CC00FF">gills</td></tr>
<tr><td bgcolor="#CC00FF">pileus</td></tr>
</table>
|
 |
 |
 |
 |
Velocimacro 引数
Velocimacro は、以下の VTL 要素のどれでも引数として取ることができます。
-
リファレンス : 「$」で始まる全て
-
文字列リテラル : "$foo" や 'hello'のようなもの
-
数値リテラル : 1, 2 など
-
整数範囲 : [1..2] や [$foo .. $bar]
-
オブジェクト配列 : ["a", "b", "c"]
-
boolean 値の true
-
boolean 値の false
Velocimacro の引数としてリファレンスを渡す際、
リファレンスは「名前渡し」されることに注意してください。
つまり、Velocimacro 内で使われるたびにその値が「生成される」ことを意味します。
この機能を使って、リファレンスにメソッド呼び出しを渡して、
使うたびにそのメソッドを呼ぶようにできます。
例えば、以下に示すように Velocimacro を呼び出すと、
 |
 |
 |
 |
#macro( callme $a )
$a $a $a
#end
#callme( $foo.bar() )
|
 |
 |
 |
 |
結果として、リファレンス $foo のメソッド bar() が3回呼び出されます。
一見、この機能は驚くべきことのように見えます、
しかし、あなたが Velocimacro の背景にある最初の動機 ―
よく使われる VTL をカット&ペーストすることによる重複を除去する ―
を考慮すれば、納得できるかと思います。
この機能により、 Velocimacro に「状態を保持する」(Stateful) オブジェクト (例えばテーブル列に色をつけるために繰り返しシーケンスで色を生成するオブジェクト) を渡すようなことができます。
この機能を回避する必要があるならば、常にメソッドから値をリファレンスとして取得し、
それを渡せばよいのです。
 |
 |
 |
 |
#set( $myval = $foo.bar() )
#callme( $myval )
|
 |
 |
 |
 |
Velocimacro プロパティ
velocity.propertiesファイル内の何行かを使えば、Velocimacro を柔軟に実装できます。
注意: 開発者ガイドも参照してください。
velocimacro.library
─
全ての Velocimacro テンプレートライブラリのコンマ区切りリスト。
デフォルトでは、Velocity は VM_global_library.vm
というライブラリのみを探します。
設定されたテンプレートパスは Velomacro ライブラリを見つけるのに使用されます。
velocimacro.permissions.allow.inline
─
このプロパティは true または false の値を取ることができ、
Velocimacro を通常のテンプレートで定義できるかどうか判定します。
デフォルト (true) では、テンプレートで Velocimacro を定義できます。
velocimacro.permissions.allow.inline.to.replace.global
─
このプロパティは true または false の値を取ることができ、
テンプレート内でインラインで定義された Velocimacro が
グローバルで定義されたテンプレート
(スタートアップ時にvelocimacro.library
プロパティ経由でロードされたもの)
を上書きできるかどうかを指定します。
デフォルトでは false なので、
スタートアップでロードされたテンプレートライブラリで定義されたものは
インラインの Velocimacro では上書きできません。
velocimacro.permissions.allow.inline.local.scope
─
このプロパティは true または false の値を取ることができ、
デフォルトは false です。
インラインで定義された Velocimacro が、
定義したテンプレートでだけ「見える」かどうかを制御します。
つまり、このプロパティを true にすると、定義されたテンプレート内でのみ有効な
インライン VM を定義することが出来ます。
これを使った、手の込んだ VM のテクニックがあります。
グローバルな VM が別のグローバルな VM を呼ぶ場合、
テンプレートはインラインスコープで、前者の VM から呼ばれる後者の
VM のプライベート実装を定義できます。
他のどのテンプレートにも影響ありません。
velocimacro.context.localscope
─
このプロパティは true または false の値を取ることができ、
デフォルトは false です。
true のときは、Velocimacro 内の #set() によるコンテキストへの変更はすべて、
Velocimacro に「ローカル」であると扱われて、
コンテキストに永続的な影響を及ぼしません。
velocimacro.library.autoreload
─
このプロパティは Velocimacro の自動ロードを制御します。
デフォルトの値は false です。
true にセットされると、呼び出された Velocimacro に対応する
Velocimacro ライブラリのソース変更がチェックされ、必要に応じてリロードされます。
これにより、ちょうど普通のテンプレートでできるように、
アプリケーションやサーブレットコンテナを再起動せずに Velocimacro
ライブラリを変更、テストすることができます。
このモードはリソースローダーでキャッシングを off にした時
(例えば file.resource.loader.cache = false にした時)
だけ有効です。
この機能は開発用で、本番環境用ではありません。
Velocimacro まめ知識
現在、Velocimacro はテンプレートで最初に使われる前に定義されていなければなりません。
つまり、 #macro() 宣言が Velocimacro を使う前に出てくる必要があります。
インラインの #macro() 指示子を含んでいるテンプレートを #parse()
しようとするときには、このことに気をつける必要があります。
というのも、 #parse() は実行時に発生し、
パーサはテンプレート中の VM のように見える要素が VM かどうかをパース時に判定するため、
VM 宣言を #parse() しても期待したようには動かないのです。
これを回避するには、単に velocimacro.library 機能を使ってください。
Velocity はあなたの VM を起動時にロードします。