AJAXカレンダー見直し

前に書いたAJAXカレンダー、年、月の表示をオーバーライドメソッドで自由にした方が良いと思った。

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxEventBehavior;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.AbstractReadOnlyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
/**
 * 月移動リンク付きカレンダー.
 */
public class CalendarPanel extends Panel{
   private IModel<Date> targetDateModel;
   private SimpleDateFormat formatYMD
   = new SimpleDateFormat(CalendarRequest.CALENDAR_PARAM_FORMAT);
   private IModel<CalendarRequest> reqModel;
   public CalendarPanel(String id,final IModel<CalendarRequest> model){
      super(id,model);
      this.reqModel = model;
      final CalenderHelper helper = new CalenderHelper(getRequestCycle());
      final Calendar cal = Calendar.getInstance();
      final CalendarRequest req = model.getObject();
      cal.setTime(req.getDate());
      cal.set(Calendar.DAY_OF_MONTH,1);
      this.targetDateModel = new Model<Date>(cal.getTime());
      // table  tbody
      final WebMarkupContainer tbody = new WebMarkupContainer("tbody");
      tbody.setOutputMarkupId(true);
      final ListView<String> daylist = createListView(req);
      daylist.setOutputMarkupId(true);
      tbody.add(daylist);
      add(tbody);
      // 年 & 月 の表示
      final Label titleComponent = new Label("title",new AbstractReadOnlyModel<String>(){
         @Override
         public String getObject(){
            return title(getTargetDateModel());
         }
      });
      titleComponent.setOutputMarkupId(true);
      add(titleComponent);


      // 前月&翌月リンク
      add(new WebMarkupContainer("prev").add(new AjaxEventBehavior("onclick"){
         @Override
         protected void onEvent(AjaxRequestTarget target){
            setTargetDateModelDate(helper.prevDate(getTargetDateModel()));
            CalendarRequest calendarRequest = getReqModel().getObject();
            calendarRequest.setDate(getTargetDateModelDate());
            tbody.remove("calendar_days");
            tbody.add(createListView(calendarRequest));
            target.addComponent(tbody);
            target.addComponent(titleComponent);
         }
      }));
      add(new WebMarkupContainer("next").add(new AjaxEventBehavior("onclick"){
         @Override
         protected void onEvent(AjaxRequestTarget target){
            setTargetDateModelDate(helper.nextDate(getTargetDateModel()));
            CalendarRequest calendarRequest = getReqModel().getObject();
            calendarRequest.setDate(getTargetDateModelDate());
            tbody.remove("calendar_days");
            tbody.add(createListView(calendarRequest));
            target.addComponent(tbody);
            target.addComponent(titleComponent);
         }
      }));
   }
   /**
    * タイトル表示文字列の決定.
    * オーバーライド可能
    * @param model 表示対象年月の日付のIModel
    * @return <span wicket:id="title"></span> に置換される
    */
   public String title(final IModel<Date> model){
      Calendar c = Calendar.getInstance();
      c.setTime(model.getObject());
      return Integer.toString(c.get(Calendar.YEAR))
+" 年 "+Integer.toString(c.get(Calendar.MONTH)+1)+" 月";

   }


   protected ListView<String
> createListView(final CalendarRequest req){
      final String wds = {"sun","mon","tue","wed","thu","fri","sat"};
      final Calendar cal = Calendar.getInstance();
      final Calendar calx = Calendar.getInstance();
      cal.setTime(req.getDate());
      cal.set(Calendar.DAY_OF_MONTH,1);
      this.targetDateModel = new Model<Date>(cal.getTime());
      calx.setTime(cal.getTime());
      return  new ListView<String
>("calendar_days",calendarList(req.getDate()," ")){
         @Override
         protected void populateItem(ListItem<String> item){
            final String
 days = item.getModelObject();
            for(int i=0; i < 7; i++){
               final int index = i;
               item.add(new BookmarkablePageLink<String>(
wds[i],req.getLinkClass(),makeParameter(cal.getTime()
,req.getPageParameters(),req.getDateParameterName())){
                  @Override
                  public boolean isEnabled(){
                     if (days[index].equals(" ")) return false;
                        calx.set(Calendar.DAY_OF_MONTH,Integer.parseInt(days[index]));
                        return req.enable(calx.getTime());
                     }
                  }.add(new Label(wds[i]+"_day",days[i]).setEscapeModelStrings(false)
               ));
               if (!days[i].equals(" ")) cal.add(Calendar.DAY_OF_MONTH,1);
            }
         }
      };
   }

