Velocityで独自のディレクティブを作る。

デフォルトで使われているディレクティブは(if、foreach等)、org/apache/velocity/runtime/defaults/directive.properties に定義されている。
directive.propertiesの内容は以下の通り。

directive.1=org.apache.velocity.runtime.directive.Foreach
directive.2=org.apache.velocity.runtime.directive.Include
directive.3=org.apache.velocity.runtime.directive.Parse
directive.4=org.apache.velocity.runtime.directive.Macro
directive.5=org.apache.velocity.runtime.directive.Literal

独自のディレクティブを定義する場合は、velocity.propertiesに以下の形式で定義する。独自のディレクティブを複数定義するときでも、キー名はuserdirectiveでいい。

userdirective=xxx.xxx.xxx.HogeDirective
userdirective=xxx.xxx.xxx.FooDirective

ここに定義されるクラス(xxx.xxx.xxx.HogeDirective)は、org.apache.velocity.runtime.directive.Directiveを実装する必要がある。

Directiveは抽象クラスで、以下のメソッドが定義されている。

public abstract String getName()
public abstract int getType()
public abstract boolean render( InternalContextAdapter context, Writer writer, Node node )
public int getLine()
public int getColumn()
public void init( RuntimeServices rs, InternalContextAdapter context, Node node)
  • getName()は、定義したいディレクティブの名前を返すようにする。
    • 例えば、"hoge"を返すと、#hoge() がディレクティブになる。
    • また、#hoge("foo" "bar") というように、ディレクティブに指定した引数は、init()またはrender()の引数nodeのjjtGetChild(i)から取ることができる。
  • getType()には、org.apache.velocity.runtime.directive.DirectiveConstantsのBLOCKとLINEのいずれかを指定する。
  • getLine()、getColumn()からは、行番号、列番号を取ることができる。
  • init()は、テンプレートのパース後(解析木を作成後)に呼び出される。
    • 引数のRuntimerServiceから、velocity.propertiesの内容を参照したりする。
    • init()呼出し後キャッシュされる。以降、init()は呼ばれない。
    • テンプレート内に出現したディレクティブの数分のDirectiveインスタンスが作成される。
  • render()は、テンプレート実行時(マージ時)に呼び出される。
    • 引数のwriter#write()メソッドで文字列を出力する。