谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

複数フィールドカレンダーバリデータ

おまけ。
複数のフィールドで、日付を入力したいとかって言う
よくある 面倒な 要望に対応するためのバリデータ。

package examples.jsf.validator;

import java.util.Calendar;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;

import org.seasar.jsf.util.MessageUtil;
import org.seasar.jsf.util.UIComponentUtil;

/**
 * @author cero-t
 * 
 */
public class S2MultiFieldCalendarValidator extends
		S2MultiSubmittedValueValidator {

	public static final String ARGS_MESSAGE_ID = "examples.jsf.validator.S2MultiFieldCalendarValidator.ARGS";

	public static final String LENIENT_MESSAGE_ID = "examples.jsf.validator.S2MultiFieldCalendarValidator.LENIENT";

	protected void doValidate(FacesContext context, UIComponent component,
			Object value, UIComponent[] targetComponents, Object[] targetValues)
			throws ValidatorException {

		if (targetValues == null) {
			return;
		}

		if (targetValues.length < 2) {
			Object[] args = { UIComponentUtil.getLabel(component) };
			throw new ValidatorException(MessageUtil.getErrorMessage(
					ARGS_MESSAGE_ID, args));
		}

		Calendar calendar = Calendar.getInstance();
		calendar.setLenient(false);
		calendar.set(Calendar.YEAR, getAsInt(targetValues[0]));
		calendar.set(Calendar.MONTH, getAsInt(targetValues[1]) - 1);
		calendar.set(Calendar.DATE, getAsInt(targetValues[2]));

		try {
			calendar.getTime();
		} catch (IllegalArgumentException ex) {
			Object[] args = { UIComponentUtil.getLabel(component) };
			FacesMessage message = MessageUtil.getErrorMessage(
					LENIENT_MESSAGE_ID, args);
			throw new ValidatorException(message);
		}
	}

	private int getAsInt(Object o) {
		if (o == null) {
			return 0;
		}

		if (o instanceof Integer) {
			return ((Integer) o).intValue();
		}

		return Integer.parseInt(o.toString());
	}
}


HTMLは、こんな感じ。
diconは省略。

<select id="year" m:value="#{userInfoDto.birthdayYear}" m:label="生年月日">
  <span m:inject="s:validator"
    m:binding="#{multiFieldCalendarValidator}"
    m:targetId="year,month,day"/>
  <option value="1974">1974</option>
  <option value="1975">1975</option>
  <option value="1976">1976</option>
  <option value="1977">1977</option>
  <option value="1978">1978</option>
  <option value="1979">1979</option>
  <option value="1980">1980</option>
  <option value="1981">1981</option>
  <option value="1982">1982</option>
</select>年
<select id="month" m:value="#{userInfoDto.birthdayMonth}">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="6">6</option>
  <option value="7">7</option>
  <option value="8">8</option>
  <option value="9">9</option>
  <option value="10">10</option>
  <option value="11">11</option>
  <option value="12">12</option>
</select>月
<select id="day" m:value="#{userInfoDto.birthdayDay}">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
  <option value="29">29</option>
  <option value="30">30</option>
  <option value="31">31</option>
</select>日
<span m:inject="h:message" m:for="year"/>

MultiSubmittedValueValidatorを継承しているので、
HTML上では、年にValidatorを掛けても正常動作します。


MultiFieldValidatorを継承するように変更しても
(ソースの他の部分を変更せずに)そのまま使えるけど、
HTML上では、日にValidatorを掛けなきゃいけません。