SAStruts + Velocity (2)

SAStruts + Velocity が動くことが確認出来たので、今度はSAStruts
チュートリアルに含まれるサンプルをVelocityに移植中です。

そこで、移植にちょっと手間取ったサンプルがありました。

「複数選択リスト」サンプルにて

「複数選択リスト」サンプルのJSPファイルは以下のようになっています。

multiselect.jsp
<html>
<head>
<title>Multiselect</title>
</head>
<body>
<html:errors/>
<s:form action="/multiselect">
<html:select property="select" multiple="true" size="3">
<html:option value="1">One</html:option>
<html:option value="2">Two</html:option>
<html:option value="3">Three</html:option>
</html:select>
<br />
${f:h(select)}<br />
<input type="submit" name="submit" value="サブミット"/>
</s:form>
</body>
</html>

まず、toolbox.xml に ListTool の定義を追加します。

toolbox.xml
 <tool>
   <key>list</key>
   <scope>application</scope>
   <class>org.apache.velocity.tools.generic.ListTool</class>
 </tool>

そして、multiselect.jspを元に、vmファイルを以下のように作成しました。

multiselect.vm
<html>
<head>
<title>Multiselect</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form name="multiselectActionForm" method="post" action="$link.setRelative("velocity/multiselect/")">
<select name="select" multiple="multiple" size="3">
<option value="1"#if($list.contains($select, "1")) selected="selected" #end>One</option>
<option value="2"#if($list.contains($select, "2")) selected="selected" #end>Two</option>
<option value="3"#if($list.contains($select, "3")) selected="selected" #end>Three</option>
</select>
<br />
$!escape.html($!select)<br />
<input type="submit" name="submit" value="サブミット"/>
</form>
</body>
</html>

すると、以下のようなエラーが発生しました。*1

nvocation of method 'contains' in class org.seasar.struts.action.ArrayWrapper threw exception class java.lang.UnsupportedOperationException : contains

何でだろうと思い、ArrayWrapper#contains(Object)の実装を見てみたら、以下のようになっていました。

    public boolean contains(Object o) {
        throw new UnsupportedOperationException("contains");
    }

これが原因です。
どうしようかな…、ArrayWrapper#toArray()はサポートされていたので以下のように修正してみました。

修正後の multiselect.vm
<html>
<head>
<title>Multiselect</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form name="multiselectActionForm" method="post" action="$link.setRelative("velocity/multiselect/")">
<select name="select" multiple="multiple" size="3">
<option value="1"#if($list.contains($select.toArray(), "1")) selected="selected" #end>One</option>
<option value="2"#if($list.contains($select.toArray(), "2")) selected="selected" #end>Two</option>
<option value="3"#if($list.contains($select.toArray(), "3")) selected="selected" #end>Three</option>
</select>
<br />
$!escape.html($!select)<br />
<input type="submit" name="submit" value="サブミット"/>
</form>
</body>
</html>

不恰好なコードですが、とりあえず動きました。
もっとスマートな方法は無いのでしょうか?

*1:SAStruts1.0.2-rc3 では、ArrayWrapper#contains(Object) がサポートされる予定になっています