タグ ライブラリのコーディング

Java 開発者は、タグ ハンドラ、TEI クラス (オプション)、サポート クラス (オプション)、および TLD ファイルをコーディングします。また、ライブラリ内のカスタム タグの名前、タグ属性、スクリプト変数、スクリプト変数の使用法、およびスクリプト変数のスコープを文書化します。さらに、タグ ライブラリの JAR ファイルを作成し、それを WEB-INF/lib 内に配置し、必要があれば、Web アプリケーションの web.xml ファイル内に taglib 要素をコーディングします。

タグ ハンドラおよび TEI クラスは、次のいずれかの格納場所に保存します。

推奨されている TLD ファイルの配置方法など、その他のパッキング情報については、"タグ ライブラリのパッケージ化"を参照してください。

クラスとインターフェイス

次の図に示すように、カスタム タグやタグ ライブラリをコーディングするときは、javax.servlet.jsp.tagext パッケージ内のクラスとインターフェイスを使用します。

主なクラスとインターフェイスは次のとおりです。

タグ ライブラリのプログラミングで使用するクラスとインターフェイスの詳細については、JRun の docs ディレクトリ内にある javadocs を参照してください。

JSP 開発者のカスタム タグの使用法

次の例に示すように、JSP 開発者がタグ ライブラリを有効にするには、taglib ディレクティブを使用し、prefix:tagname の変換を使用してカスタム タグをコーディングします。

<%@ taglib prefix="test" uri="DocSamples.tld" %>
<%-- この例では、開始タグと終了タグを組み合わせます。 --%>
<test:hello/>

カスタム タグ内では本文テキストを使用できますが、TLD ファイル内で本文テキストを禁止することができます。タグ ハンドラでは本文テキストと対話できます。これについては、"本文コンテンツとの対話" で説明します。

スクリプト変数と変換時属性の検証を有効にできます。これについては、"TEI クラスのコーディング"で説明します。

単純なタグ ハンドラのコーディング

単純なタグ ハンドラは、親元の TagSupport または BodyTagSupportdoStartTag メソッド、または必要な場合には doEndTag メソッドを書き換えます。本文テキストとは対話しません。本文テキストとの対話がないタグ ハンドラでは、TagSupport クラスを拡張する必要があります。TagSupport を拡張すると、doStartTag メソッドと doEndTag メソッドで、定数として定義されている次の戻り値が使用されることに注意してください。