   private List<String> calendarList(Date date,String blank){
      Calendar c = Calendar.getInstance();
      c.setTime(date);
      c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),1);
      int firstWeek = c.get(Calendar.DAY_OF_WEEK);
      c.add(Calendar.MONTH, 1);
      c.set(c.get(Calendar.YEAR),c.get(Calendar.MONTH),1);
      c.add(Calendar.DAY_OF_MONTH, - c.get(Calendar.DAY_OF_MONTH));
      int endday = c.get(Calendar.DAY_OF_MONTH);
      List<String
> list = new ArrayList<String>();
      int day = 1;
      int week = 0;
      String
 s = new String[7];
      int o = firstWeek - 1;
      for(;week < o;week++){
         s[week] = blank;
      }
      for(int d=day;d <= endday;d++){
         if (week==7){
            list.add(s);
            s = new String[7];
            week = 0;
         }
         s[week] = Integer.toString(d);
         week++;
      }
      for(;week < 7;week++){
         s[week] = blank;
      }
      list.add(s);
      return list;
   }
   // 日付リンクのパラメータ
   protected PageParameters makeParameter(Date ndt,PageParameters p,String key){
      p.put(key,this.formatYMD.format(ndt));
      return p;
   }

   protected void setTargetDateModelDate(Date dt){
      this.targetDateModel.setObject(dt);
   }
   protected Date getTargetDateModelDate(){
      return this.targetDateModel.getObject();
   }
   protected IModel<Date> getTargetDateModel(){
      return this.targetDateModel;
   }

   protected IModel<CalendarRequest> getReqModel(){
      return this.reqModel;
   }
   protected void setReqModel(IModel<CalendarRequest> reqModel){
      this.reqModel = reqModel;
   }
}


CalendarPanel.html は、以下のとおり。。
<wicket:panel>
<table class="calendar">
<tr><td><a wicket:id="prev" class="calendar" href="#"><</a></td>
<td colspan="5"><span wicket:id="title"></span></td><td><a wicket:id="next" class="calendar" href="#">></a></td>
</tr>
<tr class="head"><th class="sun">日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th class="sat">土</th></tr>
<tbody wicket:id="tbody">
<tr wicket:id="calendar_days" class="days">
<td><a wicket:id="sun" class="calendar"><span wicket:id="sun_day" class="calendar">1</span></a></td>
<td><a wicket:id="mon" class="calendar"><span wicket:id="mon_day" class="calendar">1</span></a></td>
<td><a wicket:id="tue" class="calendar"><span wicket:id="tue_day" class="calendar">1</span></a></td>
<td><a wicket:id="wed" class="calendar"><span wicket:id="wed_day" class="calendar">1</span></a></td>
<td><a wicket:id="thu" class="calendar"><span wicket:id="thu_day" class="calendar">1</span></a></td>
<td><a wicket:id="fri" class="calendar"><span wicket:id="fri_day" class="calendar">1</span></a></td>
<td><a wicket:id="sat" class="calendar"><span wicket:id="sat_day" class="calendar">1</span></a></td>
</tr>
</tbody>
</table>
</wicket:panel>
呼び出しもこんなに簡単にできる。

add(new CalendarPanel("calendar",new Model<CalendarRequest>(
      new CalendarRequestImpl(helper.getTargetDate(),FooPage.class,new PageParameters())
)){
   @Override
   public String title(IModel<Date> model){
      Calendar c = Calendar.getInstance();
      c.setTime(model.getObject());
      return Integer.toString(c.get(Calendar.YEAR))
+" - "+Integer.toString(c.get(Calendar.MONTH)+1);
   }

});