Ymirでの標準のビューテンプレート記述言語はZPT(Zope Page Template)です。ZPTエンジンとしてSkirnirプロジェクトから公開されているタグベーステンプレートエンジン構築フレームワークFreyja(フレイヤ)に含まれているZPT実装(以下単にFreyjaと呼びます)を使っています。
Freyjaは基本的にオリジナルのZPTの仕様に従っていますが、いくつかの違いがあります。Freyjaの実装とオリジナルの仕様との相違点についてはFreyjaのドキュメントを参照して下さい。
なおオリジナルのZPT仕様の詳細についてはZPTのサイトにある
を参照して下さい。
以下ではYmirでだけ有効なFreyjaの拡張仕様について説明します。
組み込み変数
Ymirでは次の変数が組み込み変数として追加されています。
名前 | 値 |
---|---|
ymirRequest | org.seasar.ymir.Requestオブジェクト |
container | org.seasar.framework.container.S2Containerオブジェクト |
messages | メッセージリソースが格納されているorg.seasar.ymir.message.Messagesオブジェクト |
token | トランザクショントークンを扱うためのorg.seasar.ymir.token.Tokenオブジェクト。詳しい使い方については「トランザクショントークン」を参照のこと |
notes | 制約違反のメッセージを保持するorg.seasar.ymir.message.Notesオブジェクト |
variables | その時点での変数空間を表すnet.skirnir.freyja.VariableResolverオブジェクト。この組み込み変数を使うことで、例えば変数名をnameという名前で定義しておき、variables/?nameとして動的な変数名から値を取得することができる |
param-self | リクエストパラメータとPageオブジェクトを表すオブジェクト(Ymir-1.0.2以降)。例えばparam-self/nameというTAL式は、「リクエストパラメータにnameという名前のパラメータがあればその値、なければPageオブジェクトのnameプロパティの値」というように評価されます。param-selfを使うと、フォーム画面で「初期表示はPageオブジェクトのプロパティ値を表示するが、バリデーションエラー時にはユーザによって入力された値を表示する」というケースにおいて、param-self/nameのようにZPTをシンプルに記述することができます。 |
特別なrequestスコープオブジェクト
Ymirでは以下のオブジェクトがrequestスコープにバインドされています。
名前 | 値 |
---|---|
self | 処理対象のPageオブジェクト。リクエストパスに対応するPageコンポーネントが存在しない場合は未定義 |
したがって、例えばPageオブジェクトのtitleプロパティの値を参照したい場合は「self/title」と書けばよいことになります。
TALESのPath式
ここではYmirにおけるTALESのPath式の扱いに関して説明します。
最初のセグメントの解決手順
Path式の最初のセグメント(「first/second/third」の「first」の部分) は次の順序に従って解決されます。
- "first"の部分が正の数値文字列であれば文字列をIntegerに変換した値。
- "first"の部分が"CONTEXTS"であれば組み込み変数CONTEXTSの値。
- tal:defineやtal:repeatで生成された変数スコープに"first"という変数があればその値。変数スコープは一番近いものから外側に向けてグローバル変数スコープまで検索される。
- "first"の部分がFreyjaの組み込み変数名(nothing、null、default、CONTEXTS、true、false、request、response、session、application、locale、element、attrs、repeat)であれば組み込み変数の値。
- HttpServletRequest#getAttribute("first") の値がnullでなければその値。
- セッションが張られていてかつHttpSession#getAttribute("first") の値がnullでなければその値。
- ServletContext#getAttribute("first") の値がnullでなければその値。
- "first"の部分がYmirの組み込み変数名(ymirRequest、container、messages、token、variables)であれば変数の値。
- HttpServletRequest#getParameter("first") の値がnullでなければその値。
- HttpServletRequest#getAttribute("self")の値がnullでなく、かつその値オブジェクトが"first"という名前のプロパティを持てばその値。
- 上記のいずれにも該当しない場合はnull。
セグメントの解釈
例えばPath式で「self/name」と書いた場合、selfを解決した結果であるオブジェクトについてセグメント「name」を解釈した結果が最終結果になります。
セグメントは基本的にはオブジェクトのプロパティと解釈されます。したがって、例えば上記の例ではselfに対応するオブジェクトについてgetName()メソッドを呼び出した結果が最終結果になります。
オブジェクトの型によっては特別な解釈がなされますが、Ymirではさらに以下のような解釈が行なわれます。解釈は以下の表の上から順に適用され、結果がnullでExceptionがスローされなければさらに下の解釈が適用されます。
オブジェクトの型 | 解釈 |
---|---|
org.seasar.ymir.message.Messages |
セグメントが「%」で始まる場合、「%」を除いた文字列を引数としてgetMessage()を呼び出した結果。そうでない場合はセグメント文字列を引数としてロケールなしでgetProperty()を呼び出した結果。 結果がnullである場合はMessageNotFoundRuntimeExceptionがスローされる。 |
org.seasar.kvasir.util.collection.I18NPropertyReader | セグメントが「%」で始まる場合、「%」を除いた文字列を引数として現在のロケールについてgetProperty()を呼び出した結果。そうでない場合はセグメント文字列を引数としてロケールなしでgetProperty()を呼び出した結果。 |
org.seasar.kvasir.util.collection.PropertyReader | セグメント文字列を引数としてgetProperty()を呼び出した結果。 |
org.seasar.kvasir.util.collection.AttributeReader | セグメント文字列を引数としてgetAttribute()を呼び出した結果。 |
org.seasar.ymir.message.Notes | セグメントが「size」である場合、Notes#size()の結果。「size(XXX)」の形である場合、「XXX」の部分の文字列を引数としてNotes#size(String)を呼び出した結果。「categories」である場合、Notes#categories()の結果。それ以外の場合、セグメント文字列をNotesのカテゴリ文字列とみなして、そのカテゴリに属するNoteが存在するならNotes#get(カテゴリ文字列)の返り値。 |
org.seasar.ymir.message.Note | セグメントが「%value」である場合、Note#getValue()の返り値をキーとして現在のロケールについてメッセージリソースを検索した結果のメッセージ文字列。メッセージ文字列が見つからなかった場合はMessageNotFoundRuntimeExceptionがスローされる。詳細についてはNotesオブジェクトを使ったメッセージ文字列の構築を参照のこと。 |
decorate式(Ymir-1.0.7以降)
decorate式はtal:attributesの中でclass属性の値を設定するためだけに利用できる式で、以下の構文で記述します:
decorate:*条件* with *[!]class属性に追加する値*
この式の値は、条件が真の場合は指定された値を現在のclass属性に追加したものになります。指定された値が既にclass属性の値に含まれている場合は何もしません。条件が偽の場合は、この式の値は現在のclass属性の値になります。
「条件」にはtal:conditionに書くような条件式を書くことができます。
「class属性に追加する値」には文字列で値を書いて下さい。
なお値の直前に「!」をつけると、既存のclass属性が置換されます。例えば項目「date」を表すinputタグについて、バリデーションエラーの時に動的にclass属性に「error」という値を追加するための記述例は以下の通りです:
<input type="text" name="date" tal:attributes="class decorate:notes/contains(date) with error" />
decorate-by-notes式(Ymir-1.0.7以降)
decorate-by-notes式はdecorate式とほぼ同じですが、メッセージ(Notes)表示に特化しています。具体的には、decorate式の条件部に「notes/contains(NAME)」と書く代わりに単に「NAME」と書くことができます(逆に、普通の条件式を書くことはできません。):
decorate-by-notes:[*カテゴリ名*] with *[!]class属性に追加する値*
「カテゴリ名」で指定されたカテゴリに属するNoteが現在のNotesに存在する場合に、指定された値がclass属性に追加されます。
カテゴリ名は省略することができます。省略した場合、現在のNotesになんらかのメッセージが存在する場合に指定された値がclass属性に追加されます。例えば項目「date」を表すinputタグについて、バリデーションエラーの時に動的にclass属性に「error」という値を追加するための記述例は以下の通りです:
<input type="text" name="date" tal:attributes="class decorate-by-notes:date with error" />
その他
- org.seasar.ymir.zpt.SessionIdEmbeddingInterceptorのコンポーネント定義をapp.diconやymir++.diconに追加することで、ZPTテンプレート中の「action」「href」「src」属性に書いたページ相対URL(「.」「./~」「..」「../~」形式のURL)に必要に応じて自動的にセッションIDが付与されるようになります(Ymir-1.0.2以降)。なお、ymir-skeleton-generic-1.0.2以降で生成したYmirプロジェクトにはymir++.diconにこのコンポーネント定義が記述されていますので、この機能が有効になっています。必ずCookieが利用できる前提であるケースやセッションを利用しないケースなど、この機能が不要な場合はymir++.diconからこのコンポーネント定義を除去しても構いません。