次のタグ ハンドラは、doStartTag メソッドと doEndTag メソッドから HTML を出力します。JSP でタグ ハンドラを使用するには、TLD ファイルでタグ ハンドラを定義し、それを JSP から呼び出す必要があります。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class SimpleTag extends TagSupport {
  /**
  * Executes when the tag is started.
  */
public int doStartTag() throws JspException {
  try {
    pageContext.getOut().print("<h2>Hello from doStartTag()</h2>");
    // タグの本文でテキストを使用できるようにします。
    return EVAL_BODY_INCLUDE;
  } 
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
}

/**
* Executes with the end tag.
*/
public int doEndTag() throws JspException {
  try {
    pageContext.getOut().print("<h2>Hello from doEndTag()</h2>");
    // ページの評価を継続します。
    return EVAL_PAGE;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}
}

TLD ファイルの作成

TLD は、タグ ライブラリを記述する XML 形式のテキスト ファイルです。JRun では、taglib ディレクティブが含まれているページを解釈するために TLD ファイルが参照されます。taglib ディレクティブには、TLD ファイルを指示する uri 属性が含まれています。taglib ディレクティブの詳細については、"タグ ライブラリのパッケージ化"を参照してください。

taglib 要素は、TLD ファイルのルートです。このファイルは、次の要素から構成されています。

TLD ファイルおよび TLD の形式の詳細については、JavaServer Pages バージョン 1.1 の仕様書を参照してください。

TLD ファイルでのタグの定義

カスタム タグは、TLD ファイル内で tag 要素とそのサブ要素によって定義します。tag 要素の主な目的は、JSP ファイルで使用されているカスタム タグ名をタグ ハンドラのクラス ファイルに関連付けることです。カスタム タグでスクリプト変数を作成する場合は、teiclass 要素を使用して、タグの TEI クラス ファイルを指定する必要もあります。

tag 要素を使用して、属性を定義することもできます。attribute 要素は必須ではありませんが、次のような場合に使用すると便利です。

カスタム タグ属性の詳細については、"属性との対話"を参照してください。

TLD ファイルの例

次の TLD ファイルでは、"単純なタグ ハンドラのコーディング"で示した SimpleTag クラスに対してタグを定義しています。

<?xml version="1.0" ?>
<taglib>
  <tlibversion>1.0</tlibversion>
  <jspversion>1.1</jspversion>
  <shortname>JRun Doc Samples</shortname>
  <tag>
    <name>hello</name>
    <tagclass>SimpleTag</tagclass>
    <bodycontent>JSP</bodycontent>
  </tag>
</taglib>

単純なカスタム タグの呼び出し

JSP 内でカスタム タグの使用を有効にするには、taglib ディレクティブを使用します。taglib ディレクティブでは、タグ名と一緒に使用して特定のタグを呼び出す接頭辞を指定します。

次の JSP コードでは、TLD ファイルの例で定義されている hello タグを呼び出しています。

<html>
<body>
<h1>Simple Custom Tag</h1>
<%@ taglib prefix="test" uri="DocSamples.tld" %>

<test:hello/>

</body>
</html>

属性との対話

属性を受け入れるタグ ハンドラをコーディングできます。属性の機能を有効にするには、タグ ハンドラで次のことを行う必要があります。

属性の使用法と動作は、次のようにカスタマイズできます。

TLD ファイルの指定と TEI クラス ファイルには、強力な検証機能があります。ただし、必要な機能は、Bean に類似した setter メソッドでクラス スコープ変数と対話することだけです。たとえば、次のタグ属性の使用法を有効にするとします。

...
<test:hello username="Joe"/>
...

タグ ハンドラでは、次のコードを実装する必要があります。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class TestParms extends BodyTagSupport
{
  // 属性と同じ名前を持つオブジェクトスコープの変数です。
  String username;

  // JSP コンパイラによって呼び出される setVariablename メソッドです。
public void setUsername(String username) {
  this.username = username;
}

// 最適な getter メソッドです。
public String getUsername() {
  return username;
}
...

タグ ハンドラ全体を示す次の例では、JSP で提供されている include アクション要素を属性を使用してエミュレートしています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import javax.servlet.*;
import java.io.IOException;

public class TestInclude extends TagSupport {
  // 既定値がないので必須です。
  String page;
  // 既定値は true です。
  String flush = "true";

  // setter メソッドです。
public void setPage(String page) {
  this.page = page;
}
public void setFlush(String flush) {
  // 小文字で保存します。
  this.flush = flush.toLowerCase();
}

public int doStartTag() throws JspException {
  // 本文テキストを無視します。
  return SKIP_BODY;
}

  // doEndTag がすべての作業を行います。
public int doEndTag() throws JspException {
  try {
    ServletContext sc = pageContext.getServletContext();
    RequestDispatcher rd = sc.getRequestDispatcher(page);
    if (rd !=null) {
      // アクセス要求および応答
      ServletRequest request = pageContext.getRequest();
      ServletResponse response = pageContext.getResponse();
      // 必要な場合は、バッファを一括消去します。
      if (flush.equals("true")) { 
        pageContext.getOut().flush(); 
      }
      // ファイルをインクルードします。
      rd.include(request, response);
      return EVAL_PAGE;
    }
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
  catch (Exception e) {
    pageContext.getServletContext().log("Error with " + page, e);
  }
  return EVAL_PAGE; 
}
}

TLD ファイルでの属性の定義

TLD ファイル内で属性を定義するには、attribute 要素を使用します。この要素には、次のサブ要素があります。

次の TLD エントリの例では、必須属性とオプション属性を設定しています。

<?xml version="1.0" ?>
<taglib>
  <tlibversion>0.0</tlibversion>
  <jspversion>1.0</jspversion>
  <shortname>test</shortname>
  <tag>
    <name>include</name>
    <tagclass>TestInclude</tagclass>
    <bodycontent>empty</bodycontent>
    <attribute>
      <name>page</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
    </attribute>
    <attribute>
      <name>flush</name>
      <required>false</required>
      <rtexprvalue>false</rtexprvalue>
    </attribute>
  </tag>
  <tag>
    <name>hello</name>
    <tagclass>HelloTag</tagclass>
    <teiclass>HelloTEI</teiclass>
    <bodycontent>JSP</bodycontent>
  </tag>
</taglib>

JSP での属性のコーディング

次の例に示すように、属性はカスタム タグの一部としてコーディングします。

<html>
<body>

<%@ taglib prefix="test" uri="test.tld" %>
<h1>Testing Custom Tags with Parameters</h1>

<test:include page="/includedText.htm" flush="true" />

</body>
</html>

本文コンテンツとの対話

Tag インターフェイスと BodyTag インターフェイスのどちらを使用しても、テンプレート テキスト、JSP スクリプト要素、およびネストしたカスタム タグをカスタム タグの本文に組み込むことができます。カスタム タグで本文コンテンツと対話しない場合は、TagSupport クラスを拡張し、doStartTag メソッドで EVAL_BODY_INCLUDE を返します。一方、カスタム タグで本文コンテンツの処理、ループ、または変更が必要な場合は、doInitBody メソッドと doAfterBody メソッドがある BodyTagSupport クラスを拡張します。


メモ

TLD ファイル内でカスタム タグの bodycontent 要素に empty を指定すると、本文 コンテンツを無効にできます。タグ ハンドラでは、doStartTag メソッドで SKIP_BODY を返すことによって、本文コンテンツを無視できます。


BodyContent オブジェクトは、JspWriter のサブクラスです (JspWriter は、JSP の out 変数のために内部的に使用されるライターです)。BodyContent オブジェクトは、doInitBodydoAfterBody、およびdoEndTagbodyContent 変数によって使用できます。BodyContent オブジェクトと bodyContent 変数は、大文字の使用法が違う点に注意してください。オブジェクトの内容は、doEndTag メソッドで元の JspWriter と統合できます。BodyContent オブジェクトには、出力を書き出すために使用するメソッドのほかに、このオブジェクトの内容の読み取り、クリア、および取り出しを行うメソッドが含まれています。たとえば、bodyContent.getString を使用すると、ライターの内容を取り出せるほか、必要があれば、その内容を元の JspWriter と統合する前に変更できます。


メモ

bodyContent 変数を使用する前に、ヌルでないことを確認してください。


doAfterBody メソッドが EVAL_BODY_TAG を返した場合、JRun は本文の先頭に戻って再実行します。これは、一覧やデータベースの結果セットなどの反復データ全体を繰り返し処理する上で強力な機能です。

単純な例

次の例は、doInitBody メソッドと doAfterBody メソッドの簡単な使用法を示したものです。bodyContent の出力を出力ストリームに統合する方法も示されています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class TestBody extends BodyTagSupport {

public int doStartTag() throws JspException {
  try {
    pageContext.getOut().print("<h2>We're in doStartTag()</h2>");
    return EVAL_BODY_TAG;
  } 
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
}

public void doInitBody() throws JspException {
  try {  
    // これは、doStartTag や doEndTag のライターとは違うことに
    // 注意してください。
    bodyContent.print("<h2>We're in doInitBody()</h2>");
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}

public int doAfterBody() throws JspException {
  try {
    // これは、doStartTag や doEndTag のライターとは違うことに
    // 注意してください。
    bodyContent.print("<h2>We're in doAfterBody()</h2>");
    // return EVAL_BODY_TAG;  // これを使用してループします。
    return SKIP_BODY;
  }
  catch(IOException ioe) {
     throw new JspException(ioe.getMessage());
  } 
}

public int doEndTag() throws JspException {
  try {  
    // bodyContent ライターから元のライターに書き込みます。
    pageContext.getOut().print(bodyContent.getString());
    //// バッファが大きい場合は、前の行よりも
    //// 次のコードの方がより効率的です。
    //// 元の (囲んでいる) ライターを取得します。
    // JspWriter jOut = bodyContent.getEnclosingWriter();
    //// 前のライターに本文の出力を追加します。
    //bodyContent.writeOut(jOut);

    // ここで元のライターに戻ります。
    pageContext.getOut().print("<h2>We're in doEndTag()</h2>");
    return EVAL_PAGE;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}
}

ループの例

doAfterBodyEVAL_BODY_TAG を返すようにコーディングすることによって、カスタム タグの本文を繰り返し実行するループを作成できます。


メモ

カスタム タグとループで使用されるスクリプト変数のスコープは、TEI クラスによって 制御できます。詳細については、"TEI クラスのコーディング"を参照してください。


次の例では、Enumeration タイプの属性を受け入れて、Enumeration オブジェクト内のそれぞれの名前と値 (この例では HTTP ヘッダ) をループによって処理します。

import java.util.Enumeration;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class TestBodyLoopHeaders extends BodyTagSupport {

  Enumeration thisEnum;

public void setThisEnum(Enumeration passedEnum) {
  this.thisEnum = passedEnum;
}

public int doStartTag() throws JspException {
  return EVAL_BODY_TAG;
}

public void doInitBody() throws JspException {
  if (thisEnum.hasMoreElements()) {
    pageContext.setAttribute("nextElement", thisEnum.nextElement());
  }
}

public int doAfterBody() throws JspException {
  if (thisEnum.hasMoreElements()) {
    pageContext.setAttribute("nextElement", thisEnum.nextElement());
    return EVAL_BODY_TAG;  // ループ
  }else {
    return SKIP_BODY;
  }
}

public int doEndTag() throws JspException {
  try {  
    // bodyContent ライターから元のライターに書き込みます。
    pageContext.getOut().print(bodyContent.getString());
    return EVAL_PAGE;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}
}

次の JSP の例では、上記のタグ ハンドラを呼び出しています。

<html>
<body>

<%@ taglib prefix="test" uri="DocSamples.tld" %>
<h1>Looping through Headers</h1>
<table border="1">
<tr>
  <th>Name</th>
  <th>Value</th>
</tr>
<test:enumloop thisEnum="<%= request.getHeaderNames() %>">
  <tr>
    <% String header = 
(String)pageContext.getAttribute("nextElement");%>
  <td><%= header %></td>  
  <td><%= request.getHeader(header) %></td>  
  </tr>
</test:enumloop>
</table>

</body>
</html>

ネストしたタグ ハンドラのコーディング

Tag インターフェイスと BodyTag インターフェイスのどちらを実装しているかにかかわらず、カスタム タグをネストできます。タグをネストさせると、ネストしたタグに関するタグ ハンドラでは、findAncestorWithClass メソッドによって親クラスへの参照を取得できます。ネストしたタグ ハンドラでは、この参照を親クラスにタイプ変換することによって、親クラス内のメソッドを呼び出せます。たとえば、親クラスに実装されているメソッドを利用して、ネストしたタグ ハンドラで出力ストリームを書き出せます。

次のコードは、親タグに関するサンプル タグ ハンドラを示したものです。このサンプルには、ネストしたタグに関するタグ ハンドラで出力ストリームを更新するときに呼び出せるメソッドが含まれています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class TestBodyParent extends TagSupport
{
  String name;

public void setName(String name) {
  this.name = name;
}

public int doStartTag() throws JspException {
  try {
    // 親の名前を表示することから始めます。
    pageContext.getOut().print("<h1>Parent:" + name + "</h1>");
    return EVAL_BODY_INCLUDE;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
}

public int doEndTag() throws JspException {
  try {  
    // グループの後にルーラーを追加します。
    pageContext.getOut().print("<hr>");
    return EVAL_PAGE;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}

public void setNestedName(String name) throws JspException {
  try {  
    // ネストされている名前を表示します。
    pageContext.getOut().print("<p>Nested:" + name);
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
}
}

次のコードは、ネストしたタグに関するサンプル タグ ハンドラを示したものです。このサンプルでは、親のタグ ハンドラのメソッドを呼び出して、出力ストリームを更新しています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class TestBodyNest extends TagSupport {
  private String name;
  private TestBodyParent parent = null;
public void setName(String name) {
  this.name = name;
}

public int doStartTag() throws JspException {
  // 親への参照を検索して保存します。
  Tag t = findAncestorWithClass(this, TestBodyParent.class);
  if (t == null) {
    throw new JspException("TestBodyNest must be in TestBodyParent.");
  }else {
    parent = (TestBodyParent)t;
    return EVAL_BODY_INCLUDE;
  } 
}

public int doEndTag() throws JspException {
  // 名前を親にコピーします。
  parent.setNestedName(name);
  return EVAL_PAGE;
}
}

次の JSP の例では、親タグとネストしたタグを使用しています。

<html>
<body>

<%@ taglib prefix="test" uri="DocSamples.tld" %>
<h1>Testing Nested Custom Tags</h1>

<test:bodyparent name="Johnson">
  <test:bodynest name="Lorna"/>
  <test:bodynest name="Gretchen"/>
  <test:bodynest name="Brian"/>
</test:bodyparent>

</body>
</html>

タグを使用したスクリプト変数の作成

カスタム タグでは、スクリプト変数を定義できます。スクリプト変数は、JSP 内のスクリプトレットやほかのカスタム タグで使用できます。


メモ

スクリプト変数の定義ではタグ属性 (ID 属性など) を使用できますが、タグ属性と スクリプト変数には直接の関係はないことに注意してください。


TEI クラスのコーディング

JRun は、変換時に TEI クラスを使用してスクリプト変数を有効にするとともに、必要に応じて属性の検証を実行します。TEI ファイルは、TagExtraInfo クラスを拡張する Java クラスです。getVariableInfo メソッドには、次のシグネチャがあります。

public VariableInfo[] getVariableInfo(TagData tagData) { }

tagData パラメータには、属性の名前/値ペアが格納されています。この名前/値ペアを使用してスクリプト変数を定義できます。たとえば、useBean タグでは、id 属性を使用してスクリプト変数を作成しています。

getVariableInfo メソッドで、VariableInfo オブジェクトの配列を作成し、1 つのスクリプト変数につき 1 つの VariableInfo オブジェクトをその配列に格納します。VariableInfo オブジェクトのコンストラクタには、次のパラメータがあります。

同期化とは、ページ コンテキストからオブジェクトを取り出して、それをスクリプト変数に代入する操作です。次の表では、getVariableInfo メソッドで指定した変数に関するスコープ、使用法、および同期化について説明しています。
スコープ
JSP での
使用法
JSP との同期化
タグ ハンドラによって設定
およびリセットされる場所
AT_BEGIN
タグの本文内と、JSP の残りの部分
このスクリプト変数は、本文の反復のたびに
リセットされます。
doInitBodydoAfterBody
(BodyTag を実装している場合)。
それ以外の場合は、doStartTag
または doEndTag
NESTED
タグの
本文内
このスクリプト変数は、本文の反復のたびに
リセットされます。
doInitBodydoAfterBody
(BodyTag を実装している場合)。
それ以外の場合は、doStartTag。
AT_END
JSP の
残りの部分
この変数は、本文の実行が完了した後でリセットされます。
doEndTag の後

次の例では、3 つのスクリプト変数を定義する TEI クラスに関する Java コードを示します。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class HelloTEI extends TagExtraInfo
{
public VariableInfo[] getVariableInfo(TagData tagData) {
  VariableInfo[] vars = new VariableInfo[3];

  // ページの本文と残りの部分の中で使用できます。
  vars[0] = new VariableInfo("foo", "java.lang.String", false, 
variableInfo.AT_BEGIN);
  // ページの残りの部分のカスタム タグの後ろで使用できます。
  vars[1] = new VariableInfo("bar", "java.lang.String", true, 
VariableInfo.AT_END);
  // タグ本文でのみ使用できます。
  vars[2] = new VariableInfo("baz", "java.lang.String", true, 
VariableInfo.NESTED);
  return vars;
}
}

タグ ハンドラでのスクリプト変数の有効化

スクリプト変数を pageContext オブジェクトに追加するのは、タグ ハンドラの役割です。タグ ハンドラでは、スクリプト変数に指定されているスコープに応じて、これらの変数をさまざまな方法で定義します。さらに、本文テキストをループ処理するタグ ハンドラでは、doAfterBody メソッドによって、スクリプト変数を更新またはリセットできます。

次の例は、タグ ハンドラでスクリプト変数を設定する方法を示したものです。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class HelloTag extends BodyTagSupport {
  String to;

public void setTo(String to) {
  this.to = to;
}

public int doStartTag() throws JspException {
  try {
    pageContext.getOut().print("Hello " + to);

    // TEI ファイルによってこのスクリプト変数が
    // AT_BEGIN として定義されるので、ここで定義します。 
    // それを doInitBody 内で定義し (ループの場合)、
    // doAfterBody 内で変更またはリセットできます。
    pageContext.setAttribute("foo", "foo");
    return EVAL_BODY_TAG;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  }
}

public void doInitBody() throws JspException {
  // TEI ファイルによってこのスクリプト変数が
  // NESTED として定義されるので、ここで定義します。 
  // それを doStartTag 内で定義し (ループの場合)、
  // doAfterBody 内で変更またはリセットできます。
  pageContext.setAttribute("baz", "baz");
}

public int doEndTag() throws JspException {
  try {
    // このタグ ハンドラによって BodyTag が実装されるので 
    // (BodyTagSupport を展開することによって)、
    //  本文のライターと元のライターを統合する必要があります。
    pageContext.getOut().print(bodyContent.getString());

    // TEI ファイルによってこのスクリプト変数が
    // AT_END として定義されるので、
    // doEndTag まで自分で定義する必要はありません。
    pageContext.setAttribute("bar", "bar");
    return EVAL_PAGE;
  }
  catch(IOException ioe) {
    throw new JspException(ioe.getMessage());
  } 
}
}

JSP でのスクリプト変数の使用法

次の JSP の例では、前出の TEI クラスおよびタグ ハンドラで定義したスクリプト変数を使用しています。

<%@ taglib prefix="test" uri="test.tld" %>
<% String foo; %>

<test:hello to="World">
  <%-- baz は NESTED です (本文でのみ使用可能)。--%>
  <%= baz %>
  <%-- foo は AT_BEGIN です (本文とそれ以外でも使用可能)。--%>
  <%= foo %>
</test:hello>
<%= foo %>
<%-- bar は AT_END です (本文の後ろでのみ使用可能)。--%>
<%= bar %>

isValid メソッドの使用法

TEI クラスでは、isValid メソッドを書き換えてタグ特有の属性の検証を実施できます。変換時には、JRun から isValid メソッドに TagData インスタンスが渡されます。

isValid メソッドでは、TagData.getAttribute を呼び出して、この値にアクセスできます。TLD ファイル内の属性の定義で実行時式を有効にしている場合は、
TagData.REQUEST_TIME_VALUE オブジェクトをチェックできます。このオブジェクトは、カスタム タグの呼び出しが実行時式を使用していることと、検証が不可能であることを示します。実行時式の詳細については、"TLD ファイルでの属性の定義"を参照してください。

次の例の TEI ファイルでは、バージョン属性の値が 5 より小さいことを確認しています。

import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.io.IOException;

public class TestIsValidTEI extends TagExtraInfo
{
  // この例では、スクリプト変数が 1 つのみであると想定しています 
  // (この例とは無関係に)。
public VariableInfo[] getVariableInfo(TagData tagData) {
  VariableInfo[] vars = new VariableInfo[1];
  vars[0] = new VariableInfo("foo", "java.lang.String", true, 
VariableInfo.AT_BEGIN);
  return vars;
}

public boolean isValid(TagData data) {
  Object version = data.getAttribute("version");
  // この属性により、実行時式が使用できるので、
  // REQUEST_TIME_VALUE をチェックする必要があります。
  if (version != null && version != TagData.REQUEST_TIME_VALUE) {
    int iVersion = Integer.parseInt((String)version);
    // バージョンは 5 以下になります。
    if (iVersion > 5) {
      return false;
    }else {
      return true;
    }
  }else {
    return false;
  }
}
}