-ループ

ループのあたりも含め、ひとまずサーバサイドのコードを書きおえ。Tapestryみたいに二度書きもしないし、サーバサイドでJSF風にループ毎にモデルを増やさない。JSPのELでも透過的にアクセスできる。。。結構いいかもしんない。やってることは、一意に特定できるモデルのパス文字列を作りこむことです。

@PageModel(ModelScope.APPLICATION)
public interface TaskModel {
  void setTask(List<Task> task);
  List<Task> getTask();
}
@PageModel(ModelScope.INTERNAL)
public interface Task  {
  void setDescription(String description);
  @DateConverter("yyyy/MM/dd")
  @ErrorMessageTo("dateFormatError")
  void setRegistDate(Date registDate);
  String getDateFormatError();
}

こんな、単純なリストを持つモデルを用意して、以下がJSP

<%@page contentType="text/html; charset=UTF-8"%>
<%@taglib prefix="ik" uri="http://ikushipe.ashikunep.org/core"%>
<html>
  <body>
    <ik:form>
      <ik:loop property="task">
        <ik:input property="task.registDate"/>
        <ik:input property="task.description"/>
        <ik:submit event="upTo" caption="up"/>
        <ik:submit event="downTo" caption="down"/><br>
      </ik:loop>
    </ik:form>
  </body>
</html>

これが、

<html>
  <body>
    <form action="/context/task/TaskPage">
        <input type="text" name="task[0].registDate"/>
        <input type="text" name="task[0].description"/>
        <input type="submit" name="upTo/task[0]" value="up"/>
        <input type="submit" name="downTo/task[0]" value="down"/><br>
        <input type="text" name="task[1].registDate"/>
        <input type="text" name="task[1].description"/>
        <input type="submit" name="upTo/task[1]" value="up"/>
        <input type="submit" name="downTo/task[1]" value="down"/><br>
        <input type="text" name="task[2].registDate"/>
        <input type="text" name="task[2].description"/>
        <input type="submit" name="upTo/task[2]" value="up"/>
        <input type="submit" name="downTo/task[2]" value="down"/><br>
    </form>
  </body>
</html>

を出すイメージ。まだ理論値なんだけど。"task[2].description"は、EL式で${task[2].description}でアクセスできるようにしています。HttpServletRequestWrapperでモデルプロパティをリクエストスコープのもののようにアクセスできる裏口も用意したためです。
サブミットされると、"upTo/task[1]=up"というようなリクエストパラメータの名前と値のセットが飛んできます。これはupToというハンドラメソッドが要求されていて、taskがループしてインデックス値が1ですよ、と知ることができる。受け止める描画ページには、以下のハンドラがあります。

@WebPage(TaskModel.class)
public class TaskPage {
  @LoopName("task")
  public Class<?> upTo(int index, TaskModel model) {
    if(index > 0) {
      List<Task> taskList = model.getTask();
      Task task = taskList.remove(index);
      taskList.add(index -1, task);
    }
    return null;
  }
  @LoopName("task")
  public Class<?> downTo(int index, TaskModel model) {
    List<Task> taskList = model.getTask();
      if(taskList.size() -1 > index) {
        Task task = taskList.remove(index);
        taskList.add(index + 1, task);
      }
      return null;
  }
}

引数には状況に応じて、あたかもDIのようにフレームワークが値をセットしてくれます。このハンドラはnullを返しているので遷移しませんが、ページのクラス型を返すとそのページを示すURLにリダイレクトして、結果、遷移します。