高度なカスタマイズ > Info*Engine ユーザーガイド > カスタムタグライブラリ > 定義式言語のサポート
  
定義式言語のサポート
定義式言語 (EL) とは、単純な文字列構文を使用して、動的変数のコンテンツの参照をいくつかの考えられるソースから解除するためのメカニズムです。EL は、カスタムタグ内のみで使用でき、webjectparamtask などの core ライブラリのタグ内では使用できません。さらに、ここで説明する EL の構文は、JSP ページでは使用できません。ただし、これは、JSP ページ内から使用できる JSTL 1.0 または JSP 2.0 でサポートされている EL と似ています。
* 
パフォーマンス上の理由により、EL を必要としないカスタムタグの属性では EL が使用できないようにすることをお勧めします。
タスク著作者は、EL をサポートするカスタムタグの属性を使用して、実行時に以下に対して評価される定義式を埋め込むことができます。
VDB
@FORM や @SERVER などのコンテキストコレクション
タスクレットコンテキスト
現在のリクエストの IeContext オブジェクト (リクエスト範囲のコンテキスト変数を保持)
これらのロケーションが定義式によって取得される情報のソースとなるため、必要な情報を定義式内でさらに絞り込むことができます。
定義式ではアクセッサを使用することもできるため、括弧 ([ ]) で情報をインデックシングして配列、リスト、およびマップを生成したり、. 文字を使用して Java Beans のプロパティの参照を解除したりできます。たとえば、インデックシングでリストを生成する定義式は ${listName[1]} と記述でき、これは "listName" というリストの 2 番目の要素を取得します。インデックシングでマップを生成する場合は ${mapName['key']} と記述できます。Java Beans からプロパティを取得する場合は ${employee.name} と記述でき、これは employee によって参照されている Java Beans での getName() メソッドの呼び出しによる結果を返します。
定義式は、たとえば以下のように複雑にすることもできます。
${employees['123'].name}
これは、123 キーを使用して Java Beans をマップから取得し、その Java Beans で getName() メソッドを呼び出して、その Java Beans から name プロパティを取得します。このセクション全体にわたって、ほかの例も示されています。
. 文字は一般的に使用される文字であるため、評価される定義式の次の部分が Info*Engine 要素オブジェクトであるときは、Info*Engine のデータ構造の属性値内で特殊ケース化されます。この場合、評価される定義式の次のテキストによって属性値が指定されます。たとえば、以下の定義式を使用するとします。
${document[0]thePersistInfo.createStamp[0]}
document[0] が "document" というグループの 1 番目の要素に解決する場合は、定義式の意図が壊されないように、thePersistInfo.createStamp 内にある . 文字が特殊ケース化されます。ただし、その他の場合では、. は Java Beans のプロパティの参照を解除し、上記の定義式を分割します。一重引用符 (') や中括弧 ({ }) などのほかの文字も特殊な機能を持つため、エスケープする必要がある場合があります。これらの文字をエスケープするには、これらの文字の前にバックスラッシュ (\) を挿入します。
定義式の評価では、データが VDB およびコンテキストグループから取得されるだけではなく、変数の値がタスクレットコンテキスト (データを含んでいる 1 対のマップ) に解決されます。それぞれのタスクには、変数データを保存するための独自のローカルマップがあります。このマップは、包括的なリクエストの IeContext オブジェクトによって支えられています。Info*Engine ベースのリクエストには、それぞれ独自の IeContext (com.infoengine.util.IeContext) のインスタンスがあり、これには特定のリクエストに固有のコンテキスト情報を保存できます。たとえば、これは、解体されたソースコードの各部分によって共有される必要のある情報を保存するために使用できます。
タスクレットコンテキストの機能は IeContext に似ていますが、これはタスクごとに固有であり、その存続期間はそのタスクが実行される間のみです。ただし、タスクでサブタスクを呼び出してデータを共有するには、リクエスト範囲の変数を IeContext に配置できます。これは、同じリクエスト内で実行されているほかのすべてのコードによって認識されます。/com/infoengine/tlds/iejstl.tld タグライブラリの一部として提供されている set タグには "requestScope" という引数があり、これを使用してローカル範囲の変数とリクエスト範囲の変数を区別できます。定義式の評価中、ローカルのタスクレットコンテキストが特定され、変数がない場合は IeContext が参照されます。これは、ローカル変数のデータがリクエスト範囲の変数のデータをオーバーライドすることを意味します。詳細については、set タグを参照してください。
* 
EL と標準の Info*Engine 代入構文を区別することはできないため、EL は Info*Engine の core タグ (ie:param データ属性など) 内では使用できません。<%=evaluateExpression("${x}")%> などの標準の JSP のような定義式を使用して、プログラムで属性に定義式を含めることはできます。
以下に例を示します。
<c:set var=”a” value=”${array[0]}” />
<c:set var=”a” value=”${map[‘a’]}” />
および
<ie:param name=”COUNT” data=”<%=evaluateExpression(“${group.elementCount}”)%>” />
定義式は、その個々の部分が定義式の評価時に対応するかぎり、単純にすることも複雑にすることもできます。以下に例を示します。
<!-- fetch the first element within the variable ‘list’ which
is a list of Map objects and then fetch the value of ‘a’
within that Map. -->
<c:set var=”a” value=”${list[0][‘a’]}” />
<!-- I have a group with elements containing an attribute named
‘mapAtt’ which is a map that I can index into -->
<c:set var=”a” value=”${myGroup[0]mapAtt[0][‘a’]}” />
定義式は、Java Beans のプロパティと同じようにアクセスされる変数オブジェクトで、引数を取らない get メソッドを呼び出すことができます。以下に例を示します。
<!-- populate the eCount variable with the number of elements
in “myGroup” -->
<c:set var=”eCount” value=”${myGroup.elementCount}”>
1 つの文字列に複数の任意の定義式を埋め込むことができます。以下に例を示します。
<c:if test=”${myGroup==null || myGroup.elementCount!=10}”>
<c:choose>
<c:when test=”${myGroup==null}”>
<c:set var=”err” value=”Group myGroup is null” />
</c:when>
<c:otherwise>
<c:set var=”err”
value=”Group myGroup must have 10 elements but it has ${myGroup.elementCount}” />
</c:otherwise>
</c:choose>
<ie:webject name=”Throw-Exception” type=”MGT”>
<ie:param name=”MESSAGE” data=”<%=getContextValue(“err”)%>” />
</ie:webject>
</c:if>
JSP の定義式とは異なり、Info*Engine の EL は、Info*Engine の実行時の概念に統合されます。定義式の評価中、タスクのコンテキストコレクションと VDB は、タスクレットおよびリクエストコンテキストの前に参照されます。以下に例を示します。
<c:set var=”a” value=”${@FORM[]a[]}” />
<c:forEach var=”elm” list=”${myGroup}”>
<!-- executes once for each element in myGroup -->
</c:forEach>
<c:forEach var=”a” list=”${myGroup[0]a[*]}”>
<!-- executes once for each value of the a attribute
within the first element of myGroup -->
</c:forEach>
JSP とは異なり、Info*Engine では定義式内で演算子を使用できません。core カスタムタグライブラリは、c:setc:if/c:when タグでいくぶん具体的に EL のサポートを拡張します。これらのタグは、後で簡単に説明する tasklet.evaluateExpression(String) メソッドを内部で使用して EL を拡張することにより、それぞれの目的を達成します。以下に例を示します。
<!-- the test attribute is broken into separate expressions
that are evaluated independently in order based on the
conditional expression to be evaluated.
in this case ${@FORM[]doSomething[]} ${myGroup} and
${myGroup.elementCount}. -->
<c:if test=”${@FORM[]doSomething[]==true &amp;&amp; myGroup!=null &amp;&amp;
myGroup.elementCount>0}”>
<c:set var=”idx” value=”0” />
<c:forEach var=”elm” list=”${myGroup}”>
<c:set var=”mod” value=”${idx%2}”>
<c:choose>
<c:when test=”${mod==0}”><!-- even -->/c:when>
<c:otherwise>!<-- odd -->/c:when>
</c:choose>
<!-- similar to if/when set may evaluate expressions independently
as necessary, in this case ${idx} to get what to add 1 to. -->
<c:set var=”idx” value=”${idx+1}” />
<c:forEach>
</c:if>
EL と Java スクリプトレットの統合をサポートするため、com.infoengine.SAK.Tasklet には、コンテキスト変数との対話をサポートし、定義式のプログラムによる評価を可能にするためのメソッドが定義されています (カスタムタグライブラリ内から再利用するために)。
たとえば、以下のメソッドは、タスク範囲のタスクレットコンテキスト内に変数を設定します。
public final void setContextValue ( String name, Object value );
以下のメソッドは、タスク範囲またはリクエスト範囲のタスクレットコンテキスト内に変数を設定します。requesttrue に設定されていると、その変数は同じリクエスト内のほかのタスクで使用できます。
public final void setContextValue ( String name, Object value, boolean request );
以下のメソッドは、タスクレットおよびリクエストコンテキスト内で定義されているすべての変数の名前を取得します。
public final Set<String> getContextKeys();
以下のメソッドは、コンテキスト内から名前で変数を取得します。
public final Object getContextValue ( String value );
以下のメソッドは、定義式を評価し、結果として生成されるオブジェクトまたは null を返します。定義式内の構文の問題または定義式の実行時評価に関連する例外が発生します。
public Object evaluateExpression ( final String expression ) throws IEException;
以下に例を示します。
<%
// programmatically sets a context variable that is an array of strings
setContextValue ( “myArray”, new String [] { “a”, “b”, “c” } );
// fetches a group named myGroup from the VDB
// ONLY for illustration
Group g = (Group)evaluateExpression ( “${myGroup}” );
// wouldn’t do this but fetches the above programmatically populated
// myArray variable
String [] myArray = (String [])getContextValue ( “myArray” );
%>
<c:forEach var=”one” list=”myArray”>
<!-- will run three times, a, b and c -->
<c:set var=”message” value=”one is ${one}” />
</c:forEach>